I found that the simplest way to handle all of this is to make use of
the context parameter of jQuery. Basically write your attachBehaviors
function like this:
var attachBehaviors = function(context)
{
context = context || document;
$('a', context).bind('click', ...);
$('#product', context).bind('mouseover', ...);
// etc.
}
Then whenever you load some new content via ajax all you have to do is
to pass a context element as a parameter to attachBehaviors. This will
usually be the element that you updated using ajax ; ).
Let me know if this is good enough for what you are trying to do?
-- Felix Geisendörfer
--------------------------
http://www.thinkingphp.org
http://www.fg-webdesign.de
Nedjo Rogers wrote:
As site developers using jQuery, we often attach jQuery behaviours through
an attach function that's registered with $(document).ready();. Typically,
behaviours attach to content identified by jQuery selectors, e.g., id or
class values. This works great for the initial DOM ready state. But how can
we ensure that these same behaviours are also attached to content loaded via
ajax?
Of course, if I'm using all my own behaviours I can simply hack them to
apply to ajax-loaded content. But the question is, how can we structure all
our behaviours in such a way that others can use them for both 'normal' and
ajax-loaded content?
There are two parts to this issue:
_____
(a) Behaviours list: How can we know what behaviours need to be reattached?
To reattach all behaviours to newly loaded and rendered content, we need to
know what behaviours exist.
(b) Avoiding duplication: How can we ensure that behaviours are attached
only to newly loaded content?
If we simply rerun the original attachment code, we may end up with multiple
behaviour instances attached to individual elements that the behavours were
already attached to.
_____
A concrete example: in Drupal we have various jQuery behaviours that may be
attached to content on page ready: autocomplete text fields, collapsing
fieldsets, etc. These are registered through $(document).ready. If we ajax
load and render new content, though, it doesn't get the behaviours and so is
broken. If we manually call the functions that attach the behaviours, we get
duplicate behaviours (e.g., two icons for collapsing fieldsets).
Issue (b) seems relatively easy to address. One way is by filtering the
jQuery selector by class name and then adding that class to all processed
content:
$('div.mybehavior:not(.mybehavior-processed)').each(function() {
$(this)
...
.addClass('mybehavior-processed');
});
Is this the best way?
Issue (a) is more difficult. We can't rely on what was registered through
$(document).ready() because the jQuery.readyList is emptied after being
used.
One possible approach would be to extend jQuery with array of behaviours.
Here's a rough idea:
jQuery.extend({
behaviors: [],
registerBehavior: function(attachFunction) {
jQuery.behaviors.push(attachFunction);
jQuery.readyList.push(attachFunction);
});
jQuery.each(
attachBehaviors: function() {
var elt = this;
if ( jQuery.behaviors) {
// Execute all of them
jQuery.each( jQuery.behaviors, function(){
this.apply( elt );
});
}
});
Then, for behaviours, we would register them with
$.registerBehavior(mybehaviourAttach);
and then call after ajax-loading content with
$(elt).attachBehaviors();
Is this a good general approach? Are there better solutions? What are people
currently doing to address this issue?
Thanks,
Nedjo Rogers
_______________________________________________
jQuery mailing list
discuss@jquery.com
http://jquery.com/discuss/
_______________________________________________
jQuery mailing list
discuss@jquery.com
http://jquery.com/discuss/