/*
 * Edit In Place
 * http://josephscott.org/code/js/eip/
 * Version 0.3.0
 * License http://josephscott.org/code/js/eip/license.txt
 
 * Modified by Nick Dunn to add Moo.fx transitions
 * http://www.nick-dunn.co.uk/blog/2006/08/animating-editinplacejs-with-moofx/
 */

// Fake a EditInPlace.* name space.
var EditInPlace = function() { };

// Default settings for editable ids.
EditInPlace.defaults = {
	// Default options that you can over write.
	id:						false,
	save_url:				false,
	type:					'text',
	select_text:			false,	// doesn't work in Safari
	size:					false,  // will be calculated at run time
	max_size:				100,
	rows:					false,  // will be calculated at run time
	cols:					50,
	options:				false,
	mouseover_class:		'eip_mouseover',
	editfield_class:		'eip_mouseover',
	savebutton_text:		'Save',
	savebutton_class:		'eip_savebutton',
	cancelbutton_text:		'Cancel',
	cancelbutton_class:		'eip_cancelbutton',
	saving_text:			'Saving',
	saving_class:			'eip_saving',
	empty_text:				'Click to edit',
	empty_class:			'eip_empty',
	click:					'click',  // or dblclick 
	savefailed_text:		'Failed to save changes.',

	// Private options that are managed for you.
	// PLEASE DO NOT TOUCH THESE.
	is_empty:				false,
	orig_text:				'',
	mouseover_observer:		false,
	mouseout_observer:		false,
	mouseclick_observer:	false
};

// Place to keep individual option sets.
EditInPlace.options = { };

// Make an id editable.
EditInPlace.makeEditable = function(args) {
	var id = args['id'];
	var id_opt = EditInPlace._getOptionsReference(id);

	// Start the option set with the defaults.
	for(var i in EditInPlace.defaults) {
		id_opt[i] = EditInPlace.defaults[i];
	}

	// Overwrite defaults with provided arguments.
	for(var i in args) {
		id_opt[i] = args[i];
	}

	// Store the current (original) value of the editable id.
	id_opt['orig_text'] = $(id).innerHTML;

	// Check for empty values.
	if($(id).innerHTML == '') {
		id_opt['is_empty'] = true;
		$(id).innerHTML = id_opt['empty_text'];
		Element.addClassName(id, id_opt['empty_class']);
	}

	// Build event observers.
	id_opt['mouseover_observer'] = EditInPlace._mouseOver.bindAsEventListener();
	id_opt['mouseout_observer'] = EditInPlace._mouseOut.bindAsEventListener();
	id_opt['mouseclick_observer'] = EditInPlace._mouseClick.bindAsEventListener();

	// Watch for events.
	Event.observe(id, 'mouseover', id_opt['mouseover_observer']);
	Event.observe(id, 'mouseout', id_opt['mouseout_observer']);
	Event.observe(id, id_opt['click'], id_opt['mouseclick_observer']);

	// Return a reference the option set
	// just in case someone is interested.
	return(id_opt);
};

// **************  Private Functions ***************** 

// Get a reference to the option set for a specific editable id.
EditInPlace._getOptionsReference = function(id) {
	// If an option set doesn't exist for the id
	// then create an empty one.
	if(!EditInPlace.options[id]) {
		EditInPlace.options[id] = { };
	}

	return(EditInPlace.options[id]);
};

// Process mouseover events.
EditInPlace._mouseOver = function(event) {
	var id = Event.element(event).id;
	var id_opt = EditInPlace._getOptionsReference(id);

	// If we can't get the id then don't process the event.
	if(!id) {
		return(false);
	}

	Element.addClassName(id, id_opt['mouseover_class']);
};

// Process mouseout events.
EditInPlace._mouseOut = function(event) {
	var id = Event.element(event).id;
	var id_opt = EditInPlace._getOptionsReference(id);

	// If we can't get the id then don't process the event.
	if(!id) {
		return(false);
	}

	Element.removeClassName(id, id_opt['mouseover_class']);
};

