How does stopPropagation cancel preventDefault? - javascript

I have a website that does not allow to open up the context menu by clicking the right button on a mouse.
It seems like the website does blocking it by using preventDefault on the event oncontextmenu.
I was able to bypass it by
window.addEventListener('contextmenu', (event) => {
event.stopPropagation();
}, true)
I know that preventDefault blocks the default action of an event and stopPropagtion prevents an event from firing bubble to its parent element. But how does stopPropagation cancel preventDefault?

By calling stopPropagation you stop other attached event listeners from capturing the event. Thus, the event listener that would call preventDefault would not capture it and thus would not prevent the context menu from opening.
See in the example below. The listener that tries to prevent the context menu from opening is not executed because stopPropagation is called:
window.addEventListener('contextmenu', (event) => {
console.log('stopPropagation')
event.stopPropagation();
}, true)
document.body.addEventListener('contextmenu', (event) => {
console.log('stop context menu')
event.preventDefault();
})
Right click
<br/>
<br/>
Notice that 'stop context menu' is not logged

Related

Event Listener Callback Fires Immediately When Set Inside The Callback of Another Event Listener. ReactJS

With a create-react-app boilerplate setup, I have an input field with an onFocus event passed. Within this onFocus callback I'm setting a click eventlistener on window.document.
When the input field is focused why does the clickHandler callback fire immediately?
function App() {
const clickHandler = (e) => {
console.log("clicked");
window.document.removeEventListener("click", clickHandler)
}
const focusHandler = (e) => {
console.log('onFocus');
e.stopPropagation()
window.document.addEventListener("click", clickHandler)
}
return (
<div className="App">
<input onFocus={focusHandler} />
</div>
);
When you click on the input, few events occur such as mousedown, mouseup, focus click. (fyi - click happens when a mousedown and mouseup event occur on the same element). In chrome, focus handler is executed first and then the click handler is executed (if the handlers exist).
Now, in your code when you click on the input, focusHandler is executed where a click handler is attached to the window. By the time the js engine finishes the execution of focusHandler, there is a click handler registered already. So as soon as focusHandler is executed, the js engine realises that 'ah, there is a clickHandler that I need to execute it. Let me do it' . Hence your clickHandler fires immediately.
You can test it by attaching event handler in a setTimeout. In below code, js engine has no clickHandler to execute after focusHandler execution is finished. So click handler won't fire immediately.
const focusHandler = e => {
console.log("onFocus");
e.stopPropagation();
setTimeout(() => window.addEventListener("click", clickHandler), 1000);
};

React - Key down event first triggers on body then on element

I'm injecting some code which creates a text input into existing pages on the internet.
On some sites, when the user presses some specific keys while focused onto my text input, the event gets captured instead of being bubbled.
I've been trying multiple solutions to prevent this but they do not seem to work:
keyUp = event => {
event.preventDefault();
event.nativeEvent.stopImmediatePropagation();
event.stopPropagation();
return false;
};
<Form.Control
as="textarea"
onChange={this.updateInput}
onKeyUp={this.keyUp}
onKeyPress={this.keyUp}
onKeyDown={this.keyUp}
/>
Is there a way I can prevent this event from being triggered on the body instead of being triggered in my element first?
React attaches its event listener to body by default, and uses that to trigger its own SyntheticEvent
You could try attaching your event in capture mode by appending Capture to your event name, as outlined here
Edit (added for clarification to comment):
Attach an event to your window:
window.addEventListener("keydown", function (evt) {
if (evt.target.id === 'elementID') {
//do what you want to, here.
//if you want to prevent the event propagating:
evt.stopImmediatePropagation();
evt.stopPropagation();
}
}, true);
in your jsx:
...
<input id='elementID' />
...
I've added a listener at window level to capture the event and prevent propagation down. Of course if a listener is already added at window level this will not work:
window.addEventListener("keydown", this.keyDown, true);

Activating an element's listener inside a div without activating the div's listener

I want to be able to activate an element's listener without activating the listener of the div that contains my element.
$('body').on('click', '.thiscoll', function(){
if (type === "form") {
hidePanels();
$('#navbar-pannel').show();
}
});
$('#main_container').on('click', 'a', function(){
hidePanels();
$('#custom-nav').show();
$('#l-name').html("New link name");
$('#l-destination').html("New link destination");
});
The first listener is on my div, while the second listener is on my links that are contained into my div. When I click on a link, it first triggers the 'a' listener, then the '.thiscoll' listener, while I only want to trigger the 'a' listener.
Is it possible?
Thanks.
Long story short, you want to stop event propagation. Something like
$('a').on('click', function(event) {
event.stopPropagation();
// and possibly do something else you require
});
should do.
Yes, what you want is possible. With events in Javascript we have this nice thing called event capturing and event bubbling. By default, browsers will register events in the bubbling phase.
For you, this means that the target you click will have its event handlers fired first. Then its parent's. Then its parent's parent's and so on. You can read more about it on MDN
To stop this propagation, you can use the stopPropagtion method on the Event-object. The Event object is supplied as the first argument in your event listener:
const main = document.querySelector('.main');
const button = document.querySelector('.button');
const stopPropagation = document.getElementById('stopPropagation');
main.addEventListener('click', () => console.log('Clicked on main'));
button.addEventListener('click', (evt) => {
if (stopPropagation.checked) {
evt.stopPropagation();
}
console.log('clicked button');
});
<input id="stopPropagation" type="checkbox">
<label for="stopPropagation">stopPropagation</label>
<div class="main">
Hello, World
<button class="button">Button</button>
</div>

prevent default click on drag start

I am new to javascript and am stuck with an issue
I am not able to prevent click on an element while dragging. What do i need to do in my event handlers to prevent click on dragging/ note click should work as normal while element is not being dragged
I tried prevent default and stop propagation inside the dragstart event handler, but this seems to disable the drag action and not the click action
this.message_list
.addEventListener('initrow', function(o) { ref.init_message_row(o); })
.addEventListener('dblclick', function(o) { ref.msglist_dbl_click(o); })
.addEventListener('keypress', function(o) { ref.msglist_keypress(o); })
.addEventListener('select', function(o) { ref.msglist_select(o); })
.addEventListener('dragstart', function(o) {alert('33'); ref.drag_start(o);})
.addEventListener('dragstart', function(e) {alert('44'); ref.drag_start(e); })
alerts 33 and 44 fire on dragstart , but adding stuff like stopping event propagation or preventing default action, disables the drag and not the click.
Once again click action is needed on the same element when it is not being dragged

Right way to prevent additional events [duplicate]

They seem to be doing the same thing...
Is one modern and one old? Or are they supported by different browsers?
When I handle events myself (without framework) I just always check for both and execute both if present. (I also return false, but I have the feeling that doesn't work with events attached with node.addEventListener).
So why both? Should I keep checking for both? Or is there actually a difference?
(I know, a lot of questions, but they're all sort of the same =))
stopPropagation prevents further propagation of the current event in the capturing and bubbling phases.
preventDefault prevents the default action the browser makes on that event.
Examples
preventDefault
$("#but").click(function (event) {
event.preventDefault()
})
$("#foo").click(function () {
alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
<button id="but">button</button>
</div>
stopPropagation
$("#but").click(function (event) {
event.stopPropagation()
})
$("#foo").click(function () {
alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
<button id="but">button</button>
</div>
With stopPropagation, only the button's click handler is called while the div's click handler never fires.
Where as if you use preventDefault, only the browser's default action is stopped but the div's click handler still fires.
Below are some docs on the DOM event properties and methods from MDN:
event.cancelBubble
event.preventDefault()
event.returnValue
event.stopPropagation()
For IE9 and FF you can just use preventDefault & stopPropagation.
To support IE8 and lower replace stopPropagation with cancelBubble and replace preventDefault with returnValue
Terminology
From quirksmode.org:
Event capturing
When you use event capturing
| |
---------------| |-----------------
| element1 | | |
| -----------| |----------- |
| |element2 \ / | |
| ------------------------- |
| Event CAPTURING |
-----------------------------------
the event handler of element1 fires first, the event handler of element2 fires last.
Event bubbling
When you use event bubbling
/ \
---------------| |-----------------
| element1 | | |
| -----------| |----------- |
| |element2 | | | |
| ------------------------- |
| Event BUBBLING |
-----------------------------------
the event handler of element2 fires first, the event handler of element1 fires last.
Any event taking place in the W3C event model is first captured until it reaches the target element and then bubbles up again.
| | / \
-----------------| |--| |-----------------
| element1 | | | | |
| -------------| |--| |----------- |
| |element2 \ / | | | |
| -------------------------------- |
| W3C event model |
------------------------------------------
Interface
From w3.org, for event capture:
If the capturing EventListener wishes to prevent further processing of
the event from occurring it may call the stopPropagation method of the
Event interface. This will prevent further dispatch of the event,
although additional EventListeners registered at the same hierarchy
level will still receive the event. Once an event's stopPropagation
method has been called, further calls to that method have no
additional effect. If no additional capturers exist and
stopPropagation has not been called, the event triggers the
appropriate EventListeners on the target itself.
For event bubbling:
Any event handler may choose to prevent further event propagation by
calling the stopPropagation method of the Event interface. If any
EventListener calls this method, all additional EventListeners on the
current EventTarget will be triggered but bubbling will cease at that
level. Only one call to stopPropagation is required to prevent further
bubbling.
For event cancelation:
Cancelation is accomplished by calling the Event's preventDefault
method. If one or more EventListeners call preventDefault during
any phase of event flow the default action will be canceled.
Examples
In the following examples, a click on the hyperlink in the web browser triggers the event's flow (the event listeners are executed) and the event target's default action (a new tab is opened).
HTML:
<div id="a">
<a id="b" href="http://www.google.com/" target="_blank">Google</a>
</div>
<p id="c"></p>
JavaScript:
var el = document.getElementById("c");
function capturingOnClick1(ev) {
el.innerHTML += "DIV event capture<br>";
}
function capturingOnClick2(ev) {
el.innerHTML += "A event capture<br>";
}
function bubblingOnClick1(ev) {
el.innerHTML += "DIV event bubbling<br>";
}
function bubblingOnClick2(ev) {
el.innerHTML += "A event bubbling<br>";
}
// The 3rd parameter useCapture makes the event listener capturing (false by default)
document.getElementById("a").addEventListener("click", capturingOnClick1, true);
document.getElementById("b").addEventListener("click", capturingOnClick2, true);
document.getElementById("a").addEventListener("click", bubblingOnClick1, false);
document.getElementById("b").addEventListener("click", bubblingOnClick2, false);
Example 1: it results in the output
DIV event capture
A event capture
A event bubbling
DIV event bubbling
Example 2: adding stopPropagation() to the function
function capturingOnClick1(ev) {
el.innerHTML += "DIV event capture<br>";
ev.stopPropagation();
}
results in the output
DIV event capture
The event listener prevented further downward and upward propagation of the event. However it did not prevent the default action (a new tab opening).
Example 3: adding stopPropagation() to the function
function capturingOnClick2(ev) {
el.innerHTML += "A event capture<br>";
ev.stopPropagation();
}
or the function
function bubblingOnClick2(ev) {
el.innerHTML += "A event bubbling<br>";
ev.stopPropagation();
}
results in the output
DIV event capture
A event capture
A event bubbling
This is because both event listeners are registered on the same event target. The event listeners prevented further upward propagation of the event. However they did not prevent the default action (a new tab opening).
Example 4: adding preventDefault() to any function, for instance
function capturingOnClick1(ev) {
el.innerHTML += "DIV event capture<br>";
ev.preventDefault();
}
prevents a new tab from opening.
return false;
return false; does 3 separate things when you call it:
event.preventDefault() – It stops the browsers default behaviour.
event.stopPropagation() – It prevents the event from propagating (or “bubbling up”) the DOM.
Stops callback execution and returns immediately when called.
Note that this behaviour differs from normal (non-jQuery) event handlers, in which, notably, return false does not stop the event from bubbling up.
preventDefault();
preventDefault(); does one thing: It stops the browsers default behaviour.
When to use them?
We know what they do but when to use them? Simply it depends on what you want to accomplish. Use preventDefault(); if you want to “just” prevent the default browser behaviour. Use return false; when you want to prevent the default browser behaviour and prevent the event from propagating the DOM. In most situations where you would use return false; what you really want is preventDefault().
Examples:
Let’s try to understand with examples:
We will see pure JAVASCRIPT example
Example 1:
<div onclick='executeParent()'>
<a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
function executeChild() {
alert('Link Clicked');
}
function executeParent() {
alert('div Clicked');
}
</script>
Run the above code you will see the hyperlink ‘Click here to visit
stackoverflow.com‘ now if you click on that link first you will get
the javascript alert Link Clicked Next you will get the javascript
alert div Clicked and immediately you will be redirected to
stackoverflow.com.
Example 2:
<div onclick='executeParent()'>
<a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
function executeChild() {
event.preventDefault();
event.currentTarget.innerHTML = 'Click event prevented'
alert('Link Clicked');
}
function executeParent() {
alert('div Clicked');
}
</script>
Run the above code you will see the hyperlink ‘Click here to visit
stackoverflow.com‘ now if you click on that link first you will get
the javascript alert Link Clicked Next you will get the javascript
alert div Clicked Next you will see the hyperlink ‘Click here to
visit stackoverflow.com‘ replaced by the text ‘Click event prevented‘
and you will not be redirected to stackoverflow.com. This is due > to event.preventDefault() method we used to prevent the default click
action to be triggered.
Example 3:
<div onclick='executeParent()'>
<a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
function executeChild() {
event.stopPropagation();
event.currentTarget.innerHTML = 'Click event prevented'
alert('Link Clicked');
}
function executeParent() {
alert('div Clicked');
}
</script>
This time if you click on Link the function executeParent() will not
be called and you will not get the javascript alert div Clicked
this time. This is due to us having prevented the propagation to the
parent div using event.stopPropagation() method. Next you will see the
hyperlink ‘Click here to visit stackoverflow.com‘ replaced by the text
‘Click event is going to be executed‘ and immediately you will be
redirected to stackoverflow.com. This is because we haven’t prevented
the default click action from triggering this time using
event.preventDefault() method.
Example 4:
<div onclick='executeParent()'>
<a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
function executeChild() {
event.preventDefault();
event.stopPropagation();
event.currentTarget.innerHTML = 'Click event prevented'
alert('Link Clicked');
}
function executeParent() {
alert('Div Clicked');
}
</script>
If you click on the Link, the function executeParent() will not be
called and you will not get the javascript alert. This is due to us
having prevented the propagation to the parent div using
event.stopPropagation() method. Next you will see the hyperlink ‘Click
here to visit stackoverflow.com‘ replaced by the text ‘Click event
prevented‘ and you will not be redirected to stackoverflow.com. This
is because we have prevented the default click action from triggering
this time using event.preventDefault() method.
Example 5:
For return false I have three examples and all appear to be doing the exact same thing (just returning false), but in reality the
results are quite different. Here's what actually happens in each of
the above.
cases:
Returning false from an inline event handler prevents the browser from navigating to the link address, but it doesn't stop the event from propagating through the DOM.
Returning false from a jQuery event handler prevents the browser from navigating to the link address and it stops the event from propagating through the DOM.
Returning false from a regular DOM event handler does absolutely nothing.
Will see all three example.
Inline return false.
<div onclick='executeParent()'>
<a href='https://stackoverflow.com' onclick='return false'>Click here to visit stackoverflow.com</a>
</div>
<script>
var link = document.querySelector('a');
link.addEventListener('click', function() {
event.currentTarget.innerHTML = 'Click event prevented using inline html'
alert('Link Clicked');
});
function executeParent() {
alert('Div Clicked');
}
</script>
Returning false from a jQuery event handler.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<a href='https://stackoverflow.com'>Click here to visit stackoverflow.com</a>
</div>
<script>
$('a').click(function(event) {
alert('Link Clicked');
$('a').text('Click event prevented using return FALSE');
$('a').contents().unwrap();
return false;
});
$('div').click(function(event) {
alert('Div clicked');
});
</script>
Returning false from a regular DOM event handler.
<div onclick='executeParent()'>
<a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
function executeChild() {
event.currentTarget.innerHTML = 'Click event prevented'
alert('Link Clicked');
return false
}
function executeParent() {
alert('Div Clicked');
}
</script>
Hope these examples are clear. Try executing all these examples in a html file to see how they work.
This is the quote from here
Event.preventDefault
The preventDefault method prevents an event from carrying out its default functionality. For example, you would use preventDefault on an A element to stop clicking that element from leaving the current page:
//clicking the link will *not* allow the user to leave the page
myChildElement.onclick = function(e) {
e.preventDefault();
console.log('brick me!');
};
//clicking the parent node will run the following console statement because event propagation occurs
logo.parentNode.onclick = function(e) {
console.log('you bricked my child!');
};
While the element's default functionality is bricked, the event continues to bubble up the DOM.
Event.stopPropagation
The second method, stopPropagation, allows the event's default functionality to happen but prevents the event from propagating:
//clicking the element will allow the default action to occur but propagation will be stopped...
myChildElement.onclick = function(e) {
e.stopPropagation();
console.log('prop stop! no bubbles!');
};
//since propagation was stopped by the child element's onClick, this message will never be seen!
myChildElement.parentNode.onclick = function(e) {
console.log('you will never see this message!');
};
stopPropagation effectively stops parent elements from knowing about a given event on its child.
While a simple stop method allows us to quickly handle events, it's
important to think about what exactly you want to happen with
bubbling. I'd bet that all a developer really wants is preventDefault
90% of the time! Incorrectly "stopping" an event could cause you
numerous troubles down the line; your plugins may not work and your
third party plugins could be bricked. Or worse yet -- your code
breaks other functionality on a site.
event.preventDefault()
Prevents the browsers default behaviour (such as opening a link), but does not stop the event from bubbling up the DOM.
event.stopPropagation()Prevents the event from bubbling up the DOM, but does not stop the browsers default behaviour.
return false;Usually seen in jQuery code, it Prevents the browsers default behaviour, Prevents the event from bubbling up the
DOM, and immediately Returns from any callback.
Check out this really nice & easy 4 min read with examples from where the above piece was taken.
event.preventDefault(); Stops the default action of an element from happening.
event.stopPropagation(); Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
For example, if there is a link with a click method attached inside of a DIV or FORM that also has a click method attached, it will prevent the DIV or FORM click method from firing.
Event.preventDefault- stops browser default behaviour. Now comes what is browser default behaviour. Assume you have a anchor tag and it has got a href attribute and this anchor tag is nested inside a div tag which has got a click event. Default behaviour of anchor tag is when clicked on the anchor tag it should navigate, but what event.preventDefault does is it stops the navigation in this case. But it never stops the bubbling of event or escalation of event i.e
<div class="container">
Click Me!
</div>
$('.container').on('click', function(e) {
console.log('container was clicked');
});
$('.element').on('click', function(e) {
e.preventDefault(); // Now link won't go anywhere
console.log('element was clicked');
});
The result will be
"element was clicked"
"container was clicked"
Now event.StopPropation it stops bubbling of event or escalation of event. Now with above example
$('.container').on('click', function(e) {
console.log('container was clicked');
});
$('.element').on('click', function(e) {
e.preventDefault(); // Now link won't go anywhere
e.stopPropagation(); // Now the event won't bubble up
console.log('element was clicked');
});
Result will be
"element was clicked"
For more info refer this link
https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/
$("#but").click(function(event){
console.log("hello");
event.preventDefault();
});
$("#foo").click(function(){
alert("parent click event fired !");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
<button id="but">button</button>
</div>

Categories

Resources