Halhelms
SIGN UP FOR MY NEWSLETTER
 
 
Halhelms

Shameless Money

Recent Entries

RSS

Subscribe

Learning jQuery, Day 12: Inline Editing

We're all familiar with the process of showing content to a user and letting them edit it by means of perhaps an "Edit" button that takes them to a form. Today, let's look at a different way: allowing users to do inline edits in an unobtrusive manner.

To see this working, head over to http://dev.citymind.com:8500/test/blog_jquery/day12/index.cfm.

You'll see a list of composers, each of which can be clicked on for more information. This is a standard drilldown pattern. One of them, Herr Beethoven, is colored in green. This indicates that there is, in fact, more information available about him.

If you click on Beethoven, you'll be taken to a new page that has some information about him from Wikipedia. Let's say that you have some information you'd like to add -- or perhaps you need to correct part of the entry. If you click on either of the two paragraphs of content, you'll see a border around the paragraph, indicating that you're in edit mode.

You can now change the content of either of the paragraphs. When the DIV of the text you're changing loses the focus, any changes are saved to the database and, if you refresh the page, you'll see your changes are reflected.

Now, let's look at how I did that and, in fact, you'll see I did very little. The magic lies in a jQuery plugin available at http://valums.com/edit-in-place/. But I'm getting slightly ahead of myself. Let's first look at the code for index.cfm -- the page that displays the composers:

<html>
   <head>
      <style type="text/css">
         .more{color: green;}
      </style>
      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
      <script type="text/javascript">
         $(document).ready(function(){
            $('.composer').click(function(){
               location.href='composer.cfm?composerId=' + $(this).attr('title');
            });
         });
      </script>
      
   </head>
   <cfquery datasource="learnjquery" name="composers">
      SELECT
         composerId,
         firstName,
         lastName,
         overview
      FROM composers
      ORDER BY lastName
   </cfquery>
   <body>
      <h2>Popular Composers</h2>
      <ul>
      <cfoutput query="composers">
         <cfset class="">
         <cfif Len(overview)>
            <cfset class=" more">
         </cfif>
         <li class="composer#class#" title="#composerId#"><strong>#lastName#</strong>, #firstName#</li>
      </cfoutput>
      </ul>
   </body>
</html>

Let's start by looking at the CFQUERY -- a very simple one that all ColdFusion developers will understand. After retrieving the information about all the composers in the database, I display the results of the query. The only thing even mildly interesting is that I gave all the LIs a class of "composer" and a possible class of "more" (depending on whether there was any information in the "overview" field).

To do the drilldown, I used this JavaScript:

<script type="text/javascript">
   $(document).ready(function(){
            $('.composer').click(function(){
               location.href='composer.cfm?composerId=' + $(this).attr('title');
   });
});
</script>

This tells jQuery that, once the document is ready for JavaScript processing, it should use as an event handler for the CLICK event, a simple function that relocates the visitor to a drilldown page, carrying with it a url variable with the "composerId" value. (I could have accomplished the same thing without jQuery, of course.)

Off the user goes to "composer.cfm", whose code looks like this:

<cfsetting showdebugoutput="false">
<html>
   <head>
      <style type="text/css">
         .editing{color: red};
      </style>
      <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
      <script type="text/javascript" src="jquery.editable.js"></script>
      <script type="text/javascript">
         $(document).ready(function(){
            $('.editable').editable(function(element){
               $.ajax(
                  {
                     type: "POST",
                     url: "update.cfm",
                     data: "newfieldvalue=" + $(element).html() + "&composerId=" + $('#composer').attr('title') + "§ionId=" + element.id,
                     success: function(msg){
                        alert('Your edits have been saved');
                     }
                  }
               );
            });
      });      
      </script>
   </head>
   <cfquery datasource="learnjquery" name="composer">
      SELECT
         firstName,
         lastName,
         yearBorn,
         yearDied,
         overview,
         beliefs
      FROM
         composers
      WHERE
         composerID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#url.composerId#">
   </cfquery>
   <body>
<cfoutput>
   <h2 id="composer" title="#url.composerId#">#composer.firstName# #composer.lastName#</h2>
   <h4>#composer.yearBorn# -- #composer.yearDied#</h4>
   
   <div class="editable" id="overview">#composer.overview#</div>
   
   <div class="editable" id="beliefs">#composer.beliefs#</div>
</cfoutput>      
</body>
</html>

Again, let's start with the CFQUERY whose behavior will be obvious to all CFers. I then output the content fetched from the database.

To set up the two DIVs for editing, I simply add the class "editable" to the DIV. To make it do something, I've first included the jQuery library from Google. I then include the "jquery.editable.js" file that Andrew Valums kindly wrote (available at http://valums.com/edit-in-place/.

Now, to invoke the inline editing capabilites: I begin with the ubiquitous "$(document).ready(function(){code here})" function that tells jQuery to run any code with the function. My actual code will replace the "code here" text. Let's look at it again:

$('.editable').editable(function(element){
   $.ajax(
      {
         type: "POST",
         url: "update.cfm",
         data: "newfieldvalue=" + $(element).html() + "&composerId=" + $('#composer').attr('title') + "§ionId=" + element.id,
         success: function(msg){
            alert('Your edits have been saved');
            }
      }
   );
});

This code does the following:

  1. makes any elements with a class of "editable" able to be edited
  2. posts any changes in the content to a ColdFusion page, "update.cfm"
  3. alerts the user that their changes have been saved.

The final piece of the puzzle is "update.cfm" -- standard ColdFusion code:

<cfparam name="form.composerId">

<cfquery datasource="learnjquery">
   UPDATE composers
   SET #form.sectionId# = <cfqueryparam cfsqltype="cf_sql_longvarchar" value="#form.newfieldvalue#">
   WHERE composerId = <cfqueryparam cfsqltype="cf_sql_varchar" value="#form.composerId#">
</cfquery>

With only a small bit of code, we've provided some very nice functionality to our users. jQuery rocks.

Zipped files

Comments
James Allen's Gravatar Excellent post Hal!

Nice and simple to implement and I can see this being a good way to implement a frontend admin system for the big site I'm working on. Be nice for an admin to simply enable edit mode and then click to edit various pieces of content on the page. I could link this into my localisation system so that the ini file is updated after each edit.

My only question is how is HTML handled - e.g strong tags and links etc? Does the inline edit panel change the content to HTML so you can edit it, or is not possible to edit or create these elements?

I'm definitely going to look at implementing this. Quick to build in and perfect as most of the content I want to edit on the site is plain..
# Posted By James Allen | 5/20/09 9:56 AM
Hal's Gravatar This plugin doesn't handle HTML, but there are others that do, James.
# Posted By Hal | 5/20/09 10:32 AM
James Allen's Gravatar Thanks Hal. I'll do a bit more research.

Appreciate you pointing this one out though. I think it will probably fit the bill nicely and is really easy to implement. It's the first time I've thought of building a completely front-end driven admin system so this will make life nice and easy.
# Posted By James Allen | 5/20/09 10:49 AM
 
   
Clicky Web Analytics