How to pass event as argument to an inline event handler in JavaScript?
Asked Answered
G

5

196

// this e works
document.getElementById("p").oncontextmenu = function(e) {
  e = e || window.event;
  var target = e.target || e.srcElement;
  console.log(target);
};

// this e is undefined
function doSomething(e) {
  e = e || window.event;
  var target = e.target || e.srcElement;
  console.log(target);
}
<p id="p" onclick="doSomething(e)">
  <a href="#">foo</a>
  <span>bar</span>
</p>

There are some similar questions have been asked.

But in my code, I'm trying to get child elements who's been clicked, like a or span.

So what is the correct way to pass event as an argument to event handler, or how to get event inside handler without passing an argument?

edit

I'm aware of addEventListener and jQuery, please provide a solution for passing event to inline event hander.

Groth answered 6/5, 2013 at 17:52 Comment(4)
developer.mozilla.org/en/docs/DOM/EventTarget.addEventListenerRowe
Is there a good reason for using inline event handlers rather than switching to addEventListener? en.wikipedia.org/wiki/Unobtrusive_JavaScriptUnclad
@Unclad For me yes, no need to care about re-binding them manually everytime when dynamically loading or reloading html through ajax for example.Thermion
Inline handlers are more declarativeBrackely
T
307

to pass the event object:

<p id="p" onclick="doSomething(event)">

