Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event target should be anchor but is image instead

Tags:

javascript

I am working on a dialog script in Vanilla JS. I ran into a problem with the click event on the video image. Even tough the image is surrounded with an anchor tag it shows the image as the event.target on the "trigger-dialog-open" event.

Here is the HMTL:

<a class="trigger-dialog--open thumbnail" data-dialog-id="dialog-video" href="javascript:;">
    <figure>
        <img src="http://i.ytimg.com/vi/id/sddefault.jpg" alt="" />
    </figure>
</a>

And this is the event in JS:

var openTriggers = document.getElementsByClassName('trigger-dialog--open');
for (var i = 0; i < openTriggers.length; i++) {
    openTriggers[i].addEventListener("click", function (event) {
        this.openDialog(event.target.getAttribute('data-dialog-id'));
    }.bind(this), false);
}

The event handler wants to know the dialog-id from the anchors data attribute. It can't be found because it thinks the image is the event.target, not the actual anchor. How can I correct this? Thanks!

like image 217
Floris Avatar asked Oct 31 '15 21:10

Floris


People also ask

Is event target deprecated?

target are obsolete, not that Event. target itself is obsolete. The DOM (Living Standard) specification is not marked as obsolete and you should use that definition.

What is the difference between event target and event currentTarget?

target is the element that triggered the event (e.g., the user clicked on) currenttarget is the element that the event listener is attached to.

Which element is event target in the event object?

When an event is fired, the element that fires the event is known as the emitter. This element is what we call the target. So, the target property of that event object refers to the event emitter.

What are the properties of event target?

The target event property returns the element that triggered the event. The target property gets the element on which the event originally occurred, opposed to the currentTarget property, which always refers to the element whose event listener triggered the event.


2 Answers

Use event.currentTarget. The event.target is supposed to be the img element since that is what the user has clicked on. The click then bubbles up through the image's containers. event.currentTarget gives you the element that the click handler was actually bound to.

(Or if you didn't bind this to some other object you could use this within the click handler and it should also be the current target.)

like image 165
nnnnnn Avatar answered Oct 27 '22 00:10

nnnnnn


I have a few questions is the var openTriggers supposed to be a part of a module hash? Because if it's global then you don't use a this, you only add a this, if it's referencing a variable that the function is also contained in. For example:

var aThing = {
   openTriggers: document.getElementsByClassName('trigger-dialog--open'),
   openModal: null,
   openDialog: function(clickedThingAttr){  
     if(this.openModal !== null){ 
        this.openModal.style.display = 'none';
     }else{ 
        this.openModal = document.getElementById(clickedThingAttr);
     }
     this.openModal = document.getElementById(clickedThingAttr);
     this.openModal.style.display = 'block';
   },
   setEventListenersNStuff: function(){
     for (var i = 0, n = this.openTriggers.length;i < n; i++) {
         this.openTriggers[i].addEventListener("click", function (event) {
            this.openDialog(event.target.getAttribute('data-dialog-id'));
         });
       };
    }

   };//end of aThing hash object
   aThing.setEventListenersNStuff();

There are a few issues here: 1. why are you using .bind I think that is a jQuery thing, you want to pass a string to another function when an object is clicked, there no need for binding at all. 2. Also make sure that if you want to do something like open a modal, there is no need to call another method unless it's kinda complex. 3. What about other potential dialogs, it seems that when a .trigger-dialog--open is clicked you're just showing that one one modal with the embedded id, but what about others? Make sure all modals are closed before you open a new one, unless you want to have like 10 modals are open.

A thing to note: I added the line var i = 0, n = openTriggers.length;i < n; i++, now in this case it's silly optimization, and I heard for modern browsers this doesn't apply, but to explain why I added it, is because i < openTriggers.length would count and integrate the array N times. (This may be an outdated optmiziation).

If you meant global

Below I added a different set of code, just in case you meant that var openTriggers is global, kinda like you wrote above. Also I used querySelectorAll for this which is like jQuery's $('.thing') selector.

anyhoo, I also added

var openTriggers = document.querySelectorAll('.trigger-dialog--open');
var n = openTriggers.length;
function openDialog(ddId){ 
  for (var i = 0;i < n; i++) {
    openTriggers[i].style.display = 'none';

  };
  document.getElementById(ddId).style.display = 'block';
};
for (var i = 0;i < n; i++) {
    openTriggers[i].addEventListener("click", function (event) {
       openDialog(event.target.getAttribute('data-dialog-id'));
   });
}

}

So for the question of hiding already open modals I would suggest you could either cache the open Dialog within a module, or you could toggle a class, which would be less efficient since it would require an extra DOM search. Additionally you could add a if this.openModal.id === clickedThingAttr to hide if open, that way you got a toggle feature.

Anyways I suggest you read up on this stuff, if you want to use plain JS but would like the features of jQuery: http://blog.romanliutikov.com/post/63383858003/how-to-forget-about-jquery-and-start-using-native

Thank you for your time.

like image 30
Pete Avatar answered Oct 26 '22 23:10

Pete