// Process mouseclick events.
EditInPlace._mouseClick = function(event) {
	var id = Event.element(event).id;
	var id_opt = EditInPlace._getOptionsReference(id);
	var form = EditInPlace._formField(id) + EditInPlace._formButtons(id);
	
	// If we can't get the id then don't process the event.
	if(!id) {
		return(false);
	}

	// MODIFIED BY NICK DUNN 14/08/2006
	// Stops observing click event in case of double click during fade transition
	Event.stopObserving(id, id_opt['click'], id_opt['mouseclick_observer']);
	// Fade original content and show editing form
	fader = new fx.Opacity(id, {duration: 400, onComplete: function(){
		Element.hide(id);
		
		new Insertion.After(id, form);
		Field.focus(id + '_edit');
		
		// Watch for button clicks.
		Event.observe(id + '_save', 'click', EditInPlace._saveClick);
		Event.observe(id + '_cancel', 'click', EditInPlace._cancelClick);
	}});
	fader.toggle();
	// END
};

// Process save button clicks.
EditInPlace._saveClick = function(event) {
	var id = Event.element(event).id.replace(/_save$/, '');
	var id_opt = EditInPlace._getOptionsReference(id);

	// Package data for the AJAX request.
	var new_text = escape($F(id + '_edit'));
	// this next line modified for darkroom [saji]
	var params = 'id=' + id + '&content=' + new_text + '&path=' + photo_path + '&img=' + photo_img;
	if(id_opt['type'] == 'select') {
		params += '&option_name=' + $(id + '_option_' + new_text).innerHTML;
	}

	// Build saving message.
	var saving = '<span class="' 
		+ id_opt['saving_class'] + '">' + id_opt['saving_text'] + '</span>\n';

	// Turn off event watching while saving changes.
	Event.stopObserving(id, 'mouseover', id_opt['mouseover_observer']);
	Event.stopObserving(id, 'mouseout', id_opt['mouseout_observer']);
	Event.stopObserving(id, id_opt['click'], id_opt['mouseclick_observer']);

	// Remove the form editor and display the saving message.
	Element.remove(id + '_editor');
	
	$(id).innerHTML = saving;
	
	// MODIFIED BY NICK DUNN 14/08/2006
	// Make the saving message visible, and fade it in
	Element.show(id);
	fader = new fx.Opacity(id, {duration: 400});
	fader.custom(0, 1);	
	// END

	// Send the changes via AJAX.
	var ajax_req = new Ajax.Request(
		id_opt['save_url'],
		{
			method: 'post',
			postBody: params,
			onSuccess: function(t) { EditInPlace._saveComplete(id, t); },
			onFailure: function(t) { EditInPlace._saveFailed(id, t); }
		}
	);
};

// Process cancel button clicks.
EditInPlace._cancelClick = function(event) {
	var id = Event.element(event).id.replace(/_cancel$/, '');
	var id_opt = EditInPlace._getOptionsReference(id);
	
	// Remove the edit form and mouseover class.
	Element.remove(id + '_editor');
	Element.removeClassName(id, id_opt['editfield_class']);

	// Display empty edit text if the id was empty.
	if($(id).innerHTML == '') {
		id_opt['id_empty'] = true;
		$(id).innerHTML = id_opt['empty_text'];
		Element.addClassName(id, id_opt['empty_class']);
	}
	
	// MODIFIED BY NICK DUNN 14/08/2006
	// Show the original content again, and fade it in
	Element.show(id);
	fader = new fx.Opacity(id, {duration: 400});
	fader.custom(0, 1);

	// Enable observe event after disable it to prevent double clicking during MOO FX animation
	Event.observe(id, id_opt['click'], id_opt['mouseclick_observer']);
	// END
};

// Complete the successful AJAX request.
EditInPlace._saveComplete = function(id, t) {
	var id_opt = EditInPlace._getOptionsReference(id);
	
	// Check to see if the user deleted all of the text.
	if(t.responseText == '') {
		id_opt['is_empty'] = true;
		$(id).innerHTML = id_opt['empty_text'];
		Element.addClassName(id, id_opt['empty_class']);
	}
	else {
		id_opt['is_empty'] = false;
		Element.removeClassName(id, id_opt['empty_class']);
		// MODIFIED BY NICK DUNN 14/08/2006
		// Fade out the saving message. Once the fade is complete,
		// set the new content from the Ajax request and fade it in
		fader = new fx.Opacity(id, {duration: 400, onComplete: function(){
			$(id).innerHTML = t.responseText;
			newfader = new fx.Opacity(id, {duration: 400});
			newfader.hide();
			newfader.custom(0, 1);
		}});
		fader.custom(1, 0);
		// END
	}
	
	id_opt['orig_text'] = t.responseText;
			
	// Turn on event watching again.
	Event.observe(id, 'mouseover', id_opt['mouseover_observer']);
	Event.observe(id, 'mouseout', id_opt['mouseout_observer']);
	Event.observe(id, id_opt['click'], id_opt['mouseclick_observer']);
};

