Is it considered 'good practice' to stop JavaScript event propagation - does it benefit performance in any way?
I'm wondering if there is benefit outside of layout purposes where you stop propagation so you don't trigger multiple events accidentially.
It entirely depends on the DOM complexity and the actions taken in each event that is triggered.
You would stop propagating events mainly not because of complexity but because of unwanted actions not to take place.
For eg: Consider a situation where you have a show hide div and when you click on the div it should opne and if you click anywhere else in the document it should close.
So you would wire an onclick event handler to the document as well as the div. So you have to stop propagating the event when clicked on the div so that the document click handler won't be invoked. Thats a situation where you use stop event propagtion.
Only when it is necessary to the program logic, such as to prevent form submission or another DOM element's action being triggered. Unless you have a seriously complex DOM tree, there will not be any serious performance hit.
Related
I have a Javascript mobile app that had an initial problem of touch down resulting in refreshing of the page. To counteract that, I added a ontouchmove attribute on my div tag where in the javascript I stop propagation (event.stopPropagation())
Context of the screen :
Asks a simple question, with 4 radio button options, and 2 buttons. The two buttons are being cut off after I've stopping the propagation. Confused how the bubbling of parent tags are impacting my buttons being cutoff.
Share the code so that everyone can better understand the problem.
From your statement above I could infer that some event which was vital for your screen has also stopped because of your stopPropagation call.
stop propagation should be the last resort, rather you can add your event to a specific component or add class to all components for which you need to listen to the event so as to avoid bubbling on the whole screen.
I am using a delegated event handler (jQuery) in my JavaScript code so stuff happens when dynamically added buttons are clicked.
I'm wondering are there performance drawbacks to this?
// Delegated event handler
$(document).on('click', '#dynamicallyAddedButton', function(){
console.log("Hello");
});
How would it compare to this, performance-wise?
// Regular event handler
$("#regularButton").on('click', function(){
console.log("Hello Again");
});
Looking at the jQuery documentation, it seems that events always bubble all the way up the DOM tree. Does that mean that the further nested an element is, the longer an event will take to work?
Edit: Is there a performance benefit to using JavaScript's event delegation rather than jQuery's? is asking a similar question, and the answer there is useful. I am wondering what the difference is between using a regular event handler and a delegated event handler. The linked questions make it seem like events are constantly bubbling up the DOM tree. With a delegated event handler does the event bubble up to the top and then back down to the specified element?
Every time you click pretty much anywhere in the document, the event is going to be manually bubbled up to the document element (after the natural bubbling takes place) and will run the selector engine for every element between the clicked element and the document.
So if you click on an element nested 20 elements deep, the selector engine will run 20 times for that one click.
Furthermore, this will happen for every selector the document has. So if you give it 20 selectors and click 20 elements deep, the selector engine has to run 400 times for that one click. (The manual bubbling happens only once, of course.)
Selector-based delegation is fine, but try to keep it closer to the targeted element(s) if possible.
When creating click events, I do my best to bind them only once – generally to a parent shared by all the nodes expected to trigger the event. I'm curious, however, what the best practice is with mouseover events: Does it still make sense to bind an event to a parent when the result would be the constant firing of the event on mouseover? What's the most efficient practice?
In order to provide some closure to this question, I'm going to paraphrase/quote some relevant notes from this answer: 'Should all jquery events be bound to $(document)?', which was referenced above by #Faust:
Event delegation does not always make your code faster. Unless you're binding to dynamic elements or a ton of elements, you should bind event handlers directly to the objects where the event happens as this will generally be more efficient.
More specifically, here are times when event delegation is required or advantageous:
When the objects you are capturing events on are dynamically created/removed and you still want to capture events on them without having to explicitly rebind event handlers every time you create a new one.
When you have lots of objects that all want the exact same event handler (where lots is at least hundreds). In this case, it may be more efficient at setup time to bind one delegated event handler rather than hundreds or more direct event handlers. Note, delegated event handling is always less efficient at run-time than direct event handlers.
When you're trying to capture (at a higher level in your document) events that occur on any element in the document.
When your design is explicitly using event bubbling and stopPropagation() to solve some problem or feature in your page.
Original answer by #jfriend00
So, I know this question is long dead, but I figured I might as well answer with a way to do this.
With dynamic-elements, you can establish a mousemove listener on the parent div/container, and then query within the div for elements with a :hover attribute.
For example:
<div class="list-container">
<ul class="dynamic-list-content">
<!-- actual list elements provided by js -->
</ul>
</div>
Then:
var listContainer = document.querySelector('.list-container');
listContainer.addEventListener('mousemove', function(e) {
var hovered = listContainer.querySelector('li:hover');
// do something with the hovered element here.
});
Note that (as you mentioned) this will fire a lot, but no more than if you added a mousemove event listener to the individual entries. And you could debounce this a bit, using data-attributes, unique ids, etc. From my tests though, it's pretty performant in Chrome.
you can also stop the propagation of events. More info here: http://api.jquery.com/event.stoppropagation/ and here event.preventDefault() vs. return false
I figure other developers have run into this before. We have a large code base with many components following this pattern:
$('#elm').on('click',function($e){
$e.stopPropagation();
//... do stuff (i.e. Open something);
});
$('html').on('click',function($e){
//... do oposite of stuff (i.e. Close something);
}
Our issue is, all the stopPropagation's across the site are stopping closing of other components. What we really want is a mechanism to only block the click handler for this component but not for others.
I'm looking for a solution which is the easiest to implement right now to fix our bugs and for our Multi-developer team to follow in the future.
The .live() method handles events once they have propagated to the top of the document, it is not possible to stop propagation using live events this allows you to do hack and take advantage of this because the .live() method binds a handler to the $(document), and identifies which element triggered the event up at the top of the hierarchy using the event.target property.
The stopPropagation stops the propagation from bubbling up the DOM hierarchy, but since the handler is at the document level there is no upper place to propogate to.
On the other hand note that events handled by .delegate() will bubble up to the elements to which they are binded to; event handlers bound on any elements below it in the DOM tree will already have been executed by the time the delegated event handler is called. These handlers, therefore, may prevent the delegated handler from triggering by calling event.stopPropagation()
See this example: http://jsfiddle.net/knr3v/2/
Therefore you can use the live and delegate method instead of click, bind, on method to do exactly what you are explaining.
In the case of a game where user have to click/use keys mutli and many times,
Is there any advantage to use event.stopPropagation() in all event
handler which i know bubbling is useless?
Suppose i have a div with a click event binded,
<div id="mydiv">CLICK</div>
$('#mydiv').click(function(){...});
if i click on it, this event will propagate to all ancestors elements of this div (e.g body/html/document/window). So just wondering if this could be better or same or worst to stop immediatly propagation of event.
In fact, i don't know how javascript engine internally deal with events binded (or not) to elements, if this works as a listener or what...
It is a bit general, but to answer your direct question, unless you need to stop propagation then there is no reason to do so. Propagation is not what is going to hinder the efficiency of your game, it's having too many event bindings. Consider using a generic binding on a parent element and then processing the actual target of the event to determine what action to take.