to get the clicked child element (should be used with event parameter:

function doSomething(e) {
    e = e || window.event;
    var target = e.target || e.srcElement;
    console.log(target);
}

to pass the element itself (DOMElement):

<p id="p" onclick="doThing(this)">

see live example on jsFiddle.

You can specify the name of the event as above, but alternatively your handler can access the event parameter as described here: "When the event handler is specified as an HTML attribute, the specified code is wrapped into a function with the following parameters". There's much more additional documentation at the link.

Twerp answered 6/5, 2013 at 17:57 Comment(10)
(And for anyone wondering: Yes, this does work on Chrome, Firefox, etc., even though some [Firefox, for instance] don't have a global event object. It's because the context in which the DOM0 handler is called has an event object, even if [on some browsers] it isn't a global.)Refresher
this refers to p, but I'm trying to get a or spanGroth
Passing ´event´ is the only way that I know, provided it is supported. Parsing ´this´ is of no use in this situationUnclad
@AkramBerkawy that is it. I thought I could pass e the same way as in ele.onclick = function(e), but it's event. Thanks.Groth
@Groth That's very important. the parameter must be named exactly as "event"Agility
Wadih M.'s answer is way better than this. This one is misleading (like others similar to it), making people believe that "(event)" parameter should be put into the function call, when, actually, JavaScript has the "event" parameter already and readily available inside the called function, so there is no need to declare it (it took me days to realise that it made no difference changing the variable name, because it was not really being passed). Also, the explanation given there dismisses any doubts about why JS works like that (maybe it shouldn't, but that's not on me to judge...)Burris
The reason the 'event' object can be used as an argument to the in-HTML inline event-handler is explained in developer.mozilla.org/en-US/docs/Web/Guide/Events/… .Joiejoin
I can assure you that "event" is not always available inside the function. This is the only way to pass in the event while also passing a parameter.Archduke
@JohnLord You are wrong, in natural javascript, the event object is there when it is called from an event. If the event object doesn't appear in the function, it's because it wasn't called from an event, e.g. onclick, etc. Please see my answer.Thermion
I get the error when I try to name the parameter of the eventhandler in .html: onClick( event ) "event does not exist on type..."Pure
T
33

You don't need to pass this, there already is the event object passed by default automatically, which contains event.target which has the object it's coming from. You can lighten your syntax:

This:

<p onclick="doSomething()">

Will work with this:

function doSomething(){
  console.log(event);
  console.log(event.target);
}

You don't need to instantiate the event object, it's already there. Try it out. And event.target will contain the entire object calling it, which you were referencing as "this" before.

Now if you dynamically trigger doSomething() from somewhere in your code, you will notice that event is undefined. This is because it wasn't triggered from an event of clicking. So if you still want to artificially trigger the event, simply use dispatchEvent:

document.getElementById('element').dispatchEvent(new CustomEvent("click", {'bubbles': true}));

Then doSomething() will see event and event.target as per usual!

No need to pass this everywhere, and you can keep your function signatures free from wiring information and simplify things.

Update 2022-10-30:

I have contacted someone from WHATWG, and another way it could be done is below, although some IDE's report it as "obsolete" which it's not. You could pass the "event" keyword (no capital E) in your caller's argument list, in any position, and use it as such.

Below would work, a, b, c and d being extra arguments to pass if any, to demonstrate the order doesn't matter:

<p onclick="doSomething(a,b,event,c,d)">

And in your function definition, you would capture it accordingly:

function doSomething(arg1, arg2, arg3, arg4, arg5){} //arg3 would contain the event

And access the usual properties, in this case since we wired event with arg3:

console.log(arg3.target)
Thermion answered 31/8, 2019 at 20:9 Comment(13)
At least on IE11, this is not true, There are no default arguments.Dacron
@Dacron It does work for IE11 as well. It works on all major browsers as this is necessary for backwards compatibility. As I mentioned in the answer, only if the javascript function is fired from an event, which is the only scenario where an event exists, there will be an object already called "event" that you can readily access inside your function without having had to pass extra wiring to your function prototype. I just did a test on my machine with IE11 for an onclick event and and the 'event' variable contained a "PointerEvent object".Thermion
I couldn't simulate a click on a radio button, am I missing something? document.getElementById("radioOption1").click() works but this did not: document.getElementById("radioOption1").dispatchEvent(new CustomEvent("click", {'bubbles': true}))Fireproof
I tried this by adding a parameter of data I already needed to pass and guess what? This was not passed, and neither was event. If you have to pass data through the click (or whichever event), you MUST specify the parameter you pass it through.Archduke
@JohnLord The event object will exist when the function is called from an event. I use that property all the time, and the event object is there, as it should be. Start up a fresh html file, and do it there, and you'll see it works. Make sure nothing is interfering with this natural behavior. Furthermore, event.target will contain the calling object. So it you had a data attribute in the calling object, you can access it with event.target.dataset.xxxx.Thermion
It's best not to use this method for referencing the event as it is deprecated. developer.mozilla.org/en-US/docs/Web/API/Window/eventCultivable
@FarzadSoltani It's not the first phony obsolescence message that I see. I will be sending a feedback on that mozilla form asking to remove the deprecation message. There is no reason to remove that feature, and that feature has been rock solid, on all browsers, on all devices. I always build all my sites from scratch, I use no frameworks, and this is how I access the event.target without pain. In any case, if you think you have a better suggestion though, feel free to answer that question with your solution, I would love to see what alternative you suggest.Thermion
@WadihM. Yeah I agree that removing it is a bad idea. I generally use the same approach as the accepted answer, but in some cases I access the raw event object just like you.Cultivable
@FarzadSoltani Right. I just posted my complaint to that MDN article: github.com/mdn/content/issues/21848 . I really don't see why this should be removed. I'm going to keep using it, since I build all my sites from scratch, I've never had an issue with it.Thermion
They seem to have responded to your issue with a pretty compelling answer.Cultivable
@FarzadSoltani Yes, I'm grateful for his answer. I have opened a comment on whatwg. github.com/whatwg/dom/issues/1123. I've been monitoring that problem for more than 3 years in programming tools and documentation adding strikethoughs on "event" object, as per my comment in whatwg, I had opened a case in 2019 with jetbrains about that same issue where I was asking to remove the misleading deprecation notice.Thermion
as of 2024 event seems to be deprecated. Is there any alternative for it, for the usecase the OP described? developer.mozilla.org/en-US/docs/Web/API/Window/eventCrossexamine
@Crossexamine See domenic's response here: github.com/whatwg/dom/issues/1123#issuecomment-1292854667 . Toolings might not understand the distinction and report any use of event as deprecated while it's not, You can pass (event) as a parameter, and you should be fine, since this is not Window.event. Refer to what was said on the whatwg post.Thermion
C
24

Since inline events are executed as functions you can simply use arguments.

<p id="p" onclick="doSomething.apply(this, arguments)">

and

function doSomething(e) {
  if (!e) e = window.event;
  // 'e' is the event.
  // 'this' is the P element
}

The 'event' that is mentioned in the accepted answer is actually the name of the argument passed to the function. It has nothing to do with the global event.

Chart answered 25/1, 2015 at 17:10 Comment(3)
Good tip. When people will start adopting web components call() and apply() will prove essential in emulating data binding capabilities available in mainstream js frameworks. One extra trick is to do something similar to Object.assign(this.querySelector('my-btn'), this) inside a web component and voila, data binding. You can access any method of the parent web component class from the inline events onclick="toggleBtnActive.call(this, true)".Williams
This is the absolute only way i was able to get an asp radgrid to pass the click event to an event handler along with the row index.Archduke
@JohnLord Never heard of asp radgrid, however the natural javascript standards have always worked the same, and I never needed to use above confusing constructs to access my event and event.target objects.Thermion
W
2

Here is how I would do it to prevent users from copying and pasting invalid characters into input text fields:

function validatePaste(el, e) {
  var regex = /^[a-z .'-]+$/gi;
  var key = e.clipboardData.getData('text')
  if (!regex.test(key)) {
    e.preventDefault();
    return false;
  }
}

This function is located inside <script> tags and it is called like:

<input type="text" onpaste="validatePaste(event)">
Waldrup answered 14/5, 2021 at 18:28 Comment(1)
while your example is good, your initial description came across like you were answering a completely different question.Archduke
S
0

This would answer the question perfectly without having to worry about deprecation issues.

function doSomething(e){
  // instead of e.target, use just 'e'
  console.log(e)
}

<p id="p" onclick="doSomething(this)">
   <a href="#">foo</a>
   <span>bar</span>
</p>
Slew answered 4/8, 2023 at 10:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.