// Complete the failed AJAX request.
EditInPlace._saveFailed = function(id, t) {
	var id_opt = EditInPlace.getOptionsReference(id);

	// Restore the original text, remove the editfield class
	// and alert the user that the save failed.
	$(id).innerHTML = id_opt['orig_text'];
	Element.removeClassName(id, id_opt['editfield_class']);
	alert(id_opt['savefailed_text']);

	// Turn on event watching again.
	Event.observe(id, 'mouseover', id_opt['mouseover_observer']);
	Event.observe(id, 'mouseout', id_opt['mouseout_observer']);
	Event.observe(id, id_opt['click'], id_opt['mouseclick_observer']);
};

// Build the form field to edit.
EditInPlace._formField = function(id) {
	var id_opt = EditInPlace._getOptionsReference(id);

	// If the original text value was empty then
	// make it empty again before we allow editing.
	if(id_opt['is_empty'] == true) {
		Element.removeClassName(id, id_opt['empty_class']);
		$(id).innerHTML = '';
	}

	// Every form is wrapped in a span.
	var field = '<span id="' + id + '_editor">\n';

	// Text input edit.
	if(id_opt['type'] == 'text') {
		var size = id_opt['orig_text'].length + 15;
		// Don't let the size get bigger than the maximum.
		if(size > id_opt['max_size']) {
			size = id_opt['max_size'];
		}

		// Use a specific size if one was provided.
		size = (id_opt['size'] ? id_opt['size'] : size);

		field += '<input id="' + id + '_edit" class="'
			+ id_opt['editfield_class'] + '" name="' + id
			+ '_edit" type="text" size="' + size + '" value="'
			+ id_opt['orig_text'] + '"';

//		if(id_opt['select_text']) {
//			field += 'onfocus="this.select();"';
//		}
		
		// saji - 4/27 disable keyboard input handler
		field += ' onfocus="Event.stopObserving(document, ' + "'keydown', arrowNav);" + '" ';
		field += ' onblur="Event.observe(document, ' + "'keydown', arrowNav, false);" + '" ';
				
		field += ' /><br />\n';
	}
	// Textarea edit.
	else if(id_opt['type'] == 'textarea') {
		// Calculate the number of rows to use.
		var rows = (id_opt['orig_text'].length / id_opt['cols']) + 4;

		// Use a specific rows if one was provided.
		rows = (id_opt['rows'] ? id_opt['rows'] : rows);

		field += '<textarea id="' + id + '_edit" class="'
			+ id_opt['editfield_class'] + '" name="' + id + '_edit" rows="'
			+ rows + '"cols="' + id_opt['cols'] + '"'

		if(id_opt['select_text']) {
			field += 'onfocus="this.select();"';
		}

		// saji - 4/27 disable keyboard input handler
		field += ' onfocus="Event.stopObserving(document, ' + "'keydown', arrowNav);" + '" ';
		field += ' onblur="Event.observe(document, ' + "'keydown', arrowNav, false);" + '" ';
		
		field += '>' + id_opt['orig_text'] + '</textarea><br />\n';
	}
	// Select edit.
	else if(id_opt['type'] == 'select') {
		field += '<select id="' + id + '_edit" class="'
			+ id_opt['editfield_class'] + '" name="' + id + '_edit">\n';

		for(var i in id_opt['options']) {
			field += '<option id="' + id + '_option_' + i + '" name="' + id
				+ '_option_' + i + '" value="' + i + '"';

			if(id_opt['options'][i] == $(id).innerHTML) {
				field += ' selected="selected"';
			}

			field += '>' + id_opt['options'][i] + '</option>\n';
		}

		field += '</select>\n';
	}

	return(field);
};

// Build form buttons.
EditInPlace._formButtons = function(id) {
	var id_opt = EditInPlace._getOptionsReference(id);

	return(
		'<span id="eip-buttons"><input id="' + id + '_save" class="' + id_opt['savebutton_class']
		+ '" type="button" value="' + id_opt['savebutton_text']
		+ '" /> <input id="' + id + '_cancel" class="'
		+ id_opt['cancelbutton_class'] + '" type="button" value="'
		+ id_opt['cancelbutton_text'] + '" /></span></span>\n'
	);
};

