Reputation: 51
I am working with this:
<html>
<ol onclick="myevent(event);">
<li title="a">Test 1</p>
<li title="b">Test 2</p>
</ol>
<div id="a" style="display:none;">Text to show</div>
<div id="b" style="display:none;">Other text to show</div>
<script>
function myevent(event) {
var x, i, clk, res;
x = document.getElementsByTagName("DIV");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
clk = event.target.title;
res = document.getElementById(clk);
res.style.display = "block";
}
</script>
</html>
Essentially click one line item, hide all blocks, and then show the named block. This should be simple but I have been researching for hours and getting nowhere.
Thanks in advance! - Joe
Upvotes: 1
Views: 91
Reputation: 43990
There's three ways to handle an event (in this case the click event on <ol>
):
Event Attribute (not recommended)
<ol onclick="eventHandler(); return false">...</ol>
Event Property
document.querySelector('ol').onclick = eventHandler;
Event Listener (recommended)
document.querySelector('ol').addEventListener('click', eventHandler);
For details refer to Introduction to Events and DOM Onevent Handlers
The following demo uses a programming paradigm called Event Delegation. The advantages over the code provided in OP (Original Post) are:
Only one tag needs to be registered as the event listener (common ancestor tag of all targeted tags - ex. <ol>
is an ancestor tag to all <li>
).
There's no need to loop thru each targeted tag and register each one to an event (ex. <li>
do not have to be in a for
loop).
There can be an unlimited number of targeted tags and knowing how many is not required. (ex. there can be a single <li>
to theoretically thousands of <li>
).
The targeted tags can be added dynamically anytime -- during or after page load. If done any other way, any dynamically added tags would not work without reloading the page and somehow keeping them.
Refer to Event Delegation for details.
In the following demo these methods and properties were used:
DOM
Event
Details are commented in demo
/* EVENT DELEGATION */
// Register Ancestor Tag to Event
/*
Register the click event to a common ancestor tag of all
tags you want to be clickable.
So in this instance the clickable tags are all <li>
Ancestor tags could be:
window
document
<body>
<main>
<ol>
Usually the closest tag is the best choice which is <ol>
*/
// ------ Breakdown ------
/*
document.querySelector('ol')
-- find <ol>
.addEventListener('click'...
-- register click event to <ol>
..., eventHandler);
-- run function eventHandler() when <ol> is clicked
*/
document.querySelector('ol').addEventListener('click', eventHandler);
// Event Object
/*
Pass event object which will have properties and methods that will allow us to:
1. find what tag is listening for click event
- event.currentTarget
- in this demo it is <ol>
2. find what tag the user actually clicked
- event.target
- in this demo only <li> will react to being clicked
3. stop the click event from "bubbling" up the event chain
- event.stopPropagation();
- this method is called at the end of eventHandler() so
that the click event doesn't trigger anything else
*/
function eventHandler(event) {
// Reference all tags concerned
// See Event Object #1
const listener = event.currentTarget;
// See Event Object #2
const clicked = event.target;
// Find <output>
const display = document.querySelector('output');
// ------ Breakdown ------
/*
if <ol> isn't the tag that the user clicked...
... and if the clicked tag is a <li>...
... get the text inside that <li>...
... and place it in <output>
(it gets overwritten on each click so there's no need for multiple tags)
*/
if (listener !== clicked) {
if (clicked.tagName === 'LI') {
let data = clicked.textContent;
display.textContent = data;
}
}
/*
Regardless of whether any <li> were clicked stop the click event
See Event Object #3
*/
event.stopPropagation();
}
main {
font: 700 1rem/1.5 Tahoma
}
li:hover {
cursor: pointer
}
<main>
<ol>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
<li>E</li>
<li>F</li>
</ol>
Item: <output></output>
</main>
Upvotes: 0
Reputation: 68923
You have some typos in your code.
Firstly, you are wrongly closing li
element with </p>
Secondly, getElementsBytagname
should be getElementsByTagName
and getelementbyid
should be getElementById
:
function myevent(event){
var x, i, clk, res;
x = document.getElementsByTagName("DIV");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
clk = event.target.title;
res = document.getElementById(clk);
res.style.display="block";
}
<ol onclick="myevent(event);">
<li title="a">Test 1</li>
<li title="b">Test 2</li>
</ol>
<div id="a" style="display:none;">Text to show</div>
<div id="b" style="display:none;">Other text to show</div>
You can also try using querySelectorAll()
and forEach()
that does not require the loop variable i
:
function myevent(e){
var x, clk, res;
x = document.querySelectorAll("DIV");
x.forEach(div => div.style.display = "none");
clk = e.target.title;
res = document.getElementById(clk);
res.style.display="block";
}
<ol onclick="myevent(event);">
<li title="a">Test 1</li>
<li title="b">Test 2</li>
</ol>
<div id="a" style="display:none;">Text to show</div>
<div id="b" style="display:none;">Other text to show</div>
Upvotes: 1