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/

Reply via email to