Another common task in a Web app is to create a register of events. Sometimes you want to email your users about something that happened, others you just want to show somewhere a table with the timeline of recent events. For example, let’s take the example of a project managing application (like the well-known Basecamp of 37Signals).
This comes from the last app in which I worked. I reckon there are two ways to embrace this problem. One involves adding or using the rails default field updated_at of every table in the database. Of course some other handy fields might be added as well, such as updated_by and updating_description. Showing a register of events in this case means taking every model in the database, ordering it by the updating date and limiting the results to a given constant. All of those should be added by the controller to a hash or an array and would later on be globally ordered by the value of the update field, only to be delivered to the views and finally displayed. Nonetheless, this method could get stuff complex over time, specially when using a large set of models, and it gets events dependent to subjects.
Another approach is using a self-contained concept of event. Everything done in the system is recorded and added to a register, to which we can access whenever we please and display it. As usual, someone has had this problem before and created a useful plugin for us, in this case it’s called timeline_fu. I added though a very small modification to serve my purposes.
I thought many times how Google could evolve to be a searcher in the real life as well. By approaching the market of personal gadgets, like phones, it was taking giant steps. Now it’s time to get real, have a look at this:
Google Goggles will be available from Android 1.6 on.
Update: As some people who have tried told me, it works pretty good with text and logos, but it is still far to properly recognize objects. However, as most of Google’s, this is a learning technology. If people start using it will fastly improve its recognition capacity. It is curious to note that Google stated this could work as well with people’s faces though their turned it off “for privacy concerns”. It is scaring, specially after the comments of Google’s CEO Eric Schmidt.
My last post addressed the need to get a decent WYSIWYG tool and/or a markup language so as to input formatted data to your web application. Today though this is just not enough. The concept in everyone’s mouth is Web 2.0 and, if something, this means giving users the full control to enrich their webs. That is, if there’s a header here or a description there she’d like to change, it should be done with little to no effort! Why not just clicking on it and typing the new text? This is the concept behind in-place-editing.
I’d say, hopefully not mistakenly, this feature was made popular by Flickr. There you can do and undo almost everything very much like a desktop application, and that is our aim as well.
Example of flickr in place editing
There could be a lot of chin-wagging on in-place-editing, but I’ll focus on how to set up the native Railsplugin for this, which works with Prototype and Scriptaculous. If someone is interested in using jQuery and a good library for inline edit, I recommend Jeditable, it’s beautiful and simple to use. One day I’ll get my hands dirty talking about my opinion on Javascript frameworks and their pros and cons, but not today. Some people prefer to use the default Prototype and Scriptaculous libraries for Rails, since they are built-in along with a set of available helpers.
If you didn’t know, Rails was split in plugins from its version 2.0 on, the growing core functionalities made the whole thing too bulky to drive, so they wittingly decided to cut it back. In_place_editing is one of the plugins that separated from the core in the version 2.0. Now it can be found on github (here). Some vulnerabilities where discovered afterwards, but were fixed later on. Now I think it’s a nice piece of coding. Unfortunately, the README file feels a bit short to me.
First thing to do is to think what fields are going to be inline editable. I recommend all short descriptions and headers to be easily changeable by one click. Thus, usually in the Show views or sometimes also in Index views (for example in a task list) we’ll add this extra functionality. In most cases it will completely replace the Edit view, in some others, for instance those you want to use markup or wysiwyg (i.e. a mailer form) it won’t be advisable.
To install the plugin it must be downloaded or cloned from github and copied to the right location: /vendor/plugins/in_place_editing/
Then, next thing to do is to load the default javacript files (that includes Prototype and Scriptaculous) in the header of your layout:
<%= javascript_include_tag :defaults %>
Then, since you already know what fields of your model are going to be inline-editable, you have to mark them in the controller as so. This is as simple as doing this:
class PostsController < ApplicationController
in_place_edit_for :post, :info
where info is the field of Post that is going to be editable. At this point, only the views remain to be shaken:
It is important to note that we are using the Scriptaculous Ajax.InPlaceEditor (read docs here). Rows is the height of the text-area, if it’s 1 or not specified it will be an input. The external control, if specified, is a something in the page that will trigger the editing, this sometimes makes a better visual metaphor. For example, a small pencil or an edit label beside the text will do the trick. It must go before the in place editor field, or else won’t work. The text automatically highlights when the mouse passes over it. As you will see in the Ajax.InPlaceEditor wiki you can change the color of highlighting and everything else. Another important thing to notice is that it requires an initial value or otherwise it won’t be shown. I recommend leaving a “click to edit” default text.
Remember to read the additional options of the plugin:
:rows:: Number of rows (more than 1 will use a TEXTAREA)
:cols:: Number of characters the text input should span (works for both INPUT and TEXTAREA)
:size:: Synonym for :cols when using a single line text input.
:cancel_text:: The text on the cancel link. (default: "cancel")
:save_text:: The text on the save link. (default: "ok")
:loading_text:: The text to display while the data is being loaded from the server (default: "Loading...")
:saving_text:: The text to display when submitting to the server (default: "Saving...")
:external_control:: The id of an external control used to enter edit mode.
:load_text_url:: URL where initial value of editor (content) is retrieved.
: options:: Pass through options to the AJAX call (see prototype's Ajax.Updater)
:with:: JavaScript snippet that should return what is to be sent
in the AJAX call, +form+ is an implicit parameter
:script:: Instructs the in-place editor to evaluate the remote JavaScript response (default: false)
:click_to_edit_text::The text shown during mouseover the editable text (default: "Click to edit")
And this is all really necessary to know about the helper. You can also skip the helper and create the InPlaceEditor straight away:
<p id="activator">activate</p>
<span id="post_info_1_in_place_editor"><p>click to edit</p></span><script type="text/javascript">
//<![CDATA[
new Ajax.InPlaceEditor('post_info_1_in_place_editor', '/posts/set_post_info/1', {callback:function(form)