I originally saw a version of this concept on Quirksmode and then a more Web 2.0-ish version on the 24 Ways site.

I’m going to show you two ways that you could use jQuery to accomplish the same effect, or better.

The Goal

An AJAX (or AHAH) proof-of-concept page that allows the visitor to edit the very (x)HTML page they are viewing, without leaving the page.

The Concept

Click the text to be edited and magically a textarea appears with buttons beneath to save or cancel the changes. Changes are sent via AHAH to a PHP script which normally would be used to update a database (MYSQL or flatfile).

The Demonstration

Edit In Place Using Ajax 1

In this first demonstration, I’m using a div with an id of editInPlace. When you roll your cursor over the div, the background changes to a pale yellow. Clicking the text will start some DOM (Document Object Model) magic resulting in the div being replaced by a textarea input — with the text to be edited inside.

Clicking the save button will send the new HTML over to a simple PHP script that does nothing more than print out the data it receives (via $_POST).

In a real world application you would add in some additional safety checks, and then update your database with the new information and send back information that tells jQuery if the changes were successful.

But in this example, all changes are successful, the same information sent to the PHP script comes back to the jQuery code and is show in a simple window alert.

Explanation

The way I kick things off should be very familiar by now. Remember, if you don’t want to use the jQuery document.ready function then feel free to throw in your own init() function.

$(document).ready(function(){
setClickable();
});

So the first thing that happens is that the setClickable() function is fired. This function does the following:

Looks for the div with id=”editInPlace” and tells jQuery to do something when the div is clicked.

function setClickable() {
$('#editInPlace').click(function() {

Grabs the html inside the div using jQuery’s html() function. This html is wrapped inside of some more html that will make up the textarea and buttons for save and cancel.

var textarea = '<div><textarea rows="10" cols="60">'+$(this).html()+'</textarea>';
var button = '<div><input type="button" value="SAVE"
class="saveButton" /> OR <input type="button" value="CANCEL"
class="cancelButton" /></div></div>';
var revert = $(this).html();

The same html found within the div with id=”editInPlace” is assigned to a variable called “revert”. This will be used in the event the cancel button is used.

var revert = $(this).html();

jQuery’s DOM function “after” is used to place this new textarea html after the div we’ve targeted. I immediately chain another method to this (to save space) and tell jQuery to remove the div.

$(this).after(textarea+button).remove();

Using jQuery, I target the save and cancel button by using their class names. I instruct jQuery to trigger my final function “saveChanges” when either button is clicked. I close out the function that tells jQuery what to do when the div is clicked, but I do not put an apostrophe at the end because I want to chain more methods onto this div.

$('.saveButton').click(function(){saveChanges(this, false);});
$('.cancelButton').click(function(){saveChanges(this, revert);});
})

I chain a simple mouseover and mouseout to my code which tells jQuery to add and remove a class when a cursor rolls over the div we’ve targeted (id=”editInPlace”).

.mouseover(function() {
$(this).addClass("editable");
})
.mouseout(function() {
$(this).removeClass("editable");
});
};//end of function setClickable

Function “saveChanges” will take the button object for the first variable and the cancel variable should either be false or contain the html I stored in the “revert” variable.

function saveChanges(obj, cancel) {

If “cancel” is false then I’m telling this function to save the changes by sending the html over to the php script. I grab the html within the textarea by using some of the DOM functions available through jQuery: parent() and siblings().

if(!cancel) {
var t = $(obj).parent().siblings(0).val();

DOM basics are beyond the scope of this tutorial, but I’m basically telling jQuery “The obj (save button) has a parent (a div)… go find it. This object has one or more objects on the same level of the DOM tree… I want the first one. And grab the value of that object.”

(On second thought… if you aren’t familiar with DOM style of coding, then my explanation probably didn’t make much sense to you. I suggest Googling “DOM javascript” or something similar.”)

This html is assigned to the “t” variable and now it’s time to send it via POST over to test2.php.

$.post("test2.php",{
  content: t
},function(txt){
alert( txt);
});
}

If cancel has a value, then it should be html stored originally in the “revert” variable. So, at this point, I want the “t” variable to be set to the original html.

else {
var t = cancel;
}

The next step is to use the DOM functions within the jQuery javascript library to place a new div, with the “editInPlace” id, after the div containing the textarea… and then remove the div containing the textarea.

$(obj).parent().parent().after('<div id="editInPlace">'+t+'</div>').remove() ;

In a nutshell, this tells jQuery “Go backwards on the DOM branches two moves. Place this HTML after the object found at that location, and then remove the object.”

Finally, we call the setClickable function again and close out the saveChanges() function. The purpose of recalling the setClickable() function is to reset the onMouseover, onMouseout, and onClick events.

setClickable();
}

Second Example

The second one is very similar but a little more complex.

Edit In Place With Ajax 2

Instead of one large div, this example turns every P tag into its own editable region.

The difficulty comes when you want to send the data to a server side script and target the correct P tag for updating in the database.

The solution I came up with is to number each P tag and send this information over to the PHP code. What you see in the alert box is that the PHP code “knows” which P tag is to be changed.

Known Issues

If you used something similar in a real application then you’d want to verify that the changes were made before telling jQuery to update the DOM with the new html.

For this demonstration there is no interaction with a database and so I skipped this step.

[tags]javascript, AJAX, AHAH, jQuery, DOM, scripting[/tags]