I used a function which dynamically creates ul elements with unique ids. I need the elements to be able to execute a function, and for the code to know which element executed the function. I've written some pseudo-code below to illustrate:
<ul id = "topic1" onclick = "getReleventLinks(1)"> element1 </ul>
<ul id = "topic2" onclick = "getReleventLinks(2)"> element2 </ul>
<ul id = "topic3" onclick = "getReleventLinks(3)"> element3 </ul>
getReleventLinks(x){
(gets links with topic x);
}
I have no problem embedding the function upon creating these elements, but I cannot figure out a way for the code to know which ul element executed the function. I just need the ul element's id passed in. The function will perform xml request that returns hyperlinks on the topic passed into the function.
Sorry for the pseudo-code. The actual code in its entirety is quite large and I felt this was an easier way to explain the concept. I am suspecting it may not be possible, and an alternative method would also be welcome.
Thank You
CodePudding user response:
<ul id="topic1">
element1
</ul>
<ul id="topic2">
element2
</ul>
<ul id="topic3">
element3
</ul>
<script>
// First way:
// You can query for all elements that have an id that starts with topic
// and then add an event listener to each one that can depict which element was clicked
// based off the event's currentTarget property.
// https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
// Query elements that have a tag name ul and convert the node list
// into an array
const ulElements = Array.from(document.querySelectorAll('ul'))
// Grab only the elements that have an id that starts with topic
const elementsWithTopicID = ulElements.filter(element => element.id.startsWith('topic'))
function onClick(event) {
console.log(event.currentTarget)
}
// Add the same event listener to each element
elementsWithTopicID.forEach(element => element.addEventListener('click', onClick))
// Second Way:
// This route is a bit more confusing but much more efficient in my opinion
// Add an event listener on the body and use event bubbling to handle the event
function onBodyClick(event) {
const element = event.target
// A return guard to avoid handling elements that do not have ids
// that start with topic
if (!element.id.startsWith('topic')) return;
console.log(element)
}
// When you add the listener to the body, you can handle all click events
// on the children of the body element
// https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling_and_capture
document.body.addEventListener('click', onBodyClick)
</script>
CodePudding user response:
Clicks pass an event
object to the functions that handle that event. That event object has a target
property that is the HTML element that fired that event.
But to use that, you can't pass your functions as strings. You shouldn't anyway, it's a bad practice. Instead, bind the click handlers to the elements, and pass in a reference to a function as the handler. Then the function will be called with the event as the first argument.
Working example:
function getReleventLinks(event){
console.log(event.target.id)
}
// 'ul' here is whatever CSS selector targets your list
document.querySelectorAll('ul').forEach(ul => {
ul.addEventListener('click', getReleventLinks);
})
<ul id = "topic1"> element1 </ul>
<ul id = "topic2"> element2 </ul>
<ul id = "topic3"> element3 </ul>
CodePudding user response:
You can use a function for all of them, without passing id, just use this
keyword and get element's id for your xmlrequest