On Blur Save with JRails In Place Editing

Jan 16, 2010

Code

0 Comments

I’ve been working on a Rails app recently where I used the excellent jrails_in_place_editing plugin to create a large number of in-place editing textfields. I used this in lieu of the Rails plugin because I removed Prototype completely from my app. I’m prone to do this because jQuery is so clearly better than Prototype. Please, Rails Core, replace this? I usually do this using the JRails plugin because it has all the built-in helpers written for jQuery — beautiful!

In any case, the jrails_in_place_editing plugin is quite wonderful, but limited in terms of the number of features it actually implements. The jQuery plugin it is based on has a load of more configurable features. I added in a few back for my needs, but there’s one basic functionality I was surprised to find missing: on-blur saving. Brandy suggested I needed this in my project, and I have to say she was very right — it makes editing a lot of fields so much easier for power users.

Doing this is very simple. All you need to do is add the following to /public/javascripts/jquery.inplace.js:

//ON BLUR SAVE functionality
original_element.children("form").children(".inplace_field").blur(function(){
	//put the original background color in
	original_element.css("background", settings.bg_out);

	var new_html = jQuery(this).parent().children(0).val();

	//set saving message
	if(settings.saving_image != ""){
		var saving_message = '<img src="' + settings.saving_image + '" alt="Saving..." />';
	} else {
		var saving_message = settings.saving_text;
	}

	//place the saving text/image in the original element
	original_element.html(saving_message);

	if(settings.params != ""){
		settings.params = "&" + settings.params;
	}

	if(settings.callback) {
		html = settings.callback(original_element.attr("id"), new_html, original_html, settings.params);
		editing = false;
		click_count = 0;
		if (html) {
			// put the newly updated info into the original element
			original_element.html(html || new_html);
		} else {
			// failure; put original back
			alert("Failed to save value: " + new_html);
			original_element.html(original_html);
		}
	} else if (settings.value_required && new_html == "") {
		editing = false;
		click_count = 0;
		original_element.html(original_html);
		alert("Error: You must enter a value to save this field");
	} else {
		jQuery.ajax({
			url: settings.url,
			type: "POST",
			data: settings.update_value + '=' + new_html + '&' + settings.element_id + '=' +
					original_element.attr("id") + settings.params +
					'&' + settings.original_html + '=' + original_html,
			dataType: "html",
			complete: function(request){
				editing = false;
				click_count = 0;
			},
			success: function(html){
				// if the text returned by the server is empty,
			// put a marker as text in the original element
				var new_text = html || settings.default_text;

				// put the newly updated info into the original element
				original_element.html(new_text);
				if (settings.success) settings.success(html, original_element);
			},
			error: function(request) {
				original_element.html(original_html);
				if (settings.error) settings.error(request, original_element);
			}
		});
	}

	return false;
});

Of course, if you use cacheing you’ll want to delete all.js and let Rails re-cache with the reflected changes. This code worked like a dream for me — hope it helps you too!

Leave a Comment

Fill out the form to leave a comment; name and e-mail are required. I don't edit comments for content, but please add to the discussion, don't detract from it. Please review your comment for spelling and grammar. If you're posting code, run it through Postable first to ensure proper display. Since I'm a nice guy, you can use the cool WYSIWYG editor to make your comment look fancy.

Live Comment Preview