Search code examples
jqueryajaxruby-on-rails-3edit-in-place

Rails 3 In-Place Editing


I'm trying to implement in-place editing in a Rails 3 app that takes the edited value and revises a calculation based on that value. For example:

Before edit of the "credits to donate" field:
You have 10 credits remaining. Credits to donate: 0.

After edit of the "credits to donate" field:
You have 5 credits remaining. Credits to donate: 5.

I have looked into various options, and it looks like the jquery-in-place-editor does what I'm looking for. For reference:

The demo works. But I think what I need to do is use the callback function to call a ruby script, so I can do some more processing. I'm not entirely sure if that's what I need to do though, so I'm looking for some guidance.

Here is the jQuery javascript (from /public/javascripts/application.js in the Sample app) that I think is relevant:

// Using a callback function to update 2 divs
$("#editme4").editInPlace({
    callback: function(original_element, html, original){
        $("#updateDiv1").html("The original html was: " + original);
        $("#updateDiv2").html("The updated text is: " + html);
        return(html);
    }
});

It looks like what I need to do is take original and html and play around with them a bit, then feed them back to the appropriate divs. The question is, how do I do this? I'm thinking of two possibilities:

A. There is a facility in the jquery-in-place-editor to call a url. Could I use this to call a ruby script and get a result? How would I do this in rails? Here is code to call a url (again from /public/javascripts/application.js); but it calls a php script.

$("#editme1").editInPlace({
    // callback: function(unused, enteredText) { return enteredText; },
    url: 'server.php',
    show_buttons: true
});

B. Modify the updated text directly in javascript, and pass it to the appropriate divs. I'd prefer to use a ruby script, but maybe this would be easier.


Solution

  • The solution to this problem is quite complex, but I have found a way to do it. It is surprising to me that the solution is not readily available, since it does seem, as r-dub says, something that is quite common. I ended up not using any of the edit-in-place facilities of a jQuery plugin, and instead modified a text field directly with the help of jQuery on the basis of a form text field. I other words, I followed (B) above.

    I have a view that looks like this:

    Available: <span id="available_cr"><%= @available_credits %></span>
    Remaining: <span id="remaining_cr"><%= @remaining_credits %></span>
    
    <%= form_for(@page, :html => { :id => 'do_fvalue' }, :remote => true) do |f| %>
      <div class="field">
        How many to buy at <%= @cost %> credits per unit? <%= f.text_field :fvalue, :autocomplete => :off %>
      </div>
      <div class="field">
        How many to buy at <%= @cost_20 %> credits per unit? <%= f.text_field :gvalue, :autocomplete => :off %>
      </div>
      <div class="actions">
        <%= f.submit "Update" %>
      </div>
    <% end %>
    

    I then stuff the rails @-variables into a .html.erb partial (rendered at the beginning of my page .html.erb) so that javascript/jQuery can access them:

    <script type="text/javascript">
      var cost = parseInt(<%= @cost %>)
      var cost_20 = parseInt(<%= @cost_20 %>)
      var available_credits = parseInt(<%= @available_credits %>)
      var remaining_credits = parseInt(<%= @remaining_credits %>)
    </script>
    

    Then, in public/javascripts/applications.js, I have the following code:

    function checkFields(){
      var to_buy_f = $("#page_fvalue").val();
      var to_buy_g = $("#page_gvalue").val();
      var subtract_f = to_buy_f * cost;
      var subtract_g = to_buy_g * cost_20;
      var remain = available_credits - subtract_f - subtract_g;
      $("#remaining_cr").text(remain);
    };
    
    $("#page_fvalue").keyup(function () {
       checkFields();
    }).keyup();
    
    $("#page_gvalue").keyup(function () {
       checkFields();
    }).keyup();
    

    The checkFields function updates #remaining_cr based on the values found in #page_fvalue and #page_gvalue. Notice that it makes use of available_credits, cost, and cost_20, which we stuffed into the javascript variables above. The last two functions tell jQuery to monitor #page_fvalue and #page_gvalue for keyup events. When the user presses a key, it calls checkFields() to update #remaining_cr.

    All of this aside, when the user clicks "submit" on the form, the whole form gets submitted with the current values. I don't know whether this is the most efficient way to do what I was trying to do, but it works!