Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery: How to apply a function to all elements including some which are loaded later via Ajax?

I have a simple jQuery function that resizes text areas, and I want it to apply to all text areas.

For the most part, this works great:

$(document.ready(function(){$("text_area").resizer('250px')});

However, because it is only called once when the document is ready, it fails to catch text areas that are later added onto the page using Ajax. I looked at the .live() function, which seems very close to what I'm looking. However, .live() must be bound to a specific event, whereas I just need this to fire once when they're done loading (the onLoad event doesn't work for individual elements).

The only thing I can get working is a really obtrusive inclusion of the JavaScript call directly into the Ajax. Is that the recommended way to be doing this?

Edit: Here is the rails source code for what it does for Ajax requests:

$('a[data-confirm], a[data-method], a[data-remote]').live('click.rails', function(e) {
 var link = $(this);
 if (!allowAction(link)) return false;

 if (link.attr('data-remote') != undefined) {
  handleRemote(link);
  return false;
 } else if (link.attr('data-method')) {
  handleMethod(link);
  return false;
 }
});

// Submits "remote" forms and links with ajax
function handleRemote(element) {
 var method, url, data,
  dataType = element.attr('data-type') || ($.ajaxSettings && $.ajaxSettings.dataType);

 if (element.is('form')) {
  method = element.attr('method');
  url = element.attr('action');
  data = element.serializeArray();
  // memoized value from clicked submit button
  var button = element.data('ujs:submit-button');
  if (button) {
   data.push(button);
   element.data('ujs:submit-button', null);
  }
 } else {
  method = element.attr('data-method');
  url = element.attr('href');
  data = null;
 }

 $.ajax({
  url: url, type: method || 'GET', data: data, dataType: dataType,
  // stopping the "ajax:beforeSend" event will cancel the ajax request
  beforeSend: function(xhr, settings) {
   if (settings.dataType === undefined) {
    xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
   }
   return fire(element, 'ajax:beforeSend', [xhr, settings]);
  },
  success: function(data, status, xhr) {
   element.trigger('ajax:success', [data, status, xhr]);
  },
  complete: function(xhr, status) {
   element.trigger('ajax:complete', [xhr, status]);
  },
  error: function(xhr, status, error) {
   element.trigger('ajax:error', [xhr, status, error]);
  }
 });
}

So in my particular case, I've got a link, that has data-remote set to true, which points to a location that will return JavaScript instructing a form containing a text area to be appended to my document.

like image 304
William Jones Avatar asked Jan 19 '23 22:01

William Jones


1 Answers

A simple way to do this would be to use ajaxComplete, which is fired after every AJAX request:

$(document).ajaxComplete(function() {
    $('textarea:not(.processed)').resizer('250px');
});

That says "every time an AJAX request completes, find all textarea elements that don't have the processed class (which seems to be added by the resizer plugin -- terrible name for its purpose!) and call the resizer plugin on them.

You may be able to optimise this further if we could see your AJAX call.

like image 175
lonesomeday Avatar answered Jan 31 '23 05:01

lonesomeday