-1

I get the feeling I am missing something obvious but just can see it.

A trigger on the click event is set:

anchor.addEventListener("click", myClickEvent );

function myClickEvent() {
  this.preventDefault();  // fails
  return false;
}

However the default onClick method still happens.

Can I cancel default propogation at the same time as I addEventListener or is there some other way of doing this. I cannot use .preventDefault() from within myClickEvent because the event is not available at that point.

Edit following comments for clarity: The default onClick of the tag happens even though myClickEvent returns false.

Kyll
  • 7,036
  • 7
  • 41
  • 64
NickC
  • 1,253
  • 5
  • 16
  • 23
  • 1
    What do you mean by the `default onClick` ? – XCS Aug 29 '16 at 15:57
  • 1
    Why isn't the event available in your clickEvent? – Naftali Aug 29 '16 at 15:57
  • Use [removeEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener) to remove event handlers, or simply use element.onclick instead rather than adding multiple handlers via addEventListener. What "default" click event are you talking about? There is none, until you assign one. – ManoDestra Aug 29 '16 at 15:57
  • Please elaborate, what you mean with " the event is not available at that point"? At what point? Are you calling the same function otherwise than an event listener? – Teemu Aug 29 '16 at 15:57
  • The event is passed as an argument to `myClickEvent()`, that makes it available. – Barmar Aug 29 '16 at 15:57
  • 1
    You can change your function to take an event paramenter myClickEvent(e), then you can use e.preventDefault(). – ManoDestra Aug 29 '16 at 15:58
  • 1
    Change your code to make the event available. There's no reliable way to prevent the default behavior without that. I'm guessing you have a few functions calling your handler and that's why you say you can't use `preventDefault`? – Ruan Mendes Aug 29 '16 at 15:58
  • 1
    @NickC -- there is not such function as `preventDefault` on the global scope. The event object gets passed into the handler. – Naftali Aug 29 '16 at 16:04
  • @Neal `this` will be the element that the event was registered with... still no `preventDefault()` :) – Ruan Mendes Aug 29 '16 at 16:04
  • @JuanMendes I made a CW answer -- feel free to edit (or undelete your answer) – Naftali Aug 29 '16 at 16:07
  • Returning `false` from a click listener to the event queue doesn't do anything. – Teemu Aug 29 '16 at 16:07
  • 1
    Your last attempt, do it this way: `anchor.addEventListener("click", function (e) { myClickEvent(e, param1); });`. Then the handler definition: `function myClickEvent(e, param1)`, `e` represents the event object and so on ... – Teemu Aug 30 '16 at 09:48
  • Please do not edit if it invalidates existing answers. – Kyll Aug 30 '16 at 11:20

4 Answers4

2

Returning false from a handler that was registered with addEventListener does nothing. See https://stackoverflow.com/a/1357151/227299 and https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault

The recommended way is to call event.preventDefault()

function myClickEvent(e) {
  e.preventDefault()
}

Handlers from HTML attributes still work, but you should not use it since it's not as clear what return false means when compared to event.preventDefault() (not allow the link to be followed) and event.stopPropagation() (don't let the event bubble up)

Community
  • 1
  • 1
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
2
element.addEventListener("click", myClickEvent );

function myClickEvent(event) {
  event.preventDefault();
  return false;
}
Michał Młoźniak
  • 5,466
  • 2
  • 22
  • 38
0

There is no such function in the global scope called preventDefault -- you need to use the event that has been passed into your callback.

Also please make sure that you are attaching the event to something that can be clicked on (a form, anchor, button etc) that can potentially have an event prevented.

If you attach the event to a child/parent element nothing will work as you expected.

Naftali
  • 144,921
  • 39
  • 244
  • 303
0

Nearly there thanks to Teemu's code but not quite.

There is a difference depending on how the function is called. Seemingly there is both a hidden parameter sent defining the value of 'this' and when called without parameters an automatic event object sent as the first visible parameter:

Call it without parameters:

anchor.addEventListener("click", myClickEvent );

function myClickEvent(param1, param2) {
  // this = events parent element (<a>)
  // this.href = <a href=...>
  // param1 = event object
  // param2 = undefined
  oEvent = param1;
  oEvent.preventDefault();
}

but then call it with parameters:

anchor.addEventListener("click", function (oEvent) { myClickEvent(oEvent, myParameter); });

function myClickEvent(param1, param2) {
  // this = [object Window]
  // this.href = undefined
  // param1 = event object
  // param2 = myParameter
  oEvent = param1;
  oEvent.preventDefault();
}

Notice how when parameters are sent manually the value of 'this' changes from the events parent element to '[object Window]', causing this.href to go wrong.

However the preventDefault now appears to be working reliably.

NickC
  • 1,253
  • 5
  • 16
  • 23
  • Notice, that you can pass the context too, I left it out of the comment just for the simplicity. – Teemu Aug 30 '16 at 12:30
  • When you say I can pass the context too do you mean there is some way I can pass the outer 'this' into the function so that 'this' used in the function refers to the correct outer 'this'? – NickC Aug 30 '16 at 13:37
  • Assign the context to a variable in the outer scope , and pass that variable in the argument list of `myClickEvent`. – Teemu Aug 30 '16 at 18:16
  • Ok that would work. However when running the same from elsewhere without parameters if would need code inside myClickEvent to detect how it was called and handle myThis differently. If no other solution that would work but sounds messy. – NickC Aug 30 '16 at 19:52
  • 1
    Check [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) for `this`, then you can either emulate an event object in arguments, or check, if it exists, in the function. You can also split the function into two separate functions, call the other only when event object exists ... – Teemu Aug 31 '16 at 04:10
  • Tried: anchor.addEventListener("click", function (oEvent) { myClickEvent(oEvent, myParameter).bind(this); }); but 'this' still does not get passed correctly – NickC Aug 31 '16 at 14:22