/****************************************************************************
 * HidingForm : Gives a form (or any block-level element) the
 * 				ability to be hidden/shown in response to another
 * 				element's click event.
 * 
 *		Usage : <script type="text/javascript">
 * 					new HidingForm('container_id', 'toggle_id', [options]);
 *				</script>	
 * 
 *    Options : onShow, onHide - functions to show/hide the container
 *    				(default: _show, _hide)
 *    			hidePrompt - toggle.innerHTML when container is visible
 *    				(default: 'Cancel')
 *    			showPrompt - toggle.innerHTML when container is hidden
 *    				(default: whatever the text was when initialized)
 *				is_visible - container's initial visibility (true/false)	
 *					(default: false)		
 ****************************************************************************/
HidingForm = Class.create();

HidingForm.prototype = {	

	initialize: function(container, toggle, options) {
		var hiding_form = this;
		this.container = $(container);
		this.toggle = $(toggle);	
		this.options = options || { }		
		this.hidePrompt = this.options.hidePrompt || 'Cancel';
		this.showPrompt = this.options.showPrompt || this.toggle.innerHTML;
		this.show = this.options.onShow || this._show;
		this.hide = this.options.onHide || this._hide;
		this.hideElementOnFormShow = $(this.options.hideElementOnFormShow) || null;
		this.is_visible = this.options.is_visible || false;
		if (!this.is_visible) Element.setStyle(container, {display:'none'});
		else Element.setStyle(container, {display:'block'});
		this.toggleOnClick = this._toggle.bindAsEventListener(this);
		Event.observe(this.toggle, "click", this.toggleOnClick);
	},
	
	_toggle: function(event) { // could add pre/post hooks here if necessary
		if(this.is_visible) this.hide();
		else this.show();		
		this.is_visible = !this.is_visible;
	},
	
	_show: function() {
		this.toggle.innerHTML = this.hidePrompt;
		Effect.BlindDown(this.container, {duration: .25});
		if ($('swap')){
			new Effect.Opacity('swap',  {duration:0.5, from:1.0, to:0.3});
		}
		// Added Jan 16/07: Hides the "Order" button.
		//Element.setStyle($('swap"'), {display:'none'});
		
	},
	
	_hide: function() {
		Effect.BlindUp(this.container, {duration: .25});
		this.toggle.innerHTML = this.showPrompt;
		if ($('swap')){
			new Effect.Opacity('swap',  {duration:0.5, from:0.3, to:1.0});
		}
		// Added Jan 16/07: Shows the "Order" button.
		//Element.setStyle($('swap"'), {display:'block'});
	}	
}


/**
 *  OrderableList -- class names & styles aren't being correctly applied in Safari
 */
// prototype.js, line 1578 (Element.ClassNames)

OrderableList = Class.create();
 
