Editing Text On Click With JavaScript / DOM

Recently asked in Yahoo! Answers:

Clickable text to edit? Javascript?
So I saw somewhere on this website that they had rows of DYNAMIC data that when you clicked on the actual text (onfocus), the text would turn into a editable text field containing the text, and then when you clicked off of it (onblur?), AJAX was used to update the database that the data came from with that new changed value. I believe it was used to edit categories on the fly.

How do I do this? I can figure out the AJAX/PHP/Mysql part, but I really suck at javascript. I just need to be able to have some text turn into a text field when clicked that contains that text for editing. I’m sure you understand.

Thanks so much.

This is actually pretty straightforward. Basically, you do it with two DIVs: one contains the text you want to make editable, the other contains a textarea that will edit the text. Clicking on the text DIV makes the edit DIV visible; submitting the edits changes the text and hides the edit form.

But, like all things that seem simple, there are a couple of small adjustments we need to make to ensure our solution both works as intended and is safe from HTML injection.

Let’s get to it. As always, a working demo / code you can download appears at the end of this entry.

Step 1: Create The Basic HTML

Again, we need two DIVs for this solution: One to hold the text, the other to hold the editor, each uniquely identified in some way.

<div id="thetext" onclick="toggleEditor()">
    This is the text that will be edited.<br />
    Just click on it.
<div id="editor">
    <textarea id="ta1" name="ta1" rows="10" cols="50"></textarea><br />
    <input name="submit" id="submit" type="button" value="Edit Text" onclick="doEdit()" />

Note that onclick event handlers have been assigned to both the text DIV and a button in the editor DIV. More on those shortly.

Next, we create the beginning styles for the editor DIV; basically, we set it to display: none; so that it is not visible at first.

div#editor {
	display: none;

Step 2: The toggleEditor() Function

The onclick event handler for the text DIV is named toggleEditor, and its tasks are:

  1. Get the text from the text DIV.
  2. Convert the line breaks into newlines.
  3. Convert the entities for HTML opening and closing brackets back into literal characters.
  4. Put the text into the editor’s textarea field.
  5. Hide the text DIV and show the text editor DIV.
function toggleEditor() {
	var theText = document.getElementById('thetext');
	var theEditor = document.getElementById('ta1');
	var editorArea = document.getElementById('editor');

	//set text in text div to textarea
	//correct line breaks, prevent HTML injection
	var subject = theText.innerHTML;
	subject = subject.replace(new RegExp("<br />", "gi"), 'n');
	subject = subject.replace(new RegExp("<br />", "gi"), 'n');
	subject = subject.replace(new RegExp("<", "gi"), '<');
	subject = subject.replace(new RegExp(">", "gi"), '>');
	theEditor.value = subject;

	//hide text, show editor
	theText.style.display = 'none';
	editorArea.style.display = 'inline';

The reason for converting line breaks is obvious: Unless you do so, the line breaks you make in the textarea won’t show up in HTML, and vice-versa. Because both Firefox and Internet Explorer may also convert XHTML-style line breaks (<br />) into HTML-style line breaks (<BR>), we also need to replace both kinds of break.

Finally, we need to harden this application against HTML injection / cross-site scripting (XSS). The simplest way to do that is to escape all HTML opening (<) and closing (>) brackets, replacing them with their HTML entity equivalents (&lt; and &gt;, respectively).

If I was being very thorough, I would replace all characters with their HTML equivalents; for example, all ampersands, single-quotes, etc. I’ll leave that to others, however, as my basic goal is simply to stop XSS attacks.

Which also provides me an opportunity to discuss SQL injection. This script is not armored against SQL injection attempts. And you should never, ever rely on JavaScript alone to prevent SQL injection attacks. Always use your server-side language to protect your SQL statements before they are executed.

Step 3: The doEdit() Function

When the user edits the text, we want to show the edited text to him. We do that with a function named doEdit, assigned as the onclick event handler for a button:

  1. If we are going to hand this content off to an AJAX request, as the questioner states, we probably do that first. Again, don’t rely on JavaScript to fix things before working with them on the server; use your server-side program to ensure you input good data on the server.
  2. We take the text in the textarea and replace all opening and closing HTML brackets with their entities.
  3. We replace all newlines with HTML line breaks.
  4. We assign the textarea’s value to the inner HTML of the text block.
  5. We hide the editor DIV and show the text DIV.
function doEdit() {
	var theText = document.getElementById('thetext');
	var theEditor = document.getElementById('ta1');
	var editorArea = document.getElementById('editor');

	//this is where you would call your AJAX update script
	//e.g., doXMLRequest(data);
	//you probably want to make your DB update BEFORE converting for display

	//set text to be value in editor
	//correct line breaks, prevent HTML injection
	var subject = theEditor.value;
	subject = subject.replace(new RegExp("<", "g"), '<');
	subject = subject.replace(new RegExp(">", "g"), '>');
	subject = subject.replace(new RegExp("n", "g"), '<br />');
	theText.innerHTML = subject;

	//hide editor, show text
	theText.style.display = 'inline';
	editorArea.style.display = 'none';

And that’s all there is to it. You can see a working demo here: http://demo.dougv.com/ajax_edit_text/

1 Comment

  1. As the asker of this question, I would like to thank you immensely for writing this tutorial! I’ve been browsing your site, and have found a lot of useful techniques.

    Great work!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!