Ответ 1
var ctlOne = document.getElementById("ctl_one");
var ctlTwo = document.getElementById("ctl_two");
ctlOne.onClick = ctlTwo.onclick = toggleNav;
Если у меня есть два анкерных тега, которые будут запускать одну и ту же функцию (например, несколько кнопок для закрытия панели навигации), как бы связать оба элемента с событием? Нет JQUERY
HTML:
<a href="#" id="ctl_one">Close Nav</a>
<ul id="nav">
<li>Nav One</li>
<li>Nav Two</li>
<li>Nav Three</li>
</ul>
<a href="#" id="ctl_two">Close Nav</a>
JS:
var ctlOne = document.getElementById("ctl_one");
var ctlTwo = document.getElementById("ctl_two");
var both = ctlOne || ctlTwo //<-- this is what I tried and failed.
both.onClick = function(){
toggleNav();
}
function toggleNav(){
// either close or open nav <UL>
}
Опять же, я знаю, как это сделать в jQuery. Я ищу собственный JavaScript-метод.
var ctlOne = document.getElementById("ctl_one");
var ctlTwo = document.getElementById("ctl_two");
ctlOne.onClick = ctlTwo.onclick = toggleNav;
Вы не можете сделать это в одной строке, но я не вижу, что мешает вам сделать это:
ctlOne.onClick = toggleNav;
ctlTwo.onClick = toggleNav;
Или, более DRY:
var both = [ctlOne, ctlTwo];
for (var i=0; i<both.length; i++) {
both[i].onClick = toggleNav;
}
REAL ONE eventHandler для нескольких элементов
Когда я создаю списки или сетки, которые нуждаются в одной и той же функции, я использую только один обработчик событий и решить внутри этого обработчика, что делать.
Использование одного обработчика событий означает, что если вы выгрузите код, вы должны удалить только одного обработчика, но также используете гораздо меньше ресурсов, а обновление кода проще.
В вашем случае мне пришлось включить длинную функцию (slice call...), чтобы получить индекс щелкнутого li и проверить, должен ли я выполнять вашу функцию toggleNav или нет.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script>
(function(W){
var D;
function init(){
D=W.document;
D.getElementById('ul').addEventListener('click',h,false);
}
function h(e){
var a=e.target,i=Array.prototype.slice.call(a.parentNode.childNodes).indexOf(a);
if(a.parentNode.id=='ul'){
console.log('text: ',a.textContent,' index: ',i,' execute toggleNav: ',i<2);
}
}
W.addEventListener('load',init,false)
})(window)
</script>
</head>
<body>
<ul id="ul"><li>a</li><li>b</li><li>c</li></ul>
</body>
</html>
Как вы видите, код короток, никаких циклов. Но больше всего у вас только один обработчик!
это естественно работает только в современных браузерах, но с некоторыми изменениями он делает то же самое во всех браузерах, я думаю, что-то вроде e=e||window.event; e.target=e.target||e.srcElement
..
ИЗМЕНИТЬ
ПРОСТОЙ ПРИМЕР С ДЛИННЫМИ ПЕРЕМЕННЫМИ НАЗВАНИЯМИ И WHITESPACES везде, по просьбе матового, но используя приведенный выше пример, он кэширует различные элементы и совместим с внешними библиотеками, даже если вы его расширяете.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<script>
function inizializzation () { // Here i inizialize the eventhandler
var TheULElement=window.document.getElementById('ul'); // search
// for the element which id is ul
TheULElement.addEventListener ( 'click' , clickhandler , false )
// here i add an event handler to the element which id is ul
}
function clickhandler ( clickevent ) { // that handler i previously added
if ( clickevent.target.parentNode.id == 'ul' ) { // here i check if the
// parent node id of the element i clicked is ul
console.log( clickevent.target.textContent );
// this writes to the console
//-> rigthclick 'inspect element' (in chrome)
}
}
window.addEventListener ( 'load' , inizializzation , false )
// this is the event handler when the page loads
// which starts the first function called inizializzation
</script>
</head>
<body>
<ul id="ul">
<li>a</li>
<li>b</li>
<li>c</li>
<li>d</li>
<li>e</li>
<li>f</li>
<li>g</li>
<li>h</li>
<li>i</li>
</ul>
</body>
</html>
Точка этого ответа состоит не только в том, чтобы обрабатывать два элемента, но несколько элементов
и это отражает название вопроса
Как присоединить одну функцию к нескольким элементам?
а также несколько элементов, которые содержат несколько элементов.
в этом случае вам нужно думать как на большой сетке
строки - это li
внутри этого li я мог бы добавить прокрутки кнопок или что-то еще, и снова только с этим единственным обработчиком событий управляет их все.
на основе номера строки /colum или того, что вы можете предложить.
с cols/rows ваш обработчик находится в prantNode parentNode.
if ( clickevent.target.parentNode.parentNode.id == 'ul' ) {
console.log( clickevent.target.textContent );
}
а строки/столбцы будут
<ul> // whatever (div span) it just has to be a element
<li> // whatever ,best if display:block/flex on all thiselements but
<whatever></whatever> // but with WHITESPACES this does not work
<whatever></whatever> // so it better you add them with a script
<whatever></whatever> // or learn to write without WHITESPACES
<whatever></whatever> // or new lines.
<whatever></whatever> // because a textnode/newline/whitespace
</li> // in dom is a ELEMENT
<li>
<whatever></whatever>
<whatever></whatever>
<whatever></whatever>
<whatever></whatever>
<whatever></whatever>
</li>
</ul>
Есть ли LOOPS? НЕТ.
ps.: Я ответил на этот вопрос, поскольку у него уже есть зеленый флаг, поэтому я просто пытаюсь помочь, но мой язык не является английским, поэтому не стесняйтесь исправлять текст. но pls не касаются моего кода.