Using contenteditable for Inline Editing - Exercise

Contact Us or call 1-877-932-8228
Using contenteditable for Inline Editing - Exercise

Using contenteditable for Inline Editing

Duration: 20 to 30 minutes.

In this exercise, you will improve the inline editing page to make use of the contenteditable attribute instead of form elements.

  1. Navigate to the directory MoreAjaxApps/Exercises/ from the command line. Type npm install to install the needed Node.js modules.
  2. Type npm start from the command line to start the Node.js server.
  3. Open MoreAjaxApps/Exercises/inline-editing.js for editing. This file currently contains the same code we saw in the demo earlier.
  4. Delete the editElem() function. You won't need it.
  5. Modify the enableEditing() function so that the text of the editable elements gets surrounded with a span tag that has the contenteditable attribute set to "true." Attach the saveCell() function to blur events on the new span tag. We no longer need to observe double clicks.
  6. Modify the saveCell() function so that it gets the correct value. Remember, we are now using a span rather than a form element. Also, in the callback function, we no longer need to change the form field back to text.
  7. Test your solution by opening http://localhost:8080/Presidents in your browser and modifying a field. The text should blink. Refresh the page to see if your change stuck.

Solution:

MoreAjaxApps/Solutions/inline-editing.js
function enableEditing() {
	var editableElems = getElementsByClassName(document, "editable");
	var numElems = editableElems.length;
	var elem;
	for (var i = 0; i < numElems; i++) {
		elem = editableElems[i];
		elem.innerHTML = "<span contenteditable='true'>" + elem.innerHTML + "</span>";
		observeEvent(elem.firstChild, "blur", saveCell);
	}
}

function saveCell(e) {
	var target = getTarget(e);
	var td = target.parentNode;
	var tr = td.parentNode;
	var field = td.title;
	var value = target.innerHTML;
	var pid = tr.id;

	var xmlhttp = new XMLHttpRequest();
	xmlhttp.open("POST", "SaveCell", true);
	xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
			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;
	elem.className = (elem.className == on) ? off : on;

	if (timePast < time) {
		setTimeout(function() {
			blinkText(elem, time, on, off, timePast)
		}, 100);
	} else {
		elem.className = "editable";
	}
}

observeEvent(window, "load", enableEditing);

The for loop in function enableEditing wraps the inner HTML contents of each element with class editable with a span tag with the attribute contenteditable='true'. The listener observeEvent is attached to each span, fired on the blur event.

The blur event - that is, when the field loses focus - invokes the saveCell function, which sends (via Ajax) the name and value of the changed field to the Node.js SaveCell response route in MoreAjaxApps/Solutions/server.js. The response route, in turn, updates the database.

Next