As of jQuery 1.7 you should use jQuery.fn.on
with the selector parameter filled:
$(staticAncestors).on(eventName, dynamicChild, function() {});
Explanation:
This is called event delegation and works as followed. The event is attached to a static parent (staticAncestors
) of the element that should be handled. This jQuery handler is triggered every time the event triggers on this element or one of the descendant elements. The handler then checks if the element that triggered the event matches your selector (dynamicChild
). When there is a match then your custom handler function is executed.
Prior to this, the recommended approach was to use live()
:
$(selector).live( eventName, function(){} );
However, live()
was deprecated in 1.7 in favour of on()
, and completely removed in 1.9. The live()
signature:
$(selector).live( eventName, function(){} );
... can be replaced with the following on()
signature:
$(document).on( eventName, selector, function(){} );
For example, if your page was dynamically creating elements with the class name dosomething
you would bind the event to a parent which already exists (this is the nub of the problem here, you need something that exists to bind to, don't bind to the dynamic content), this can be (and the easiest option) is document
. Though bear in mind document
may not be the most efficient option.
$(document).on('mouseover mouseout', '.dosomething', function(){
// what you want to happen when mouseover and mouseout
// occurs on elements that match '.dosomething'
});
Any parent that exists at the time the event is bound is fine. For example
$('.buttons').on('click', 'button', function(){
// do something here
});
would apply to
<div class="buttons">
<!-- <button>s that are generated dynamically and added here -->
</div>
Event bubbling and capturing are two ways of event propagation in the HTML DOM API, when an event occurs in an element inside another element, and both elements have registered a handle for that event. The event propagation mode determines in which order the elements receive the event.
With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements.
With capturing, the event is first captured by the outermost element and propagated to the inner elements.
Capturing is also called "trickling", which helps remember the propagation order:
trickle down, bubble up
Back in the old days, Netscape advocated event capturing, while Microsoft promoted event bubbling. Both are part of the W3C Document Object Model Events standard (2000).
IE < 9 uses only event bubbling, whereas IE9+ and all major browsers support both. On the other hand, the performance of event bubbling may be slightly lower for complex DOMs.
We can use the addEventListener(type, listener, useCapture)
to register event handlers for in either bubbling (default) or capturing mode. To use the capturing model pass the third argument as true
.
Example
<div>
<ul>
<li></li>
</ul>
</div>
In the structure above, assume that a click event occurred in the li
element.
In capturing model, the event will be handled by the div
first (click event handlers in the div
will fire first), then in the ul
, then at the last in the target element, li
.
In the bubbling model, the opposite will happen: the event will be first handled by the li
, then by the ul
, and at last by the div
element.
For more information, see
In the example below, if you click on any of the highlighted elements, you can see that the capturing phase of the event propagation flow occurs first, followed by the bubbling phase.
var logElement = document.getElementById('log');
function log(msg) {
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function capture() {
log('capture: ' + this.firstChild.nodeValue.trim());
}
function bubble() {
log('bubble: ' + this.firstChild.nodeValue.trim());
}
function clearOutput() {
logElement.innerHTML = "";
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>
Another example at JSFiddle.
Best Answer
Let's start by describing DOM elements' event handling.
DOM node event handling
First of all you wouldn't want to work with DOM node directly. Instead you probably would want to utilize
Ext.Element
interface. For the purpose of assigning event handlers,Element.addListener
andElement.on
(these are equivalent) were created. So, for example, if we have html:and we want add
click
event handler.Let's retrieve
Element
:Now let's check docs for
click
event. It's handler may have three parameters:Knowing all this stuff we can assign handler:
Widgets event handling
Widgets event handling is pretty much similar to DOM nodes event handling.
First of all, widgets event handling is realized by utilizing
Ext.util.Observable
mixin. In order to handle events properly your widget must containgExt.util.Observable
as a mixin. All built-in widgets (like Panel, Form, Tree, Grid, ...) hasExt.util.Observable
as a mixin by default.For widgets there are two ways of assigning handlers. The first one - is to use on method (or
addListener
). Let's for example createButton
widget and assignclick
event to it. First of all you should check event's docs for handler's arguments:Now let's use
on
:The second way is to use widget's listeners config:
Notice that
Button
widget is a special kind of widgets. Click event can be assigned to this widget by usinghandler
config:Custom events firing
First of all you need to register an event using addEvents method:
Using the
addEvents
method is optional. As comments to this method say there is no need to use this method but it provides place for events documentation.To fire your event use fireEvent method:
arg1, arg2, arg3, /* ... */
will be passed into handler. Now we can handle your event:It's worth mentioning that the best place for inserting addEvents method call is widget's
initComponent
method when you are defining new widget:Preventing event bubbling
To prevent bubbling you can
return false
or useExt.EventObject.preventDefault()
. In order to prevent browser's default action useExt.EventObject.stopPropagation()
.For example let's assign click event handler to our button. And if not left button was clicked prevent default browser action: