I'm trying to trigger a function when user clicks on <img class="gallery_image">
but it doesn't work.
The script is at the very bottom of the body:
<script>
document.getElementsByClassName('gallery_image').onclick = function (event) {
console.log('click')
event = event || window.event;
var target = event.target || event.srcElement,
link = target.src ? target.parentNode : target,
options = {index: link, event: event},
links = this.parentNode.getElementsByTagName('a');
blueimp.Gallery(links, options);
};
</script>
And there are <img>
elements inside a table.
<img class="gallery_image" src="...IMG_20170907_192537_A1rqcbg.jpg.230x200_q85_crop.jpg" alt="">
Click on such image do nothing (nothing is logged into the console). Do you know why?
As the documentation says getElementsByClassName() returns an array.
Use of :
document.getElementsByClassName('gallery_image')[0].onclick
or with forEach
if they are multiple elements.
Because the returns of the method is Array-like
but not an instance of Array
, here is how you loop on it :
const matches = document.getElementsByClassName('example'); Array.from(matches).forEach((x) => { x.style.backgroundColor = 'red'; });
.example { height: 10px; width: 10px; margin-top: 5px; }
<div class="example"> </div> <div class="example"> </div> <div class="example"> </div>
Example from the documentation :
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="parent-id">
<p>hello word1</p>
<p class="test">hello word2</p>
<p >hello word3</p>
<p>hello word4</p>
</div>
<script>
var parentDOM = document.getElementById("parent-id");
var test=parentDOM.getElementsByClassName("test");//test is not target element
console.log(test);//HTMLCollection[1]
var testTarget=parentDOM.getElementsByClassName("test")[0];//here , this element is target
console.log(testTarget);//<p class="test">hello word2</p>
</script>
</body>
</html>
it is because getElementsByClassName always returns an array so to access that array objects , you must use syntax like
document.getElementsByClassName('gallery_image')[0].onclick = function(){
//your function goes here
}
here 0 is the array element returned by document.getElementsByClassName('gallery_image')
always execute this type of function after dom is ready
Please use EventTarget#addEventListener
in composition with Element#querySelectorAll
:
document.querySelectorAll('.gallery_image').forEach(element => element.addEventListener(galleryImageClick));
function galleryImageClick(event) {
console.log(click);
// do the rest
}
If you want to pick one particular element, use document.querySelector
as it returns a reference to a Node instead of NodeList:
document.querySelector('.gallery_image').addEventListener(galleryImageClick);
As mentioned in comments, you need to make sure the DOM is ready by the moment you establish the event listener. You need to add an appropriate event listener for that:
// vanilla JS way
document.addEventListener('DOMContentLoaded', () => {
// query the DOM, add event listeners, etc.
});
// or jQuery way
$(document).ready(() => {
// query the DOM, add event listeners, etc.
});
Hope it helps.
On a side note, please check out why assigning value to "onclick" property of an element is a bad practice . Cheers!
There's an easier and more efficient way to handling a click event for multiple nodes called Event Delegation :
Find a parent element of the group of elements that need to listen for a click event.
Register the click event to that parent element. Now whenever a child element is clicked, the parent element hears the event and then invokes the callback function. #ids, .classes, [names] are not necessary to find the clicked node because being registered to an event allows it to utilize the Event Object property event.target
.
I noticed that you may not know about the return of methods such as getElementsByClassName
, getElementsByName
getElementsByTagName
or querySelectorAll
or children
, etc.These properties and methods return an array-like object called a HTMLCollection or NodeList . To properly handle this type of data structure requires that each item be looped through array method or a for loop.
The first function listens for the click event on an image them zooms it in or zooms it out. The second part gathers all of the images into a NodeList then assigns an index number to it's url.
// Reference the parent node var gallery = document.getElementById('gallery'); // Register the parent to the click event gallery.onclick = zoomImg; // Callbak function function zoomImg(e) { // if the clicked element is an IMG tag if (e.target.tagName === "IMG") { // Add/Remove the .zoom class e.target.classList.toggle('zoom'); } return false; } // Collect all .image classes into a NodeList var images = document.querySelectorAll('.image'); /* Loop the NodeList through the forEach() method || On each loop add an index number to each of the images' src */ images.forEach(function(img, idx) { img.src = `http://via.placeholder.com/50?text=${idx+1}`; });
.image { transform: scale(1); transition: .5s ease; } .zoom { transform: scale(2); transition: .5s ease; }
<section id='gallery'> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> <img class='image' src="http://via.placeholder.com/50?text="> </section>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.