(function($) {
  $.fn.extend({
    ajaxForm: function(options) {
      options = options || {};
      
      this.each(function() {
        var $this = $(this).submit(function(e) {
          e.preventDefault();
          
          var data = $this.serializeArray();
          
          if (options.loading) {
            // exit if false is returned.
            if (options.loading.call($this, data) === false) {
              return;
            }
          }
          
          $.ajax({
            data: data,
            dataType: "json",
            type: "POST",
            url: $this.attr("action"),
            success: function(data, textStatus) {
              if (options.success) {
                options.success.call($this, data);
              }
            },
            error: function(xhr, textStatus, error) {
              if (options.error) {
                options.error.call($this, textStatus);
              }
            }
          });
          
          // When submitting a form programmatically, preventDefault() doesn't work.
          return false;
        });
      });
      
      return this;
    }
  });
  
  $.ajaxSetup({
    "beforeSend": function(xhr) {
      xhr.setRequestHeader("Accept", "text/javascript");
    }
  });
})(jQuery);
