Configurable Javascript In Place Editor

Why do we need another in place edit library for Javascript? This one is different of course! This library allows for a high degree of customization due to its modular nature. Each action on an in place edit object (submitting on blur, adding a class on focus, toggling a label on click, etc) is complete isolated and designed to stack with each other. This allows for one library to accomplish a wide variety of in place edit functionality in the same project. You can even have different functionality on the same page if you wish.

Setup is a breeze. Just grab the latest copy of the Javascript library from https://github.com/bsimpson/in_place_edit. You will need to be using jQuery in your project, since this plugin depends on it to work. Once you have include both jQuery, and in_place_edit.js, you can initialize it like this:

  $(function() {
    $('.in_place_edit').inPlaceEdit();
  });

The argument passed is the CSS selector that contains the form on which you wish to use in place edit.

Next, we need to configure the form to tell it what actions we want it to perform. If we want basic edit in place functionality, we can add “submit_on_blur” to have the form submit when a blur event is received. Note that this only occurs if the contents of the form have changed, in order to save on the number of server posts.

<div class="in_place_edit" data-in_place_data="submit_on_blur">
  <form action="#" method="post">
    <input type="text" name="foo" value="foo" />
  </form>
</div>

The options are simple, and the combination are many. Check out the following options to see what you can do with your form fields on the DEMO page.

Happy in place editing!

Update: This plugin has been updated to be a jQuery plugin. Thanks to jsumners for providing lots of help!

Rail’s Acts_as_revisable now summarizes changes

If you are a frequent reader, please congratulate me next time you see me on my first ever GiHub commit. I have been a long time user of GitHub, but I haven’t contributed anything back yet. I decided to start with the project acts_as_revisable, because I have some ideas for it that I think are useful.

The commit tonight adds a “revisable_changes” column, which records the attributes “before” and “after” values in the revision record. This data is calculated from the ActiveRecord instance method “changes”. To demonstrate:

# User.create :username => 'ben'
#<User id: 1, username: "ben", revisable_changes: {"username"=>[nil, "ben"]}>
# User.find(1).update_attributes :username => 'bob'
#<User id: 1, username: "ben", revisable_changes: {"username"=>["ben", "bob"]}>

This should serve as a good base to build summaries in a human readable format in an application. After tossing around a few different word choices to describe the changes, I decided that the better approach was to just record the data that changed in a structured format and leave it up to the implementation. Such an implementation may look something like this:

  def changes_summary
    self.revisable_changes.map do |attribute, values|
      before, after = values[0], values[1]
      if before.blank? and after
        "Added #{attribute} as #{after}"
      elsif before and after.blank?
        "Removed #{attribute} value of #{before}"
      else
        "Changed #{attribute} from #{before} to #{after}"
      end
    end.join('; ')
  end

Using our user instance above, this method out return: “Changed username from ben to bob”.

Other plans for acts_as_revisable in the future include tracking associations of a model. For example, if a user has many permissions, and the permissions change, the revisable information will include the permissions for that user at that point in time. I haven’t worked out the specifics of this yet, as it could potentially generate a lot of unwanted data. I plan on parsing the data from ActiveRecord’s “reflect_on_all_associations” method to gather the associations. I will then provide a way for a user to configure which associations should, or should not be tracked. Then I will iterate through these objects using ActiveRecord hooks and somehow record the state. Either a shadow table, or by serializing the associations in a column. The trick here will be to marshal the objects back to the live data when a revert is called. More soon…