Elliott C. Back: Internet & Technology

Ajax Edit In Place with Yahoo UI API

Posted in AJAX,Code,Computers & Technology,Interface,Web 2.0,Yahoo by Elliott Back on February 9th, 2007.

You’ve probably seen the article at at 24 ways about Ajax in-place editing, but honestly the javascript they code up there seems quite hacky and un-standards-compliant. Instead, we’re going to use the Yahoo UI Library (YUI, YUI-EXT), a modern cross-browser javascript toolkit, to accomplish the same results with less hassle, and more power.

The effect we want is like Flickr’s edit in place descriptions:

edit-in-place.jpg

Part 1: The YUI javascript example:

In javascript, here’s the code. First you need some includes:

<script type="text/javascript" src=js/yahoo.js"></script>
<script type="text/javascript" src=js/connection.js"></script>
<script type="text/javascript" src=js/event.js"></script>
<script type="text/javascript" src=js/utilities.js"></script>
<script type="text/javascript" src=js/dom.js"></script>
<script type="text/javascript" src=js/yui-ext.js"></script>

Don’t forget to add this handy shortcut–we’ll use it later:

<script type="text/javascript">
var $ = YAHOO.util.Dom.get
</script>

Then we need a function to show something as editable:

function showAsEditable(e){
	YAHOO.util.Event.preventDefault(e);
	YAHOO.util.Event.stopPropagation(e);
		
	if(this.oldBG == undefined) {
		var pos = this;
			
		while(pos && pos.style.backgroundColor == '') {
			pos = pos.parentNode;
		}
				
		this.oldBG = pos.style.backgroundColor;
	}
		
	var anim = new YAHOO.util.ColorAnim (
		this,
        	{backgroundColor:{to:'#ffffd3'}},
		.5,
		YAHOO.util.Easing.easeOut
	);
        
	anim.animate();
}

This function finds the closest defined background color, if not already defined, and saves it. Then it animates to a nice yellow overlay color. Now we need its reverse:

function showAsNotEditable(e){
	YAHOO.util.Event.preventDefault(e);
	YAHOO.util.Event.stopPropagation(e);
		
	var anim = new YAHOO.util.ColorAnim (
		this,
		{backgroundColor:{to:this.oldBG}},
		.5,
		YAHOO.util.Easing.easeOut
	);
        
        anim.animate();
}

This function is even simpler–it just restores the saved background color. Now that we can turn their “editable effect” on and off, we need something to actually do the work:

function editHandler(e){
	YAHOO.util.Event.preventDefault(e);
	YAHOO.util.Event.stopPropagation(e);
	var target = (e.srcElement) ? e.srcElement : e.target;
		
	var form = '<div id="' + target.id + '_editor">';
	form = form + '<textarea id="' + target.id + 
		'_edit" name="' + target.id + 
		'" rows="4" cols="60">' + 
		target.innerHTML + '</textarea>';
	form = form + '<br/><input id="' + target.id + 
		'_save" type="button" ' + 
		'value="SAVE" /> OR <input id="' + 
		target.id + '_cancel" type="button" ' + 
		value="CANCEL" /></div>';
	form = form + '</div>';
								
	YAHOO.ext.DomHelper.insertHtml('afterEnd', target, form);
	
	YAHOO.util.Event.addListener(target.id + '_save', 'click', function(){
		YAHOO.util.Connect.asyncRequest('POST', 'ajax.php',
		{
			success: function(o){
	                	target.innerHTML = $(target.id + '_edit').value;
	                  	$(target.id + '_editor').parentNode.
					removeChild($(target.id + '_editor'));
				target.style.display = 'block';
			},
			failure: function(o){
				$(target.id + '_editor').value = 
				'Sorry, the update failed...';
			},
			scope: this
		},
		'action=updatepost&target=' + target.id + '&value=' 
			+ escape($(target.id + '_edit').value)
		);
	});
		
	YAHOO.util.Event.addListener(target.id + '_cancel', 'click', function()
	{
		$(target.id + '_editor').parentNode.
			removeChild($(target.id + '_editor'));
		target.style.display = 'block';
	});
		
	target.style.display = 'none';
}

Now that that’s out of the way, you just need to add these handlers to mouseover, mouseout, and click events of “editable” items:

var elements = YAHOO.util.Dom.getElementsByClassName('editable');
YAHOO.util.Event.addListener(elements, 'click', editHandler);
YAHOO.util.Event.addListener(elements, 'mouseover', showAsEditable);
YAHOO.util.Event.addListener(elements, 'mouseout', showAsNotEditable);
YAHOO.ext.EventManager.onDocumentReady(Init.init, Init, true);

Part 2: the HTML code

Here’s an example of some html code that automatically makes itself editable:

<div class="itemcontent">
	<p id="description-' . $row['id'] . 
		'" class="editable">' . 
			htmlentities($row['description']) .
		'</p>
</div>

Part 3: the AJAX

Since we encode the field name and identifier in the id attribute of the editable element, processing the ajax request is easy:

$value = urldecode($_POST['value']);
$bits = preg_split('[-]', $_POST['target'], -1);
$field = $bits[0];
$id = $bits[1];
			
switch($field) {
	case 'title':
		$object->UpdatePostTitle($id, $value);
		break;
	case 'description':
		$object->UpdatePostDescription($id, $value);
		break;
}

Conclusion

Using YUI you can add a robust, cross-platform edit-in-place solution that’s as easy as giving your html elements id attributes in the form “$field-$id” and the classname “editable.” The rest is magic. For a live demo, see my edit in place demo.

This entry was posted on Friday, February 9th, 2007 at 12:31 am and is tagged with . You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback.

22 Responses to “Ajax Edit In Place with Yahoo UI API”

  1. George says:

    Hello! I have followed all the instructions here, but I don’t get to work the SQL UPDATE, I would appreciate if anybody can give me some help:

    $value = urldecode($_POST[‘value’]);
    $bits = preg_split(‘[-]’, $_POST[‘target’], -1);
    $field = $bits[0];
    $id = $bits[1];

    switch($field) {
    case ‘title':
    $object->UpdatePostTitle($id, $value);
    break;
    case ‘description':
    $object->UpdatePostDescription($id, $value);
    break;
    }

    $updateData= “UPDATE table SET table_field='”.$value.”‘ WHERE id='”.$id.”‘”;
    mysql_query($updateData);

  2. francisco says:

    esto no funciona en IE
    l

  3. Brenton says:

    Sorry for the multiple comments. I was having issues with your server. You can delete the other messages.

    I rolled my own based on your code to make it deployable on Facebook. It seems to work better if I convert \n to \\n for the upload field, and then back to \n for the text area. Otherwise, the text area doesn’t seem to receive any text after a newline character. Also, adding a tag to your preview would make the newlines display properly in-browser.

  4. Brenton says:

    I’m working on a similar edit-in-place for Facebook apps. I’m trying to figure out how to handle new-lines properly.

    For the display, you need to either replace them with s or wrap them in a . As far as adding them to a form value, I’m bug-squashing.

  5. […] Yahoo UI  Edit in Place – This edit in place uses the Yahoo UI Library.   The effect is very similar to Flicker.  But also allows you to edit lists. […]

  6. thanks for the GREAT post! Very useful…

  7. Ed Martinez says:

    errata…

    When I typed PARAGRAPH HTML tags in the inline editor started working buggy.

    Such bug happens also in the line items.

  8. Ed Martinez says:

    When I typed tags in the inline editor started working buggy.

    Check it out!

    Such bug happens also in the line items.

  9. dja says:

    I’m also falling between the abstraction cracks in the latest code. A version with minimal moving parts would be helpful.

  10. Elliott Back says:

    Psh, my demo works, port it yourself. It’s trivial!

  11. anthony p. says:

    I am unable to get this working using the lastest libraries of yahoo ui and ext. Could you update the example?

    thx :)

  12. John Jack says:

    Ok, nevermind. I had ActiveX disabled in the browser.

  13. John Jack says:

    This works flawlessly in FF2.0 but I can not get it to work in IE 6. Does it work in IE 6 or should I keep looking for whatever I’m doing wrong?

  14. Leite says:

    Hi Elliot,
    How about YUI-only approach!?!
    There is 2 lines with Slocum’s EXT.
    I figured out you can drop one doing this:

    a)
    Replace:
    var Init = {
    init : function(){
    ….. code ….
    } // ends init
    }; // ends Init
    YAHOO.ext.EventManager.onDocumentReady(Init.init, Init, true);

    [[[You don’t need Init and init! AND YUI Event takes care of it ;) ]]]

    By:
    function init() {
    ….. code ….
    };
    YAHOO.util.Event.addListener(window, “load”, init);

    ————————-
    b)
    YUI utilities.js contains yahoo, event, dom, connection, animation AND dragdrop Minified – one and only one – script file!

    ————————–
    c)
    How about get rid off
    YAHOO.ext.DomHelper.insertHtml(‘afterEnd’, target, form);
    ???

    Drop me a line!

    Leite

  15. Jonas says:

    Hi, thanks a lot! Well written and just what I was looking for…

    I’m only having some trouble on Firefox 2.0.0.2 on Edgy with it not being very responsive and sometimes opening two edit windows below each other. I’ll hack around with it some and see where it takes me.

    Cheers,
    Jonas

  16. Elliott Back says:

    Oh wow, you’re right. Uh let me remove that ….

  17. Dragan says:

    Your demo page is password-protected. Why?

  18. Tom says:

    This is great! …but can it be done with just YUI alone? Yahoo’s version? I see YUI-EXT is now just EXT…. from trying to read about it (and it looks cool, all the examples on that site) it seems to be just a fork of YUI with a mix of jquery and other libraries…. So if this edit in place is done with EXT and not YUI …. then I don’t know if I like that so much (I mean I love different libraries, but have to use YUI for one of my needs here). Your blog post title is confusing if this is the case — but thanks for sharing a real nice edit in place solution.

  19. Thanks for the writeup! This will come in handy for me.

Leave a Reply