title: Ruby on Rails with jQuery
body: <p>Hi
  I just came across an article about how to combine Rails with jQuery.<br>
  <a href="http://blog.bernatfarrero.com/category/ror/" rel="nofollow">http://blog.bernatfarrero.com/category/ror/</a><br>
  I followed the instructions but I couldn't make it work (instead of using ajax rails tried the non-javascript way of handling the request). After I downloaded the source code i found out what the problem was. In the source in public/javascripts there is a file jquery-rails.js which is connected with the line</p>
  
  <pre><code>javascript_include_tag "jquery-rails.js" 
  </code></pre>
  
  <p>in application.html.erb. If I change the name of that file in the line above it doesn't work anymore. So I tried to change the original name of a driver file downloaded form here: <a href="http://docs.jquery.com/Downloading_jQuery#Download_jQuery" rel="nofollow">http://docs.jquery.com/Downloading_jQuery#Download_jQuery</a> (many different versions) to the one I found in the source. Of course I placed it in the same directory too. And again it failed to work... So finally i compared the files. What I so was that the file from the source was much shorter. Well I'm a real beginner to JS so I must ask you for help here. Why doesn't it work? How to make Rails work with the original jQuery driver?<br>
  Bye  </p>
  
  <p>Below you can see the 'jquery-rails.js'  from the source</p>
  
  <pre><code>jQuery(function ($) {
  var csrf_token = $('meta[name=csrf-token]').attr('content'),
      csrf_param = $('meta[name=csrf-param]').attr('content');
  
  $.fn.extend({
      /**
       * Triggers a custom event on an element and returns the event result
       * this is used to get around not being able to ensure callbacks are placed
       * at the end of the chain.
       *
       * TODO: deprecate with jQuery 1.4.2 release, in favor of subscribing to our
       *       own events and placing ourselves at the end of the chain.
       */
      triggerAndReturn: function (name, data) {
          var event = new $.Event(name);
          this.trigger(event, data);
  
          return event.result !== false;
      },
  
      /**
       * Handles execution of remote calls firing overridable events along the way
       */
      callRemote: function () {
          var el      = this,
              data    = el.is('form') ? el.serializeArray() : [],
              method  = el.attr('method') || el.attr('data-method') || 'GET',
              url     = el.attr('action') || el.attr('href');
  
          if (url === undefined) {
            throw "No URL specified for remote call (action or href must be present).";
          } else {
              if (el.triggerAndReturn('ajax:before')) {
                  $.ajax({
                      url: url,
                      data: data,
                      dataType: 'script',
                      type: method.toUpperCase(),
                      beforeSend: function (xhr) {
                          el.trigger('ajax:loading', xhr);
                      },
                      success: function (data, status, xhr) {
                          el.trigger('ajax:success', [data, status, xhr]);
                      },
                      complete: function (xhr) {
                          el.trigger('ajax:complete', xhr);
                      },
                      error: function (xhr, status, error) {
                          el.trigger('ajax:failure', [xhr, status, error]);
                      }
                  });
              }
  
              el.trigger('ajax:after');
          }
      }
  });
  
  /**
   *  confirmation handler
   */
  $('a[data-confirm],input[data-confirm]').live('click', function () {
      var el = $(this);
      if (el.triggerAndReturn('confirm')) {
          if (!confirm(el.attr('data-confirm'))) {
              return false;
          }
      }
  });
  
  
  /**
   * remote handlers
   */
  $('form[data-remote]').live('submit', function (e) {
      $(this).callRemote();
      e.preventDefault();
  });
  
  $('a[data-remote],input[data-remote]').live('click', function (e) {
      $(this).callRemote();
      e.preventDefault();
  });
  
  $('a[data-method]:not([data-remote])').live('click', function (e){
      var link = $(this),
          href = link.attr('href'),
          method = link.attr('data-method'),
          form = $('&lt;form method="post" action="'+href+'"&gt;&lt;/form&gt;'),
          metadata_input = '&lt;input name="_method" value="'+method+'" type="hidden" /&gt;';
  
      if (csrf_param != null &amp;&amp; csrf_token != null) {
        metadata_input += '&lt;input name="'+csrf_param+'" value="'+csrf_token+'" type="hidden" /&gt;';
      }
  
      form.hide()
          .append(metadata_input)
          .appendTo('body');
  
      e.preventDefault();
      form.submit();
  });
  
  /**
   * disable-with handlers
   */
  var disable_with_input_selector = 'input[data-disable-with]';
  var disable_with_form_selector = 'form[data-remote]:has(' + disable_with_input_selector + ')';
  
  $(disable_with_form_selector).live('ajax:before', function () {
      $(this).find(disable_with_input_selector).each(function () {
          var input = $(this);
          input.data('enable-with', input.val())
               .attr('value', input.attr('data-disable-with'))
               .attr('disabled', 'disabled');
      });
  });
  
  $(disable_with_form_selector).live('ajax:after', function () {
      $(this).find(disable_with_input_selector).each(function () {
          var input = $(this);
          input.removeAttr('disabled')
               .val(input.data('enable-with'));
      });
  });
  </code></pre>
  
  <p>});</p>