OrderableList.prototype = {
	initialize: function(object_list, item_class, msgTarget, url, togglebutton, options) {
		var orderable_list = this;
		this.object_list = $(object_list);
		this.msgTarget = $(msgTarget);
		this.msgTargetID = msgTarget;
		this.togglebutton = togglebutton;
		this.item_class = item_class;
		this.list_items = document.getElementsByClassName(item_class);
		this.url = url;
		this.options = options || { }
		
		// This is pretty gross...
		//this.initialContent = this.object_list.innerHTML;
		
		// Look for specific buttons
		this.startButton = $(this.options.startButton || 'startOrder');
		this.saveButton = $(this.options.saveButton || 'saveOrder');
		this.cancelButton = $(this.options.cancelButton || 'cancelOrder');
		
		this.defaultDiv = $('defaultDiv');
		this.orderingDiv = $('orderingDiv');
		
		this.startOrder = this._makeOrderable.bindAsEventListener(this);
		this.saveOrder = this._saveOrder.bindAsEventListener(this);
		this.cancelOrder = this._cancelOrder.bindAsEventListener(this);
		
		Event.observe(this.startButton, "click", this.startOrder);
		Event.observe(this.saveButton, "click", this.saveOrder);
		Event.observe(this.cancelButton, "click", this.cancelOrder);
		
		//this.initialOrder = Sortable.serialize(this.object_list, {});
		
		this._destroyOrderable();
	},
		
	_makeOrderable: function() {
		Sortable.create(this.object_list, {
			tag:'div',
			only: this.item_class,
			handle:'handle',
			overlap: 'horizontal',
			constraint: false}
		);
		this.is_orderable = true;
		this._updateListItems('sortable');		
		Element.setStyle(this.saveButton, {display:'block'});
		Element.setStyle(this.cancelButton, {display:'block'});
		Element.setStyle(this.startButton, {display:'none'});
		if ($(this.togglebutton)){
			new Effect.Opacity(this.togglebutton,  {duration:0.5, to:0.3});
		}
		// set messaging
		Element.setStyle(this.defaultDiv, {display:'none'});
		Element.setStyle(this.orderingDiv, {display:'block'});
	},
	
	_saveOrder: function() {
			this.msgTarget.innerHTML = 'Saving...';
			// set messaging
			Element.setStyle(this.defaultDiv, {display:'none'});
			Element.setStyle(this.orderingDiv, {display:'none'});
			Element.setStyle(this.msgTarget, {display:'none'});
			
			new Ajax.Updater(this.msgTarget, this.url, {
				onComplete:function() {
					fadeaway = function(){	new Effect.Fade('msgTarget');	}
					window.setTimeout(fadeaway,500);
				},
				parameters:Sortable.serialize(this.object_list), evalScripts:true, asynchronous:true
			});
			new Effect.Appear(this.msgTargetID);
		this._destroyOrderable();
	}, // End _saveOrder()
	
	_cancelOrder: function() {
		// This is pretty gross...CSS doesn't get re-applied.  should find a DOM-friendly way...
		//this.object_list.innerHTML = this.initialContent;
		this._destroyOrderable();
	},
	
	_destroyOrderable: function() {
		Sortable.destroy(this.object_list);
		this.is_orderable = false;
		this._updateListItems('unsortable');
		Element.setStyle(this.saveButton, {display:'none'});
		Element.setStyle(this.cancelButton, {display:'none'});
		Element.setStyle(this.startButton, {display:'block'});
		// set messaging
		Element.setStyle(this.defaultDiv, {display:'block'});
		Element.setStyle(this.orderingDiv, {display:'none'});
		if ($(this.togglebutton)){
			new Effect.Opacity(this.togglebutton,  {duration:0.5, to:1.0});
		}
	},
	
	_updateListItems: function(new_class) {
	for (i=0; i<this.list_items.length; i++)
		this.list_items[i].className = new_class + " " + this.item_class;
	}

 };
 
 /*
  * Button for toggling a boolean attribute of an object.
  * Constructor takes the DOM ID of the button element,
  * the AJAX url to request, and a hash of options.
  * 
  */
 
 ToggleButton = Class.create();
 
 ToggleButton.prototype = {
 	
	initialize: function(button, state, url, options) {
		
		// Constants for state (should be moved to static members)
		this.OFF = -1;
		this.ON = 1;
		this.WAIT = 0;
		
		this.button = $(button);
		this.options = options || { };
		this.url = url;
		
		// Set up the CSS classes for the button
		this.buttonClass = this.button.className || 'toggleButton';
		this.onClass = this.options.onClass || 'toggleOn';
		this.offClass = this.options.onClass || 'toggleOff';
		this.waitClass = this.options.waitClass || 'toggleWait';
		
		this.toggleClick = this.press.bindAsEventListener(this);
		Event.observe(this.button, "click", this.toggleClick);
		
		// begin fugly:
		if (state == 'True')
			this.state = this.ON;
		else
			this.state = this.OFF
		this.showCurrentState();
	},
	
	showCurrentState: function() {
		if (this.state == 1)
			this.button.className = this.onClass;
		else if (this.state == -1)
			this.button.className = this.offClass;
		else if (this.state == this.WAIT)
			this.button.className = this.waitClass;
		this.button.addClassName(this.buttonClass);	
	},
	
	press: function() {
		this.wait();
		this.execRequest(); // Execute the AJAX request (will flip state if successfull)	
	},
	
	wait: function() {
		this.state = this.WAIT;
		this.showCurrentState();
	},
	turnOn: function() {
		this.state = this.ON;
		this.showCurrentState();
	},
	turnOff: function() {
		this.state = this.OFF;
		this.showCurrentState();
	},
	
	execRequest: function() {
		b = this;	
		new Ajax.Request(this.url, { 
			asynchronous:true,
			onSuccess: function(r) {
				if(r.responseText == 'True') b.turnOn();
				else if (r.responseText == 'False') b.turnOff();
			}
		});
	}
	
 };
 

 
 
 
 
 
 
 
