It appears that you have two objectives:
- Create an event handler that understands its calling context without hardcoding it.
- Locate an HTML element in relation to another element.
Let's tackle these separately and then demonstrate a combined example.
Developing an event handler with contextual awareness
This is where this
comes into play :)
As stated in the MDN article on this
:
When a function serves as an event handler, its this is set to the element on which the listener is placed (some browsers may not adhere to this convention for dynamically added listeners using methods other than addEventListener()).
In simple terms, this
is a special variable whose value changes based on the function's call location.
This Stack Overflow post delves deeper into scopes and contexts in JavaScript.
Discovering an HTML element relative to another element
A combination of the Element.querySelector function and DOM Node interface's parent/child/sibling properties is typically sufficient for this task.
Merging it all together
Below is a snippet that implements these concepts within your HTML structure (enclosed within an outer div):
// Define event handler
function toggleMute(e) {
// "this" is derived from the calling context
// here, it represents the clicked element
var video = this;
// obtain the video's parent element and locate the first img element inside it
var muteicon = video.parentElement.querySelector('img');
// perform actions on these elements
if(video.muted) {
video.muted = false;
video.style.background = "green"
muteicon.style.background = "yellow";
}
else {
video.muted = true;
video.style.background = "orange"
muteicon.style.background = "teal";
}
}
// Attach handler to video element, listen for "click" event
document.getElementById('my-vid').addEventListener("click", toggleMute);
video { height: 100px; width: 100px; background: green; }
img { height: 50px; width: 50px; background: yellow; }
<div>
<video id="my-vid">
<source src="my.mp4">
</video>
<br>
<img src="img/muted_icon.png" id="speaker-icon" />
</div>
Further options
There are alternative ways to ensure an event handler comprehends its context. You could utilize the event object exposed upon dispatching the event, or explicitly pass this
in HTML. Refer to the examples below. Personally, I prefer avoiding inline handlers in HTML, opting for the second or third methods instead.
function ping(target) {
console.log(target);
target.classList.toggle('pinged');
const next = target.nextElementSibling;
next.classList.toggle('pinged');
next.nextElementSibling.classList.toggle('pinged');
}
function pong() {
console.log(this);
this.classList.toggle('ponged');
this.nextElementSibling.classList.toggle('ponged');
this.previousElementSibling.classList.toggle('ponged');
}
function pang(e) {
console.log(e.target);
e.target.classList.toggle('panged');
const prev = e.target.previousElementSibling;
prev.classList.toggle('panged');
prev.previousElementSibling.classList.toggle('panged');
}
// 'ping' attached to element 'one' inline, in HTML
document.getElementById('two').addEventListener("click", pong);
document.getElementById('three').addEventListener("click", pang);
img {max-height: 200px; max-width: 200px;}
.pinged {filter: sepia(80%)}
.ponged {transform: scale(0.5)}
.panged {opacity: 0.5;}
<img id="one" src="https://www.thewholesomedish.com/wp-content/uploads/2019/06/The-Best-Classic-Tacos-550-500x500.jpg" onclick="ping(this)">
<img id="two" src="https://www.thewholesomedish.com/wp-content/uploads/2019/06/The-Best-Classic-Tacos-550-500x500.jpg">
<img id="three" src="https://www.thewholesomedish.com/wp-content/uploads/2019/06/The-Best-Classic-Tacos-550-500x500.jpg">