简体   繁体   中英

javascript .onclick doesn't work

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.

Demo

 // 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM