<button id="add-div-button">
Click to add the div
<'/button>
jQuery:
// Build the div element as a string and then prepend it
$('#add-div-button').click(function() {
var strDiv = ';
strDiv += 'Double-click to switch the text and background colors.';
strDiv += ';
$('body').prepend(strDiv);
});
// Set up the div with a double-click event handler
$('#my-div').on('dblclick', function() {
if($('#my-div').css('color') === 'rgb(255, 250, 205)') {
$('#my-div').css('color', 'darkgreen');
$('#my-div').css('background-color', 'lemonchiffon');
} else {
$('#my-div').css('color', 'lemonchiffon');
$('#my-div').css('background-color', 'darkgreen');
}
});
When you click the button, the first jQuery event handler builds a div
element as a string and then uses prepend
to add it to the body
element. That div
element uses the id
value my-div
. However, the second jQuery event handler is for a dblclick
event on that same my-div
element. Theoretically, the dblclick
handler switches the element's text and background colors, but if you try this example, you can double-click the div
until your finger falls off and nothing will happen.
Why doesn’t the event handler handle anything? Because when the browser was loading the page and came upon the code for the dblclick
event handler, the target — that is, the div
with the id
value my-div
— didn't yet exist, so the browser ignored that event handler.
To fix this problem, you use a jQuery technique called event delegation, which means you do two things:
- You bind the event handler not to the element itself, but to an ancestor element higher up in the web page hierarchy. This needs to be an element that exists when the web browser parses the event handler.
- Add an extra parameter to the
on()
method that specifies which element your click handler actually applies to.
on()
method:
$(ancestor).on(event, descendant, function() {
This code runs when the event fires
});
ancestor
: A selector that specifies the ancestor element that is delegated to be monitored for the eventevent
: A string specifying the name of event you want the browser to listen fordescendant
: A selector that specifies the descendant element ofancestor
that's the actual target of the eventfunction()
: The callback function that jQuery executes when the event occurs
on()
method delegates the event handler to the ancestor
element. When the event fires, the ancestor
element looks through its descendants until it finds the element or set given by descendant
, and it then runs the handler with that element or set as the event target.To fix the previous example, you could use the document
object as the ancestor
argument, and add #my-div
as the descendant argument:
$(document).on('dblclick', '#my-div', function() {
When choosing which ancestor to use as the delegate, the best practice is to use the closest ancestor that exists when the browser processes the event handler. For example, if in the example you were appending the div
to, say, an existing article
element, it would be better to use that article
element as the delegate than the document
object. Why is it better, you ask? Because the further away the ancestor, the more descendants the ancestor has to run through before it finds the event target, which can be a real drag on performance.