简体   繁体   中英

How do I attach a single function to a multiple element?

If I have two anchor tags that would trigger a same function, (ie multiple button to close a navigation bar) how would I bind both elements with the event? No 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>
}

Again, I know how to do it in jQuery. I'm looking for a native javascript method.

var ctlOne = document.getElementById("ctl_one");
var ctlTwo = document.getElementById("ctl_two");

ctlOne.onClick = ctlTwo.onclick = toggleNav;

You can't do it in one line, but I don't see what's stopping you from doing this:

ctlOne.onClick = toggleNav;
ctlTwo.onClick = toggleNav;

Or, more DRY:

var both = [ctlOne, ctlTwo];
for (var i=0; i<both.length; i++) {
    both[i].onClick = toggleNav;
}

REAL ONE eventHandler on multiple items

When i create lists or grids which need the same function i use only one eventhandler and decide inside that handler what to do.

Heaving one eventhandler means if you unload the code you have to remove only one handler, but also uses alot less resources and updating the code is simpler.

In your case i had to include a long function (slice call...) to get the index of the clicked li and check if i should execute your toggleNav function or not.

<!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>

As you can see the code is short, no loops. But most of all you only have ONE handler!!

this naturally works on modern browsers only but with some changes it does the same in all browsers, i think something like e=e||window.event; e.target=e.target||e.srcElement e=e||window.event; e.target=e.target||e.srcElement ..

EDIT

SIMPLE EXAMPLE WITH LONG VARIABLE NAMES and WHITESPACES everywhere as requested by matt, but use the above example at it caches the various elements and it's compatible with external libraries even if you extend it.

<!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>

The point of this answer is not just to handle the 2 elements but multiple elements

and that reflets the titleof the question

How do I attach a single function to a multiple element?

or also multiple elements which contains multiple elements.

in that case you need to think like on a large grid

rows are the li's

inside this li's i could add buttons spans or whatever and again only with that single eventhandler control them all.

based on the row/colum number or whatever you immagination has to offer.

with cols/rows your handler is on the prantNode of the parentNode.

if ( clickevent.target.parentNode.parentNode.id == 'ul' ) {
 console.log( clickevent.target.textContent );
}

and the rows/colums would be

<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's 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>

Are there LOOPS ? NO.

ps.: i answered this question as it has already the green flag so i just try to help but my laguage is not english so feel free to correct my text . but pls don't touch my code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM