Inline Editing Using Ajax

  • google plus

In Brief...

Sometimes it is nice to be able to edit a page without displaying form elements by default. For example, if you want to allow people who are logged in as administrators to edit sections of a page, you could make it so that the administrator could click on those sections to turn them into form elements and perform inline editing using Ajax.

Take our Ajax Training course for free.

See the Course Outline and Register

Instructions

First, let's look at a simple table that shows the presidents' first and last names:

Presidents Table

The neat thing about this table is that the names become editable when double clicked:

All the user has to do is type a new value and tab out or click anywhere else in the document to change the value in the table. An XMLHttpRequest is used to change the record in the database.

Presidents Table

This page is generated by the Node.js response route /Presidents in MoreAjaxApps/Demos/server.js and rendered by the MoreAjaxApps/Demos/Presidents.jade template. The server-side code queries the "Presidents" database to retrieve a list of all presidents' IDs, first and last names, and bios, and returns those data as an HTML table.

For these examples to work, more files are required than are available in this how to. To see these examples in action, take the Ajax training course.

  1. The following code queries the database for the presidents' first and last names and biographies (taken from the Whitehouse website9) and then iterates through the result set creating a table row for each president. Each td element has the editable class. The Jade template includes a call to MoreAjaxApps/Demos/inline-editing.js, which does the real work:
    function enableEditing() {
    	var editableElems = getElementsByClassName(document, "editable");
    	var numElems = editableElems.length;
    	for (var i = 0; i < numElems; i++) {
    		observeEvent(editableElems[i], "dblclick", editElem);
    	}
    }
    
    function editElem(e) {
    	var target = getTarget(e);
    	var input;
    	var textLen = target.innerHTML.length;
    	if (textLen > 30) {
    		target.innerHTML = "<textarea cols='120' rows='6'>" + target.innerHTML + "</textarea>";
    	} else {
    		target.innerHTML = "<input value='" + target.innerHTML + "'>";
    	}
    	var input = target.firstChild;
    	input.select();
    	observeEvent(input, "blur", saveCell);
    }
    
    function saveCell(e) {
    	var target = getTarget(e);
    	var td = target.parentNode;
    	var tr = td.parentNode;
    	var field = td.title;
    	var value = target.value;
    	var pid = tr.id;
    
    	var xmlhttp = new XMLHttpRequest();
    	xmlhttp.open("POST", "SaveCell", true);
    	xmlhttp.onreadystatechange = function() {
    		if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    			td.innerHTML = target.value;
    			blinkText(td, 1000, "Saved", "Normal");
    		}
    	}
    	xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
    	xmlhttp.send("field=" + field + "&value=" + value + "&pid=" + pid);
    }
    
    function blinkText(elem, time, on, off, timePast) {
    	var timePast = timePast + 100 || 0;
    	if (hasClassName(elem, on)) {
    		removeClass(elem, on);
    	} else {
    		addClass(elem, on);
    	}
    
    	if (timePast < time) {
    		setTimeout(function() {
    			blinkText(elem, time, on, off, timePast)
    		}, 100);
    	} else {
    		removeClass(elem, on);
    		removeClass(elem, off);
    	}
    }
  2. Now let's review this JavaScript library functions so you can understand the code:
    • enableEditing() Gets all the elements with the "editable" class using the getElementsByClassName() function from lib.js and attaches the editElem() function to their double-click events.
    • editElem() Changes the innerHTML of the double-clicked td to an input or textarea tag (depending on the length of the innerHTML) and attaches the saveCell() function to its change event.
    • saveCell() Uses Ajax to send the field, value and president id to SaveCell.jsp, which updates the record. The inline callback function changes the innerHTML of the td to the new value and calls blinkText().
    • blinkText() Toggles the class name of the passed in element (elem) between the passed-in on and off values for timePast milliseconds. This creates a blinking effect.
  3. In addition, HTML 5 includes a contenteditable attribute that can be applied to almost any element, though Internet Explorer does not allow it on elements that make up tables (e.g, table, tr, td, etc.). All you have to do to make an element editable is add contenteditable="true" to the tag.
    <!DOCTYPE HTML>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Content Editable</title>
    </head>
    <body>
    <p contenteditable="true" style="font-size:xx-large">I am editable.</p>
    </body>
    </html>
    Of course, when the user changes content on the page that doesn't have any permanent effect. You, as the developer, have to catch that change and do something about it. When an editable element loses focus, a blur event is triggered (there is no change event). You can use the blur event to trigger Ajax code that saves any changes the user made.

Author: Chris Minnick

Chris is a prolific author and trainer, and the CEO of WatzThis?. His published books include Writing Computer Code, JavaScript for Kids, Coding with JavaScript For Dummies, Beginning HTML5 and CSS3 For Dummies, Webkit For Dummies, CIW eCommerce Certification Bible, and New Riders' XHTML.

Discuss