JavaScript - Способы подписки на события. JavaScript - Способы подписки на события Использование атрибута HTML
У вас есть следующий прослушиватель для клавиатуры ArrowDown event (it key code is 40):
Window.onload = function() { var itemsContainer = document.getElementById("cities-drop"); document.addEventListener("*****",function(event){ if (event.keyCode == 40 && itemsContainer.style.display=="block") { event.preventDefault(); for (var i=0;i
в этом случае hovering переходит к последнему элементу в списке, после нажатия ArrowDown .
В случае, если break раскоментирован, он переходит ко второму элементу и больше не прыгает.
Невозможно получить принцип, как это сделать, что слушатель всегда слушает...
ИЗМЕНИТЬ живая демонстрация возможно, это вопрос закрытия, но я не уверен, что
3 ответа
Посмотрев на свой код и понимая, что вы пытаетесь сделать, я думаю, что ваша ошибка использует substr , где вы должны использовать indexOf . Вот обновленная строка:
If (itemsContainer.getAttribute("class").indexOf("hovered") != -1) Подробнее: Фактически вы использовали substr со строковым значением для индекса start . Не уверен, каков был бы результат этого, но, по-видимому, это не -1, поскольку условие возвращалось true каждый раз, заставляя следующий элемент зависеть КАЖДОЕ время, вплоть до нижней части списка. С помощью инструкции break в ней выполнялся оператор if в первом элементе (заставляя второй элемент "зависать"), а затем завершался.
Я оставил бы инструкцию break там, после исправления вашего кода, так что цикл остановится после того, как он найдет его совпадение, и не будет излишне перебирать остальные элементы.
EDIT:Я нашел еще пару проблем в коде. Вот пример, который работает для меня в IE и FF, по крайней мере (не тестировался в Safari, Opera или Chrome):
Подробно: Для меня в IE9 функция никогда не вызывалась. Вместо этого я просто сделал его регулярной функцией и добавил событие onkeydown в тег body .
В вашем if-statement у вас есть itemsContainer.getAttribute("class") . Во-первых, вам нужно использовать itemsContainer.children[i] . Во-вторых, .getAttribute("class") не работал у меня в IE, поэтому я переключил его только на.className .
Наконец, itemsContainer.children[i].nextSibling не работал у меня, но он достаточно прост, чтобы просто изменить его на itemsContainer.children , чтобы получить следующего брата.
Вместо использования цикла вы можете попробовать более простой подход:
Window.onload = function() { var itemsContainer = document.getElementById("cities-drop"); document.addEventListener("*****",function(event) { if (event.keyCode == 40 && itemsContainer.style.display=="block") { event.preventDefault(); var previousHoveredChoice = itemsContainer.querySelector(".hovered"); previousHoveredChoice.className = ""; var currentHoveredChoice = previousHoveredChoice.nextSibling; if (currentHoveredChoice) { currentHoveredChoice.className = "hovered"; } } }); //following code is copy-pasted from the live example //just to close the onload function handler in this solution document.addEventListener("*****",function(event){ if (event.keyCode == 27) { if (document.getElementById("cities-drop").style.display=="block"){ document.getElementById("cities-drop").style.display="none"; } } }); //end of copy-pasted code };
Есть несколько вещей, которые я вижу, что может быть проблемой. Прежде всего, вы обновляете itemsContainer.children[i].nextSibling , который равен itemsContainer.children . Поэтому всегда выбирается последний элемент, если вы пропустите перерыв. itemsComtainer всегда будет зависать, если есть элемент, соответствующий классу.
Вторая проблема - это то, что Travesty3 указывает на его ответ.
Я также изменил условие if, чтобы проверить, находится ли зависавший класс на одном из дочерних элементов, а не на самом контейнере.
If (itemsContainer.children[i].getAttribute("class").match("hovered"))
Я изменил обработчик событий со следующими строками кода, и это, кажется, отлично работает:
Document.addEventListener("*****",function(event){ if (event.keyCode === 40 && itemsContainer.style.display==="block") { event.preventDefault(); for (var i=0,l=itemsContainer.children.length;i
Имейте в виду, что создание такого понижающего контроля - это довольно много работы. Пользователь ожидает навигации по ней с помощью клавиатуры. Чтобы создать отличный пользовательский интерфейс, вы должны обрабатывать несколько клавиш, таких как клавиши со стрелками, вкладку, чтобы сфокусировать управление, пространство для его открытия и закрытия, буквенно-цифровой ввод для фокусировки на первом совпадающем элементе и т.д.
Если пользовательский опыт важен, я бы рекомендовал использовать для этого фреймворк и плагин. Я лично предпочитаю jquery и jquery ui, и есть несколько плагинов для выбора drop downs. Еще одно преимущество заключается в том, что если javascript отключен клиентом или ваш javascript будет ошибочным по какой-то причине, большинство плагинов возвращаются к обычному собственному элементу select, который все равно будет работать нормально.
Я сам использовал этот плагин для selectbox для простого выпадающего списка: http://www.abeautifulsite.net/blog/2011/01/jquery-selectbox-plugin/
Изменить: Я отменяю эту рекомендацию, так как она не работает, если несколько элементов имеют одинаковое имя. Если это важно, вы должны проверить плагин Filament Group selectmenu: http://filamentgroup.com/lab/jquery_ui_selectmenu_an_aria_accessible_plugin_for_styling_a_html_select/ //Изменить
И плагин автозаполнения jquery для combobox, также поддерживающий письменный ввод: http://jqueryui.com/demos/autocomplete/
Обработка событий
Клиентские программы на языке JavaScript основаны на модели программирования, когда выполнение программы управляется событиями. При таком стиле программирования веб-браузер генерирует событие, когда с документом или некоторым его элементом что-то происходит. Например, веб-браузер генерирует событие, когда завершает загрузку документа, когда пользователь наводит указатель мыши на гиперссылку или нажимает клавишу на клавиатуре.
Если JavaScript-приложение интересует определенный тип события для определенного элемента документа, оно может зарегистрировать одну или более функций, которая будет вызываться при возникновении этого события. Имейте в виду, что это не является уникальной особенностью веб-программирования: все приложения с графическим интерфейсом пользователя действуют именно таким образом - они постоянно ожидают, пока что-то произойдет (т.е. ждут появления событий), и откликаются на происходящее.
Тип события - это строка, определяющая тип действия, вызвавшего событие. Тип «mousemove», например, означает, что пользователь переместил указатель мыши. Тип «keydown» означает, что была нажата клавиша на клавиатуре. А тип «load» означает, что завершилась загрузка документа (или какого-то другого ресурса) из сети. Поскольку тип события - это просто строка, его иногда называют именем события.
Цель события - это объект, в котором возникло событие или с которым это событие связано. Когда говорят о событии, обычно упоминают тип и цель события. Например, событие «load» объекта Window или событие «click» элемента . Самыми типичными целями событий в клиентских приложениях на языке JavaScript являются объекты Window, Document и Element, но некоторые типы событий могут происходить и в других типах объектов.
Обработчик события - это функция, которая обрабатывает, или откликается на событие. Приложения должны зарегистрировать свои функции обработчиков событий в веб-браузере, указав тип события и цель. Когда в указанном целевом объекте возникнет событие указанного типа, браузер вызовет обработчик. Когда обработчики событий вызываются для какого-то объекта, мы иногда говорим, что браузер «возбудил» или «сгенерировал» событие.
Объект события - это объект, связанный с определенным событием и содержащий информацию об этом событии. Объекты событий передаются функции обработчика события в виде аргумента (кроме IE8 и более ранних версий, где объект события доступен только в виде глобальной переменной event). Все объекты событий имеют свойство type , определяющее тип события, и свойство target , определяющее цель события.
Для каждого типа события в связанном объекте события определяется набор свойств. Например, объект, связанный с событиями от мыши, включает координаты указателя мыши, а объект, связанный с событиями от клавиатуры, содержит информацию о нажатой клавише и о нажатых клавишах-модификаторах. Для многих типов событий определяются только стандартные свойства, такие как type и target, и не передается никакой дополнительной полезной информации. Для таких типов событий важно само наличие происшествия события, и никакая другая информация не имеет значения.
Распространение события - это процесс, в ходе которого браузер решает, в каких объектах следует вызвать обработчики событий. В случае событий, предназначенных для единственного объекта (таких как событие «load» объекта Window), надобность в их распространении отсутствует. Однако, когда некоторое событие возникает в элементе документа, оно распространяется, или «всплывает», вверх по дереву документа.
one |
two |
In this code, modifyText() is a listener for click events registered using addEventListener() . A click anywhere in the table bubbles up to the handler and runs modifyText() .
Result Event listener with anonymous functionHere, we"ll take a look at how to use an anonymous function to pass parameters into the event listener.
HTMLone |
two |
Notice that the listener is an anonymous function that encapsulates code that is then, in turn, able to send parameters to the modifyText() function, which is responsible for actually responding to the event.
Result Event listener with an arrow functionThis example demonstrates a simple event listener implemented using arrow function notation.
HTMLone |
two |
Please note that while anonymous and arrow functions are similar, they have different this bindings. While anonymous (and all traditional JavaScript functions) create their own this bindings, arrow functions inherit the this binding of the containing function.
That means that the variables and constants available to the containing function are also available to the event handler when using an arrow function.
Example of options usage HTML outer, once & none-once middle, capture & none-capture inner1, passive & preventDefault(which is not allowed) inner2, none-passive & preventDefault(not open new page) CSS .outer, .middle, .inner1, .inner2 { display:block; width:520px; padding:15px; margin:15px; text-decoration:none; } .outer { border:1px solid red; color:red; } .middle { border:1px solid green; color:green; width:460px; } .inner1, .inner2 { border:1px solid purple; color:purple; width:400px; } JavaScript const outer = document.getElementsByClassName("outer") ; const middle = document.getElementsByClassName("middle"); const inner1 = document.getElementsByClassName("inner1"); const inner2 = document.getElementsByClassName("inner2"); const capture = { capture: true }; const noneCapture = { capture: false }; const once = { once: true }; const noneOnce = { once: false }; const passive = { passive: true }; const nonePassive = { passive: false }; outer.addEventListener("click", onceHandler, once); outer.addEventListener("click", noneOnceHandler, noneOnce); middle.addEventListener("click", captureHandler, capture); middle.addEventListener("click", noneCaptureHandler, noneCapture); inner1.addEventListener("click", passiveHandler, passive); inner2.addEventListener("click", nonePassiveHandler, nonePassive); function onceHandler(event) { alert("outer, once"); } function noneOnceHandler(event) { alert("outer, none-once, default"); } function captureHandler(event) { //event.stopImmediatePropagation(); alert("middle, capture"); } function noneCaptureHandler(event) { alert("middle, none-capture, default"); } function passiveHandler(event) { // Unable to preventDefault inside passive event listener invocation. event.preventDefault(); alert("inner1, passive, open new page"); } function nonePassiveHandler(event) { event.preventDefault(); //event.stopPropagation(); alert("inner2, none-passive, default, not open new page"); } ResultClick the outer, middle, inner containers respectively to see how the options work.
Before using a particular value in the options object, it"s a good idea to ensure that the user"s browser supports it, since these are an addition that not all browsers have supported historically. See for details.
Other notes Why use addEventListener ?addEventListener() is the way to register an event listener as specified in W3C DOM. The benefits are as follows:
- It allows adding more than a single handler for an event. This is particularly useful for AJAX libraries, JavaScript modules, or any other kind of code that needs to work well with other libraries/extensions.
- It gives you finer-grained control of the phase when the listener is activated (capturing vs. bubbling).
- It works on any DOM element, not just HTML elements.
It is often desirable to reference the element on which the event handler was fired, such as when using a generic handler for a set of similar elements.
If attaching a handler function to an element using addEventListener() , the value of this inside the handler is a reference to the element. It is the same as the value of the currentTarget property of the event argument that is passed to the handler.
My_element.addEventListener("click", function (e) { console.log(this.className) // logs the className of my_element console.log(e.currentTarget === this) // logs `true` }) my_element.addEventListener("click", (e) => { console.log(this.className) // WARNING: `this` is not `my_element` console.log(e.currentTarget === this) // logs `false` })
Specifying this using bind()Note: useCapture is not supported, as IE 8 does not have any alternative method. The following code only adds IE 8 support. This IE 8 polyfill only works in standards mode: a doctype declaration is required.
(function() { if (!Event.prototype.preventDefault) { Event.prototype.preventDefault=function() { this.returnValue=false; }; } if (!Event.prototype.stopPropagation) { Event.prototype.stopPropagation=function() { this.cancelBubble=true; }; } if (!Element.prototype.addEventListener) { var eventListeners=; var addEventListener=function(type,listener /*, useCapture (will be ignored) */) { var self=this; var wrapper=function(e) { e.target=e.srcElement; e.currentTarget=self; if (typeof listener.handleEvent != "undefined") { listener.handleEvent(e); } else { listener.call(self,e); } }; if (type=="DOMContentLoaded") { var wrapper2=function(e) { if (document.readyState=="complete") { wrapper(e); } }; document.attachEvent("onreadystatechange",wrapper2); eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper2}); if (document.readyState=="complete") { var e=new Event(); e.srcElement=window; wrapper2(e); } } else { this.attachEvent("on"+type,wrapper); eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper}); } }; var removeEventListener=function(type,listener /*, useCapture (will be ignored) */) { var counter=0; while (counterAlternate Name Uses the non-standard name: attachEvent
Notes
Full support 1Notes
Notes Before Chrome 49, the type and listener parameters were optional.Notes
Full support 18Notes
Notes Before Chrome 49, the type and listener parameters were optional.Приложить событие щелчка на элемента. Когда пользователь нажимает на кнопку, выход "Hello World" в
Элемент с идентификатором = «демо»:
document.getElementById("demo").innerHTML = "Hello World";
});
Больше "Try it Yourself" примеры ниже.
Определение и использованиеaddEventListener() метод придает обработчик события для указанного элемента.
пример
Вы можете добавить много событий к одному элементу, без перезаписи существующих событий.
В этом примере показано, как добавить два события щелчка на одной и той же элемента:
Document.getElementById("myBtn").addEventListener("click",
myFunction);
пример
Вы можете добавлять события различных типов к одному элементу.
Этот пример показывает, как добавить много событий на одной и той же элемента:
Document.getElementById("myBtn").addEventListener("mouseover", myFunction);
document.getElementById("myBtn").addEventListener("click", someOtherFunction);
document.getElementById("myBtn").addEventListener("mouseout", someOtherFunction);
пример
При передаче значений параметров используйте "anonymous function" , которая вызывает указанную функцию с параметрами:
Document.getElementById("myBtn").addEventListener("click", function() {
myFunction(p1, p2);
});
пример
Изменение цвета фона элемента:
Document.getElementById("myBtn").addEventListener("click", function(){
this.style.backgroundColor = "red";
В этой статье мы рассмотрим различные способы, с помощью которых Вы можете подписаться на события элементов веб-страницы. Один из способов основан на использовании атрибутов HTML, два других способа осуществляются через код JavaScript посредством свойства on или метода addEventListener() .
Как подписаться на событие?- Подписаться через код HTML (не рекомендуется использовать).
- Через код JavaScript с помощью задания элементу свойства on[событие] , где [событие] - это имя определённого события.
- Через код JavaScript с помощью специального метода addEventListener .
Данный способ основывается на использовании атрибута, который имеет вид on[событие] , где [событие] - это имя определённого события.
Основные действия: добавить к элементу определённый атрибут (например: onclick - где: on означает событие, а click - вид события) со значением, содержащим оператор или функцию. Данный оператор или функция будет выполняться при наступлении этого события у элемента.
Например, добавить к кнопке событие click , при наступлении которого будет выводиться сообщение с помощью метода alert:
Если в обработчике события надо выполнить некоторый код, то необходимо использовать функцию.
Например, выполним вышеприведённый пример с использованием функции:
//функция, которая будет вызываться при наступлении события click у указанного элемента function myFunction() { alert("Событие click"); }
Например, добавить к кнопке событие click , при наступлении которого выполняется указанная функция:
//функция, которая будет вызываться при наступлении события click у указанного элемента function countElements() { var count = document.getElementsByTagName("*").length; alert("Количество элементов на странице:" + count.toString()); }
Данный вариант подписки на событие использовать не рекомендуется, т.к. он не только загромождает код HTML, но и имеет ограничения связанные с использованием объекта event , ключевого слово this и др.
Этот способ подписки на событие осуществляется через код JavaScript с помощью задания элементу свойства on[событие] . Основной принцип данного метода заключается в следующем:
on[событие] , где [событие] - это имя определённого события.
После этого необходимо данному свойству присвоить обработчик, т.е. безымянную или некоторую указанную функцию, которая будет выполняться при наступлении этого события.
//в качестве обработчика события будем использовать безымянную функцию: document.getElementById("myID").onclick = function { alert("Событие click"); }
Например, добавить к кнопке, имеющей id="myButton" событие click , при наступлении которого выполняется указанная функция:
//Найти элемент на событие, которого Вы хотите подписаться var myButton = document.getElementById("myButton"); //добавить к объекту свойство, имеющее имя on[событие] //при наступлении события click выполняется функция myFunction myButton.onclick = myFunction; //функция myFunction function myFunction() { //код функции //... }
Если событие задаётся через атрибут, то браузер, читая код HTML, создаёт соответствующее свойство автоматически. Т.е. браузер работает с событиями только с помощью соответствующих свойств объекта (элемента).
Если Вы подпишитесь на событие различными способами, т.е. через атрибут и с помощью свойства, то браузер в этом случае будет использовать только вариант реализации события, выполненный с помощью свойства. Подписываться на события лучше только с помощью соответствующих свойств объекта (элемента), использовать атрибуты для этих целей не рекомендуется.
Подписка на событие через код JavaScript с помощью метода addEventListenerЭтот способ подписки на событие осуществляется через код JavaScript с помощью специального метода addEventListener . Данный способ подписки является наиболее предпочтительным и рекомендуется стандартом.
Метод addEventListener , предназначен для добавления прослушивателя (listener) определённого события (event) к элементу и выполнения обработчика (callback) при его наступлении. Кроме метода addEventListener есть ещё один метод removeEventListener , который предназначен для выполнения обратного действия, т.е. для удаления прослушивателя.
Синтаксис методов addEventListener и removeEventListener:
Element.addEventListener(event, callback, phase); element.removeEventListener(event, callback, phase);
Метод addEventListener имеет 3 параметра:
- event (обязательный) - имя события, на которое Вы хотите подписаться (прослушивать);
- callback (обязательный) - функция (анонимная или именованная), которая будет выполнять обработку события;
- phase (не обязательный) - этап, на котором будет перехватываться событие. Данный параметр принимает 2 значения: true (на этапе погружения (перехвата) события) и false (на этапе всплытия события). Если данный параметр не указать, то будет использоваться значение false .
Например, использование анонимной функции для обработки события " click ":
Element.addEventListener("click", function { //... });
Например, использование функции myFunction() для обработки события " click ":
Element.addEventListener("click", myFunction); //функция myFunction function myFunction() { //... }
Обработчик события, который Вы добавили с помощью метода addEventListener() можно при необходимости удалить с помощью метода removeEventListener() . Удалить обработчик события можно только в том случае, если он в методе addEventListener() задан в виде именованной функции. Если Вы задали обработчик в виде анонимной функции в методе addEventListener() , то его удалить с помощью метода removeEventListener() не получится.
Например, добавить, а затем удалить обработчик myFunction для события mousemove объекта document:
//добавить для события mousemove объекта document обработчик, заданный в виде функции myFunction document.addEventListener("mousemove",myFunction); //удалить у события mousemove объекта document обработчик, заданный в виде функции myFunction document.removeEventListener("mousemove", myFunction);
Document.addEventListener("click",myFunction); function myFunction() { alert("I LOVE JAVASCRIPT!"); }
Например, добавить несколько обработчиков событий, которые будут выполняться при клике в области, принадлежащей документу:
Document.addEventListener("click",myFunction1); document.addEventListener("click",myFunction2);
Например, добавить объекту document обработчики для следующих событий: click , mouseover , mouseout .
Document.addEventListener("mouseover",myFunction1); document.addEventListener("click",myFunction2); document.addEventListener("mouseout",myFunction3);
Например, для передачи обработчику значений параметров, будем использовать анонимную функцию. В этой анонимной функции будем использовать ещё одну функцию (именованную) с помощью которой и будем передавать необходимые параметры:
Document.addEventListener("click",function() { myFunction(parameter1, parameter2); });
Например, при наступлении события click в документе, изменить цвет фона элемента body . Обработчик события выполнить в виде анонимной функции.
Document.addEventListner("click",function() { document.body.style.backgroundColor = green; });
Как правильно работать с событиямиРаботать в JavaScript с документом HTML (DOM-деревом) и обрабатывать события необходимо только после того страница полностью загрузится:
//когда вся страница загрузилась, вызываем нашу функцию pageInit window.addEventListener("load", pageInit); //функция pageInit() function pageInit() { //подписываемся на события }
Window.addEventListener("load", function() { //подписываемся на события }
Более правильно работать не с событием load (происходит после полной загрузки страницы), а с событием DOMContentLoaded , которое происходит после того как браузер загрузил документ HTML и построил DOM-дерево. Т.е. для того чтобы работать с DOM-деревом нет необходимости ждать пока загрузятся все ресурсы HTML-страницы достаточно чтобы браузер построил дерево DOM.
//HTML документ загрузился и дерево DOM построено document.addEventListener("DOMContentLoaded", pageInit); //функция pageInit() function pageInit() { //подписываемся на события }
Вышеприведенный код можно записать более кратко, с помощью анонимной функции:
Document.addEventListener("DOMContentLoaded", function() { //подписываемся на события }
Одновременно подписать на событие сразу несколько объектовНапример, подписать на событие click сразу все элементы p. Обработку события выполнять с помощью функции myFunction():
Document.addEventListener("DOMContentLoaded", function() { var elementsP = document.getElementsByTagName("P"); for (var i=0; i < elementsP.length, i++) { elementsP[i].addEventListener("click", myFunction); } } //функция myFunction() function myFunction() { //... }
Похожие статьи
-
Простая цифровая антенна своими руками: требования к устройству
Иногда телевизионная антенна выходит из строя в самый неподходящий момент, или ее просто не оказывается под рукой. Например, во время поездки на дачу. В таком случае возникает вопрос, как сделать антенну для телевизора своими руками из...
-
Как правильно ухаживать за рулонным газоном Уход за рулонным газоном зимой
Рулонный газон, вопреки расхожему мнению о трудностях эксплуатации, напротив, требует минимального ухода. Уход сразу после укладки Сразу после укладки по газону не рекомендуется ходить, бегать, играть в активные игры. Через несколько дней,...
-
Нож "Скиннер": характеристики и отзывы
Одним из непременных атрибутов каждого охотника является нож. У многих он является предметом внимания и даже гордости, к его выбору подходят со всей тщательностью. Для правильного подбора охотничьего ножа нужно определиться со способами...
-
Охота на тетерева весной
Является одной из самых популярных, поскольку позволяет получить охотнику не только солидный трофей, но и массу незабываемых эмоций. Своеобразна, поэтому для подготовки к данной охоте нужно знать несколько важных особенностей, чтобы не...
-
Установка циркуляционного насоса – понятная для всех технология
1. НАЗНАЧЕНИЕ ИЗДЕЛИЯ 1.1 Насосы и агрегаты центробежные одноступенчатые типа К предназначены для подачи воды, а также чистых неагрессивных жидкостей сходных с водой по вязкости с водородным показателем (рН) от 6 до 8,5, температурой до...
-
Пошаговая инструкция включения кондиционера на тепло Мобильные и настенные сплит-системы MDV
Появившаяся на рынке сравнительно недавно, но уже успевшая завоевать хорошую популярность торговая марка MDV (МДВ) предлагает широкий спектр климатического оборудования. Для большого сегмента пользователей наиболее интересны кассетные и...