I am using Backbone here, but I’ve also experienced this issue with non-Backbone sites as well.
Essentially, my issue is that I define in one javascript file, base.js, a number of ‘global’ jquery functions. Then, I load new elements and append them to the page using Backbone, AJAX, or whichever asynchronous call you like. This works great, except the new objects don’t seem to be linked to the jQuery events I declared on pageload. (Sorry for the layman language here – often I am a newbie at proper wording)
For example, let’s say I declare in a js file loaded on pageload:
$('.element').hover(function(){alert('hi world')});
But then I append a new element after pageload, then this hover won’t work.
Can anyone explain:
- Why this is?
- Whether I can force a new appended element to work with/listen to current events already declared?
I suspect (2) may not be possible (that I have to rewrite the events after appending), but am interested to know if there is some sort of solution.
Because when the event binding code is executed, elements that do not exist in the DOM already will not be affected (how could they be? They don’t exist yet!) The “normal” event binding methods (e.g.
.click()or.change()) will attach a copy of the event handler function to every element in the matched set.You can indeed, by delegating the event handler higher up the DOM tree. Since most DOM events bubble up the tree from the element on which they originate, this works well. With jQuery, you can use the
.on()(jQuery 1.7+ – for older versions use.delegate()instead) method to do this:The element on which you call
.on()must exist in the DOM at the time the code runs. When the event bubbles up far enough to reach whatever#someCommonAncestormay be, jQuery will check to see if the target element matched the selector you passed to.on(). If it does, it will execute the event handler. If it doesn’t, the event will continue bubbling to the root of the document and not trigger any handler.