It sounds like you want to do two things:
- Write an event handler that is aware of its invocation context, without hardcoding that context.
- Find an HTML element relative to another element.
Let's address these separately and then see an example that does both.
Writing an event handler that is aware of its invocation context
This is what this
is for :)
From the MDN article on this
:
When a function is used as an event handler, its this is set to the element on which the listener is placed (some browsers do not follow this convention for listeners added dynamically with methods other than addEventListener()).
In simple terms, this
is a special variable whose value changes based on where a function is called from.
This SO question addresses scopes and contexts in JavaScript more thoroughly.
Finding an HTML element relative to another element
Some combination of the Element.querySelector function and DOM Node interface's parent/child/sibling properties is usually enough to get this job done.
Putting it all together
Here's a snippet that applies these ideas to your HTML structure (wrapped in an outer div):
// Define event handler
function toggleMute(e) {
// "this" comes from the calling context
// in this case it's the element that was clicked
var video = this;
// get the video's parent element and find the first img element inside it
var muteicon = video.parentElement.querySelector('img');
// do some stuff with 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, listening 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>
Additional possibilities
There are other ways to make an event handler aware of its context. You could also use the event object that is exposed when the event is dispatched, or pass this
in explicitly in HTML. See the examples below. My preference is to avoid setting handlers inline in HTML, so I'd opt for the second or third methods.
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">