Reputation: 15
I just thought I could use event delegation on ul element so that a click on any of the li elements will bubble up to ul. This is then captures by ul's event.target to get the right li element and proceed according to what I need with the li. This is the way I learnt. But clicking on the contact li element is not alerting as expected. Please help me with this. My company forces me to use event delegation. That's why this is so important.
HTML
<!doctype html>
<html>
<head>
<title>Title</title>
<link rel="stylesheet" type="text/css" href="style.css" >
<script src="JavaScript.js"></script>
</head>
<body>
<div>
<ul id="nav">
<li id="click"><a href="#">Contact</a></li>
<li> <a href="#">Blog</a></li>
<li> <a href="#">Work</a></li>
<li> <a href="#">About</a></li>
<li> <a href="#">Home</a></li>
</ul>
</div>
</body>
</html>
JS
var list = document.getElementById("nav");
list.addEventListener("click", function(event) {
switch(event.target.id) {
case "click":
alert("haha");
break;
}, false);
CSS
body {
margin: 0;
}
#nav {
list-style-type: none;
margin: 0;
padding: 0;
}
#nav li {
width: 20%;
float: left;
text-align: center;
display: inline;
}
#nav li a {
line-height: 40px;
display: block;
padding: 0.5em 5px;
text-decoration: none;
font-weight: bold;
color: #F2F2F2;
-webkit-box-shadow: 3px 3px 3px rgba(51,51,51,0.3);
box-shadow: 3px 3px 3px rgba(51,51,51,0.3);
}
#nav a:link, #nav a:visited {
background-color: #071726;
}
#nav a:hover, #nav a:active, #nav a:focus {
background-color: #326773;
}
Upvotes: 0
Views: 545
Reputation: 1074038
Your main problem is that there's a syntax error in your event handler, you're missing the }
for the switch
. (Using consistent indentation will help avoid those kinds of errors.)
Then your problem is that event.target
isn't what you think it is. event.target
is the actual element that was clicked. The odds in your case are that the actual element that was clicked is the a
element (the link).
So what you want to do is look at the lineage from the clicked element down to the element on which you hooked the click (which will be this
), looking for the one that's at the level you want (in your case, an li
): Live Example | Source
var list = document.getElementById("nav");
list.addEventListener("click", function(event) {
// Start with the element that was clicked
var li = event.target;
// You may want `event.preventDefault();` here
// If the element exists, it isn't the list on which we hooked
// the event, and its tag name isn't LI, go to the parent
// element instead.
while (li && li !== this && li.tagName.toUpperCase() !== "LI") {
li = li.parentNode;
}
// If we got an LI, use it
if (li) {
// OR you may want `event.preventDefault();` here
switch(li.id) {
case "click":
alert("haha");
// OR you may want `event.preventDefault();` here
break;
}
}
}, false);
Also, be sure that the code above is either in a script
element below your navigation list in the HTML, or in an onload
handler (I recommend the former, just put the script at the end).
And finally: Since the link's href
is just "#"
, I'm guessing you don't actually want the link to be followed by the browser (as that will scroll up to the top of the page). If that's the case, you'll want to add a call to event.preventDefault()
in the handler. I've noted a few places above where you may want it, it depends on whether you always want to prevent the link from being followed, or only in certain cases.
Side note: Although you can, of course, do this work yourself, you can reuse the work of others by using a good library like jQuery, YUI, Closure, or any of several others. For example, in jQuery, that looks like this:
$("#nav").on("click", "li", function(event) {
// Possibly with `event.preventDefault();` here
switch (this.id) {
case "click":
alert("haha");
// OR possibly with `event.preventDefault();` here
break;
}
});
Other libraries have similar features.
Upvotes: 2