// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BŽdard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * Extends the native element in order to add the container properties. The
 * container is basically the reference of the class which is holding an
 * element.
 * @package core
 * @subpackage element
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Lemieux Bedard Communication (francois.patry@lemieuxbedard.com)
 * @since 1.0.0
 * @version 1.0.0
 */
Element.implement
({
	/**
	 * @var array The array of object used as actors.
	 */
	actors : null,
	
	/**
	 * @var int The count of actors.
	 */
	actorsCount : 0,

	/**
	 * Set the id of an element. This method is simply a shortcut to the common
	 * set property method allready in place.
	 * @param string The id.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setId : function(id) {
		this.set('id', id);
	},

	/**
	 * Return the id of an element. This method is simply a shortcut to the common
	 * get property method allready in place.
	 * @return string The id.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	getId : function() {
		return this.get('id');
	},
	
	/**
	 * Return the text of an element.
	 * @return string The text.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	getText : function() {
		return this.get('text');
	},
	
	/**
	 * Set the text of an element.
	 * @param string The text.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setText : function(text) {
		this.set('text', text);
	},
	
	/**
	 * Set the inside html of an element.
	 * @param array The html.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setHtml : function(html) {
		return this.set('html', html);
	},
	
	/**
	 * Return the inside html of an element.
	 * @return array The html.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	getHtml : function() {
		return this.get('html');
	},
	
	/**
	 * This method will dispose of an attribute but the attribute will be stored
	 * in the internal class properties using the store method.
	 * @param string The property name.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	disposeProperty : function(property) {
		this.store(property, null);
		this.store(property, this.getProperty(property));
		this.removeProperty(property);
	},
	
	/**
	 * Return the property that was disposed before it was removed.
	 * @param string The property name.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	getDisposedProperty : function(property) {
		return this.retrieve(property);
	},
	
	/**
	 * This method will dispose the href attribute but the attribute will be stored
	 * in the internal class properties using the store method.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	disposeHrefProperty : function() {
		this.disposeProperty('href');
		this.setStyle('cursor', 'pointer');
	},
	
	/**
	 * Return the href property that was disposed before it was removed.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	getDisposedHrefProperty : function() {
		return this.getDisposedProperty('href');
	},
	
	/**
	 * Initialize the actor array.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	initializeActors : function() {
		if (this.actors == null) this.actors = new Array();
	},
	
	/**
	 * Add an actor to the current element. An actor is basically a class
	 * which will act as a complex event.
	 * @param object The actor object.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	addActor : function(actor) {
		this.initializeActors();
		this.actors.push(actor);
		this.actorsCount++;
		actor.applyOn(this);
	},
	
	/**
	 * Return an actor based on the instance name.
	 * @param object The actor class.
	 * @return object The actor.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	getActor : function(actorName) {
		this.initializeActors();
		for (var i = 0; i < this.actors.length; i++) {
			if (this.actors[i] instanceof actorName) {
				return this.actors[i];
			}
		}
		return null;
	},
	
	/**
	 * Return the ammount of actors used on this element.
	 * @return int The actor count.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */	
	getActorCount : function() {
		return this.actorCount;
	},
	
	/**
	 * Indicate whether or not a given actor is acting in this object.
	 * @param object The actor class.
	 * @return bool True if the actor is present.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	hasActor : function(actorName) {
		this.initializeActors();
		for (var i = 0; i < this.actors.length; i++) {
			if (this.actors[i] instanceof actorName) {
				return true;
			}
		}
		return false;
	}
});// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BÃ©dard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * An actor is a class that will basically activate itself upon an element using
 * the actAs method of the element.
 * @package core
 * @subpackage actor
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Lemieux Bedard Communication (francois.patry@lemieuxbedard.com)
 * @since 1.0.0
 * @version 1.0.0
 */
var MooActor = new Class
({
	/**
	 * @var implements MooElement, Event, Options
	 */
	Implements : [Events, Options],
	
	/**
	 * @var object The element on which the actor will act on.
	 */
	element : null,
	
	/**
	 * Initialize the actor by setting the options.
	 * @param object The options.
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	initialize : function(options) {
		this.setOptions(options);
		return this;
	},
	
	/**
	 * This method is called when an object is given as an actor to an element.
	 * @param object The element to apply everything's on.
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	applyOn : function(element) {
		this.element = element;
		return this;
	}	
});// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BÃ©dard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * This actor will handle the look of the different navigation element.
 * @package core
 * @subpackage actor
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Lemieux Bedard Communication (francois.patry@lemieuxbedard.com)
 * @since 1.0.0
 * @version 1.0.0
 */
var MooNavigationElementActor = new Class
({
	/**
	 * @extends MooActor
	 */
	Extends : MooActor,
	
	/**
	 * @var object The options.
	 */
	options : {
		onEmphasize : $empty,
		onNormalize : $empty,
		css : {
			current : 'cur',
			alternate : 'alt'
		}
	},
		
	/**
	 * This method is called when an object is given as an actor to an element.
	 * @param object The element to apply everything's on.
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	applyOn : function(element) {
		this.parent(element);
		this.element.addEvent('mouseenter', this.onEmphasize.bind(this));
		this.element.addEvent('mouseleave', this.onNormalize.bind(this));
		return this;
	},
	/**
	 * This event is called when the mouse moves over the tab for the first
	 * time. This method will basically highlight the tab.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	onEmphasize : function() {
		if (this.isCurrent() == false) {
			this.element.addClass(this.options.css.alternate);
			this.fireEvent('onEmphasize');
		}
	},

	/**
	 * This event is called when the mouse moves out the tab for the first
	 * time. This method will basically unhighlight the tab.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	onNormalize : function() {
		if (this.isCurrent() == false) {
			this.element.removeClass(this.options.css.alternate);
			this.fireEvent('onNormalize');
		}
	},

	/**
	 * Indicate wheter or not the tab is considered has the current tab. This
	 * is given by the class named current.
	 * @return bool True if the tab is a current one.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	isCurrent : function() {
		return this.element.hasClass(this.options.css.current);
	}
});// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BÃ©dard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * This actor will handle the look of the different navigation element.
 * @package core
 * @subpackage actor
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Lemieux Bedard Communication (francois.patry@lemieuxbedard.com)
 * @since 1.0.0
 * @version 1.0.0
 */
var MooSlidingElementActor = new Class
({
	/**
	 * @extends MooActor
	 */
	Extends : MooActor,
	
	/**
	 * @var object The options.
	 */
	options : {},
	
	/**
	 * @var object The slider.
	 */
	fx: null,
		
	/**
	 * This method is called when an object is given as an actor to an element.
	 * @param object The element to apply everything's on.
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	applyOn : function(element) {
		this.parent(element);
		this.fx = new Fx.Slide(element);
	},
	
	hide: function() {
		this.fx.hide();
	},
	
	show: function() {
		this.fx.show();
	},
	
	slideIn: function() {
		this.fx.slideIn('vertical');
	},
	
	slideOut: function() {
		this.fx.slideOut('vertical');
	}
	
});// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BŽdard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * MooSelector is a mootools implementation of the original event selector.
 * This been ported to mootools by rossco.
 * @package core
 * @subpackage selector
 * @author Ross Lawley
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Ross Lawley
 * @since 1.0.0
 * @version 1.0.0
 */
var MooSelector = new Class
({
	/**
	 * Apply the selector rules when the dom ready event is called. This event
	 * is similar to the load event except it does not wait until the image are
	 * fully loaded. This is much faster.
	 * @param object The rules.
	 * @return object This class.
	 * @author Ross Lawley
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	start : function(rules) {
		window.addEvent('domready', function() {
			this.assign(rules);
		}.bind(this));
		return this;
	},

	/**
	 * Assign the selector rules when the dom ready event is called. This event
	 * is similar to the load event except it does not wait until the image are
	 * fully loaded. This is much faster.
	 * @param object The rules.
	 * @return object This class.
	 * @author Ross Lawley	 
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	assign : function(rules) {
		for (var key in rules) {
			var rule = rules[key];
			key.clean().split(',').each(function(selector) {
				var pair = selector.split('::');
				$$(pair[0]).each(function(elem) {
					if (pair.length == 1) return rule(elem);
					// attach the event on the selector
					elem.addEvent(pair[1], rule.pass(elem));
				});
			});
		}
	}
});// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BÃ©dard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * MooElementFinder is a class used to find an element using a selector from
 * a given context. The context can be a dom tree or a text tree given by an
 * ajax response.
 * @package core
 * @subpackage finder
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Lemieux Bedard Communication (francois.patry@lemieuxbedard.com)
 * @since 1.0.0
 * @version 1.0.0
 */
var MooElementFinder = new Class
({
	/**
	 * @var object The context to search in.
	 */
	context : null,

	/**
	 * Constructor. Set the context used to search in. The context may be a
	 * simple dom object or an ajax response object. This object will search
	 * in both type.
	 * @param object The context.
	 * @return object This class.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	initialize : function(context) {
		this.setContext(context);
		return this;
	},

	/**
	 * Set the context used to search in. The context may be a simple dom object
	 * or an ajax response object. This object will search in both type.
	 * @param object The context.
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setContext : function(context) {
		if (context) { 
			if (typeof context == 'string') { 			
				var html = context.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
				html = (html) ? html[1] : context;		
				this.context = new Element('div').setHtml(html);
			}
		}
		return this;
	},

	/**
	 * Return the context used to search in. The context may be a simple dom object
	 * or an ajax response object. This object will search in both type.
	 * @return object The context.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	getContext : function() {
		return this.context;
	},

	/**
	 * Try to find an element in the current context. It's important to specify
	 * both the element id and tag so the search will be successfully in a
	 * ajax response type of context.
	 * @param string The search id.
	 * @param string The search type.
	 * @return object The result.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	find : function(selector) {
		if (this.context == null) return document.getElement(selector);
		// the getElement method will only for some reason find class selectors and
		// not selectors with an id. If we are looking for an id we must search it
		// the old string way
		if (selector.search('#') > -1) {
			selector = selector.replace('#', '');
			selector = selector.replace(' ', '');
			return this.context.getElement('*[id=' + selector + ']');
		} else {
			return this.context.getElement(selector);
		}
	}
});// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BÃ©dard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * MooForm is a class which sends a form through an ajax query and handle
 * the result. 
 * @package core
 * @subpackage finder
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Lemieux Bedard Communication (francois.patry@lemieuxbedard.com)
 * @since 1.0.0
 * @version 1.0.0
 */
var MooForm = new Class
({
	/**
	 * @implements Events Options The basic element methods.
	 */
	Implements : [Events, Options],
	
	/**
	 * @var object The main element used.
	 */
	element : null,
	
	/**
	 * @var object The options.
	 */
	options : {
		onRequest : $empty,     // this event is called when the request is sent.
		onSuccess : $empty,     // this event is called when the request is completed.
		onError   : $empty,     // this event is called when the form have errors on the response.
		updateOnSuccess : true, // replace the current form with the success selector on success.
		inputSelector : '',     // the selector used to find the input form.
		successSelector : ''    // the selector used to find the success element.
	},
	
	/**
	 * Constructor. Initialize the form handler.
	 * @param object The form element.
	 * @param object The options. 
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	initialize : function(form, options) {
		this.setOptions(options);
		this.element = $(form);
		return this;
	},

	/**
	 * Submit the form by creating the ajax request.
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	submit : function() {
		this.fireEvent('request');
		this.element.set('send', { method : 'post', headers: {'X-Request': 'text/html'}, onComplete : this.onComplete.bind(this), evalScripts : true });
		this.element.send();
		return this;
	},

	/**
	 * Find the errors or the success page in the response and update it.
	 * @param object The response. 
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	complete : function(response) {
		var error = false;			
		var oldFormFinder = new MooElementFinder();
		var newFormFinder = new MooElementFinder(response);
		var oldForm = oldFormFinder.find(this.options.inputSelector);
		var newForm = newFormFinder.find(this.options.inputSelector);	
		if (newForm) {			
			var newFormLabels = newForm.getElements('label');
			var oldFormLabels = oldForm.getElements('label');			
			newFormLabels.each(function(label, index) {
				var newLabel = newFormLabels[index];
				var oldLabel = oldFormLabels[index];												
				var newField = newForm.getElement('*[id=' + newLabel.get('for') + ']');
				var oldField = oldForm.getElement('*[id=' + oldLabel.get('for') + ']');				 								 				
				if (newLabel.hasClass('error')) {
					oldLabel.addClass('error');
					error = true;							
					if (oldField) {
						oldField.addClass('error');
					}				
					// add the error message under the field if a new message is set
					var newError = newField.getNext('div.errors');
					var oldError = oldField.getNext('div.errors');
					if (newError) {
						var update = true;
						if (oldError) {
							if (oldError.getText() == newError.getText()) {
								update = false;
							}
						}
						if (update) {
							if (oldError) {
								newError.fade('hide');
								newError.replaces(oldError);
								newError.fade(1);	
							} else {
								newError.fade('hide');
								newError.inject(oldField, 'after');
								newError.fade(1);	
							}							
						}						
					}									
				} else {				
					oldLabel.removeClass('error');							
					if (oldField) {
						oldField.removeClass('error');
						// remove the error message if it exists
						var oldError = oldField.getNext('div.errors');
						if (oldError) {
							oldError.fade(0);
							oldError.dispose();
						}
					}				
				}					
			});			
		} 
		// at this point the form does not contain any errors, we assume it's been submited
		// successfully so we show the success part using the selector
		if (error == false) {			
			if (this.options.updateOnSuccess) {
				var successFinder = new MooElementFinder(response);
				var successFinderElement = successFinder.find(this.options.successSelector);
				if (successFinderElement) {
					oldForm.fade('hide');
					successFinderElement.replaces(oldForm);
					successFinderElement.fade(1);
				}
			}
		} else {
			this.fireEvent('error', response);
		}
		this.fireEvent('success', response);
	},
		
	/**
	 * This method gets called when the request is completed.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	onComplete : function(response) {
		this.complete(response);
	}
}); 
 
/* A workaround for IE issues in mootools 1.2.1
 * - Recreates FX.Scroll() but utilises 1.2.0's getPosition/getOffset routines.
 */
Fx.ScrollTo = new Class({
 
    'Extends': Fx.Scroll,
 
    'styleString': Element.getComputedStyle,
    'styleNumber': function(element, style) {
        return this.styleString(element, style).toInt() || 0;
    },
    'borderBox': function(element) {
        return this.styleString(element, '-moz-box-sizing') == 'border-box';
    },
    'topBorder': function(element) {
    return 0;
        return this.styleNumber(element, 'border-top-width');
    },
    'leftBorder': function(element) {
    return 0;
        return this.styleNumber(element, 'border-left-width');
    },
    'isBody': function(element) {
        return (/^(?:body|html)$/i).test(element.tagName);
    }, 
    'toElement': function(el) {
        var offset   = {x: 0, y: 0};
        var element  = $(el);
       
        if (this.isBody(element)) {
            return offset;
        }
        var scroll = element.getScrolls();
               
        while (element && !this.isBody(element)){
            offset.x += element.offsetLeft;
            offset.y += element.offsetTop;
           
            if (Browser.Engine.gecko){
                if (!this.borderBox(element)){
                    offset.x += this.leftBorder(element);
                    offset.y += this.topBorder(element);
                }
                var parent = element.parentNode;
                if (parent && this.styleString(parent, 'overflow') != 'visible'){
                    offset.x += this.leftBorder(parent);
                    offset.y += this.topBorder(parent);
                }
            } else if (Browser.Engine.trident || Browser.Engine.webkit){
                offset.x += this.leftBorder(element);
                offset.y += this.topBorder(element);
            }
 
            element = element.offsetParent;
            if (Browser.Engine.trident) {
                while (element && !element.currentStyle.hasLayout) {
                    element = element.offsetParent;
                }
            }
        }
        if (Browser.Engine.gecko && !this.borderBox(element)){
            offset.x -= this.leftBorder(element);
            offset.y -= this.topBorder(element);
        }
       
        var relative = this.element;
        var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0};
        var position = {x: offset.x - scroll.x, y: offset.y - scroll.y};
       
        return this.start(position.x - relativePosition.x, position.y - relativePosition.y);
    }
});
 
 // +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BÃ©dard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * A command is basically an ajax request with extra options.
 * @package core
 * @subpackage command
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Lemieux Bedard Communication (francois.patry@lemieuxbedard.com)
 * @since 1.0.0
 * @version 1.0.0
 */
var MooCommand = new Class
({	
	/**
	 * @var implements MooElement, Event, Options
	 */
	Implements : [Events, Options],

	/**
	 * @var string The url to request the command.
	 */
	url: null,

	/**
	 * @var object The ajax request.
	 */
	request: null,

	/**
	 * @var hash The ajax request headers.
	 */
	headers: null,
	
	/**
	 * @var hash The ajax request parameters.
	 */
	parameters: null,
	
	/**
	 * @var object The options.
	 */
	options: {
		onRequest: $empty,
		onComplete: $empty,
		evalScripts: false,
		method: 'post'
	},
	
	/**
	 * Initialize the actor by setting the options.
	 * @param object The options.
	 * @return object A reference to this object.
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	initialize : function(url, options) {
		this.setUrl(url);
		this.setOptions(options);
		this.headers = new Hash();
		this.parameters = new Hash();
		return this;
	},
	
	/**
	 * Set the url to execute the command.
	 * @param string The url.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setUrl: function(url) {
		this.url = url;
	},

	/**
	 * Set an header to send to the request.
	 * @param string The header name.
	 * @param string The header value.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setHeader: function(name, value) {
		this.headers.set(name, value);
	},
	
	/**
	 * Set the content request header which will be handled by the server in order to
	 * return the content or the content with the decorator.
	 * @param string content or decorator.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setContentRequestHeader: function(value) {
		this.setHeader('X-Content-Request', value);
	},
	
	/**
	 * Set an parameter to send to the request.
	 * @param string The parameter name.
	 * @param string The parameter value.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	setParameter: function(name, value) {
		this.parameters.set(name, value);
	},
	
	/**
	 * Clear all the parameters.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	clearParameters: function() {
		this.parameters = null;
		this.parameters = new Hash();
	},
	
	/**
	 * Prepare the ajax request.
	 * @param string The mode
	 * @param string The parameter value.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	prepare: function(mode) {
		this.fireEvent('request');
		switch (mode) {
			case 'json': this.request = new Request.JSON({url: this.url, method: this.options.method, evalScripts: this.options.evalScripts, data: this.parameters.toQueryString(), headers: this.headers.getClean(), onComplete: this.jsonRequestCompleted.bind(this)}); break;
			case 'html': this.request = new Request.HTML({url: this.url, method: this.options.method, evalScripts: this.options.evalScripts, data: this.parameters.toQueryString(), headers: this.headers.getClean(), onComplete: this.htmlRequestCompleted.bind(this)}); break;
			default:     this.request = new Request.HTML({url: this.url, method: this.options.method, evalScripts: this.options.evalScripts, data: this.parameters.toQueryString(), headers: this.headers.getClean(), onComplete: this.htmlRequestCompleted.bind(this)}); break;  
		}
	},
	
	/**
	 * Execute the command and request for an html response.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	executeHtml: function() {
		this.setContentRequestHeader('content');
		this.prepare('html');
		this.request.send();
	},
	
	/**
	 * Execute the command and request for a json response.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	executeJson: function() {
		this.prepare('json');
		this.request.send();
	},

	/**
	 * This is called when the html request is completed.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */
	htmlRequestCompleted: function(responseTree, responseElements, responseHtml, responseJavaScript) {
		this.fireEvent('complete', [responseTree, responseElements, responseHtml, responseJavaScript]);
	},
	
	/**
	 * This is called when the html request is completed.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */	
	jsonRequestCompleted: function(responseJson, responseText) {
		this.fireEvent('complete', [responseJson, responseText]);
	},
	
	/**
	 * This is called when the html request is completed.
	 * @return void
	 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
	 * @since 1.0.0
	 */	
	isError: function() {
		return false;
	}
});// +---------------------------------------------------------------------------+
// | This file is part of the Mootools Addon project.                          |
// | Copyright (C) Lemieux BÅ½dard Communication                                |
// |                                                                           |
// | For the full copyright and license information, please view the LICENSE   |
// | file that was distributed with this source code.                          |
// +---------------------------------------------------------------------------+

/**
 * MooProgressIndicator.
 * @package core
 * @subpackage selector
 * @author Ross Lawley
 * @author Jean-Philippe Dery (jean-philippe.dery@lemieuxbedard.com)
 * @copyright Ross Lawley
 * @since 1.0.0
 * @version 1.0.0
 */
var MooProgressIndicator = new Class
({
	/**
	 * @implements Events Options The basic element methods.
	 */
	Implements: [Events, Options],
	
	/**
	 * @var string The path to the loading image.
	 */
	source: null,
	
	/**
	 * @var string The element which will be used to position the indicator.
	 */
	guide: null,
	
	/**
	 * @var object The image element injected.
	 */
	image: null,
	
	/**
	 * @var object The options.
	 */
	options: {
		offset: {
			x: 0, 
			y: 0
		}
	},
	
	/**
	 *
	 */
	initialize: function(source, guide, options) {
		this.setOptions(options);
		this.source = source;
		this.guide = $(guide);
	},
	
	startAnimation: function() {
		this.image = new Element('img', {'src': this.source});
		this.image.fade('hide');
		this.image.setStyle('position', 'absolute');
		if (this.options.offset.x) this.image.setStyle('margin-left', this.options.offset.x);
		if (this.options.offset.y) this.image.setStyle('margin-top', this.options.offset.y);
		this.image.inject(this.guide, 'after');
		this.image.fade(1);
		this.guide.fade(0.4);
	},
	
	stopAnimation: function() {
		if (this.image) {
			new Fx.Tween(this.guide).start('opacity', 0.4, 1);
			new Fx.Tween(this.image).start('opacity', 1, 0).chain(function() {
				this.image.dispose();
				this.image = null;
			}.bind(this));
		}
	}
});


