// *********************************************
// Element.getInputData
// Adds the getInputData method to an Element object.
// gets all input fields found within the element and returns it as an object.
// *********************************************
Element.implement({
	getInputData: function() {
		var obj, name, value;
		
		obj = $H({});
		this.getElements('input, select, textarea', true).each(function(el) {
			if (!(el.id || el.name) || el.disabled)
			{
				return;
			}
			name = (el.id) ? el.id : el.name;
			value = (el.tagName.toLowerCase() === 'select') ? Element.getSelected(el).map(function(opt) {
				return opt.value;
			}) : ((el.type === 'radio' || el.type === 'checkbox') && !el.checked) ? null: el.value;
			$splat(value).each(function(val) {
				if (typeof val !== 'undefined')
				{
					obj.set(name, val);
				}
			});
		});
		return obj;
	}
});

// *********************************************
// CHKOverrides functionality
//		Allows the ability to include alternate functions in the options
// *********************************************
var CHKOverrides = new Class({
	overrides: null,
	setOverrides: function() {
		if (($defined(this.options)) && ($defined(this.options.overrides)))
		{
			// take the object and turn it into a hash
			this.overrides = $H(this.options.overrides);
			if (($defined(this.overrides)) && (this.overrides.getLength() > 0))
			{
				// cycle through the object and take each of the functions and 
				// replace the existing or add new functions in this instance of the object
				this.overrides.each(function(value, key) {
					if ($type(value) === 'function')
					{
						this[key] = value;
					}
				}.bind(this));
			}
		}
	}
});

// *********************************************
// CHKClassName functionality
//		Adds the function getClassName that returns the 
//		name of the class of the current object.
// *********************************************
var CHKClassName = new Class({
	getClassName: function() { 
        var w = $H(window); 
        return w.keyOf(this.constructor); 
    }
});

// *********************************************
// CHKControl_Base - Base class for controls.  
//		Ensures that the basic object signature exists and implements common code.
//
//		Options: name, showClass, hideClass, useFx, fxOpenStyle, fxCloseStyle, fxWait, fxDuration, fxTransition
//		Properties: uid, isOpen
//		Methods: render, setPosition, show, hide, showDelay, hideDelay 
//		Events: onShow, onHide, onTransitionStart, onTransitionComplete
// *********************************************
var CHKControl_Base = new Class({
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		name: null,
		showClass: null,
		hideClass: null,
		selectedClass: null,
		deselectedClass: null,
		enabledClass: null,
		disabledClass: null,
		stopPropagation: true,
		preventDefault: false,
		useFx: false,
		fxOpenStylePre: null,
		fxOpenStyle: null,
		fxOpenStylePost: null,
		fxCloseStylePre: null,
		fxCloseStyle: null,
		fxCloseStylePost: null,
		fxSelectedStylePre: null,
		fxSelectedStyle: null,
		fxSelectedStylePost: null,
		fxDeselectedStylePre: null,
		fxDeselectedStyle: null,
		fxDeselectedStylePost: null,
		fxEnabledStylePre: null,
		fxEnabledStyle: null,
		fxEnabledStylePost: null,
		fxDisabledStylePre: null,
		fxDisabledStyle: null,
		fxDisabledStylePost: null,
		
		fxWait: false,
		fxDuration: 500,
		fxTransition: Fx.Transitions.Sine.easeInOut
	},
	controlEl: null,
	timer: null,
	uid: null,
	isOpen: true,
	isSelected: false,
	isEnabled: true,
	inTransition: false,
	fx: null,
	initialize: function(control, options) {
		this.controlEl = $(control);
		this.setOptions(options);
		this.setOverrides();
		var tempHash, keys, styles, count;

		tempHash = $H({});
		if ($defined(this.controlEl))
		{
			// bubble up the uid from the control element
			this.uid = this.controlEl.uid;
			
			// bubble up the instance name from the element class if it hasn't been assigned already
			if ((!$defined(this.options.name)) && (this.controlEl.className.contains('js_name_')))
			{
				this.controlEl.className.split(' ').each(function(item, index) {
					if (item.contains('js_name_'))
					{
						this.options.name = item.replace('js_name_', '');
					}
				}.bind(this));
			}
			
			// isOpen detection
			if (($defined(this.options.useFx)) && (this.options.useFx))
			{
				if ($defined(this.options.fxOpenStyle))
				{
					if ($type(this.options.fxOpenStyle) === 'object')
					{

						tempHash = $H(this.options.fxOpenStyle);
						keys = tempHash.getKeys();
						styles = $H(this.controlEl.getStyles(keys));
						count = 0;
						
						keys.each(function(item, index) {
							if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
							{
								count++;
							}
						}.bind(this));
						
						if (count === keys.length)
						{
							this.isOpen = true;
						}
					}
				}
				
				if ($defined(this.options.fxCloseStyle))
				{
					if ($type(this.options.fxCloseStyle) === 'object')
					{
						tempHash = $H(this.options.fxCloseStyle);
						keys = tempHash.getKeys();
						styles = $H(this.controlEl.getStyles(keys));
						count = 0;
						
						keys.each(function(item, index) {
							if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
							{
								count++;
							}
						}.bind(this));
						
						if (count === keys.length)
						{
							this.isOpen = false;
						}
					}
				}
			}
			else
			{
				if ($defined(this.options.showClass))
				{
					switch ($type(this.options.showClass))
					{
						case 'string':
							if ((this.options.showClass !== "") && (this.controlEl.hasClass(this.options.showClass)))
							{
								this.isOpen = true;
							}
							break;
						case 'object':
							tempHash = $H(this.options.showClass);
							keys = tempHash.getKeys();
							styles = $H(this.controlEl.getStyles(keys));
							count = 0;
							
							keys.each(function(item, index) {
								if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
								{
									count++;
								}
							}.bind(this));
							
							if (count === keys.length)
							{
								this.isOpen = true;
							}
							break;
					}
				}
				
				if ($defined(this.options.hideClass))
				{
					switch ($type(this.options.hideClass))
					{
						case 'string':
							if ((this.options.hideClass !== "") && (this.controlEl.hasClass(this.options.hideClass)))
							{
								this.isOpen = false;
							}
							break;
						case 'object':
							tempHash = $H(this.options.hideClass);
							keys = tempHash.getKeys();
							styles = $H(this.controlEl.getStyles(keys));
							count = 0;
							
							keys.each(function(item, index) {
								if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
								{
									count++;
								}
							}.bind(this));
							
							if (count === keys.length)
							{
								this.isOpen = false;
							}
							break;
					}
				}
			}
			
			// instantiate the fx engine, if fx will be used for opening and closing.
			if (this.options.useFx)
			{
				this.fx = new Fx.Morph(this.controlEl, {wait: this.options.fxWait, duration: this.options.fxDuration, transition: this.options.fxTransition});
				this.fx.addEvent('onComplete', this.transitionCompleteHandler.bind(this));
				this.fx.addEvent('onStart', this.transitionStartHandler.bind(this));
			}
			
		}
	},
	render: function(resize) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		this.fireEvent('onBeginRender', this);
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}
			
		this.fireEvent('onEndRender', this);
	},
	customRender: $empty,
	toggleShow: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			if (this.isOpen)
			{
				this.hide(stopEventFiring);
			}
			else
			{
				this.show(stopEventFiring);
			}
		}
	
	},
	show: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			// set the is open flag
			this.isOpen = true;
			
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxOpenStylePre) && (!this.inTransition))
				{
					this.controlEl.setStyles(this.options.fxOpenStylePre);
				}
				
				// Show with transitions effects
				this.inTransition = true;
				this.fx.start(this.options.fxOpenStyle);
			}
			else
			{
				if (!$defined(this.options.showClass))
				{
					// Show using the visibility and display styles
					this.controlEl.setStyles({ visibility: 'visible', display: 'block' });
				}
				else
				{
					if ($type(this.options.showClass) === 'object')
					{
						// Show using styles
						this.controlEl.setStyles(this.options.showClass);
					}
					else
					{
						// Show using class names
						if (this.options.showClass !== "")
						{
							this.controlEl.addClass(this.options.showClass);
						}
							
						if ($defined(this.options.hideClass) && ($type(this.options.hideClass) === 'string') && this.controlEl.hasClass(this.options.hideClass))
						{
							this.controlEl.removeClass(this.options.hideClass);
						}
					}
				}
			}
		}
		
		// fire the onshow event
		if (!stopEventFiring)
		{
			this.fireEvent('onshow', this);
			this.fireEvent('onShowStateChange', this);
		}
	},
	hide: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			// set the is open flag
			this.isOpen = false;
			
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxCloseStylePre))
				{
					this.controlEl.setStyles(this.options.fxCloseStylePre);
				}
					
				// Hide with transitions effects
				this.fx.start(this.options.fxCloseStyle);
			}
			else
			{
				if (!$defined(this.options.hideClass))
				{
					// Hide using the visibility and display styles
					this.controlEl.setStyles({ visibility: 'hidden', display: 'none' });
				}
				else
				{
					if ($type(this.options.hideClass) === 'object')
					{
						// Hide using styles
						this.controlEl.setStyles(this.options.hideClass);
					}
					else
					{
						// Hide using class names
						if (this.options.hideClass !== "")
						{
							this.controlEl.addClass(this.options.hideClass);
						}
							
						if ($defined(this.options.showClass) && ($type(this.options.showClass) === 'string') && this.controlEl.hasClass(this.options.showClass))
						{
							this.controlEl.removeClass(this.options.showClass);
						}
					}
				}
			}
		}
		
		// fire the onhide event
		if (!stopEventFiring)
		{
			this.fireEvent('onhide', this);
			this.fireEvent('onShowStateChange', this);
		}
	},
	showDelay: function(timeDelay, stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		if ($chk(timeDelay))
		{
//			this.timer = this.show(stopEventFiring).bind(this).delay(timeDelay);
			this.timer = this.show.bind(this).delay(timeDelay);
		}
	},
	hideDelay: function(timeDelay, stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		if ($chk(timeDelay))
		{
//			this.timer = this.hide(stopEventFiring).bind(this).delay(timeDelay);
			this.timer = this.hide.bind(this).delay(timeDelay);
		}
	},
	clearTimer: function() {
		$clear(this.timer);
	},
	toggleSelected: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			if (this.isSelected)
			{
				this.deselect(stopEventFiring);
			}
			else
			{
				this.select(stopEventFiring);
			}
		}
	
	},
	select: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			// set the is open flag
			this.isSelected = true;
			
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxSelectedStylePre) && (!this.inTransition))
				{
					this.controlEl.setStyles(this.options.fxSelectedStylePre);
				}
				
				// Show with transitions effects
				this.inTransition = true;
				this.fx.start(this.options.fxSelectedStyle);
			}
			else
			{
				if (!$defined(this.options.selectedClass))
				{
					// Show using the visibility and display styles
					this.controlEl.setStyles({ visibility: 'visible', display: 'block' });
				}
				else
				{
					if ($type(this.options.selectedClass) === 'object')
					{
						// Show using styles
						this.controlEl.setStyles(this.options.selectedClass);
					}
					else
					{
						// Show using class names
						if (this.options.selectedClass !== "")
						{
							this.controlEl.addClass(this.options.selectedClass);
						}
							
						if ($defined(this.options.deselectedClass) && ($type(this.options.deselectedClass) === 'string') && this.controlEl.hasClass(this.options.deselectedClass))
						{
							this.controlEl.removeClass(this.options.deselectedClass);
						}
					}
				}
			}
		}
		
		// fire the events
		if (!stopEventFiring)
		{
			this.fireEvent('onSelected', this);
			this.fireEvent('onSelectedStateChange', this);
		}
		
	},
	deselect: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			// set the is open flag
			this.isSelected = false;
			
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxDeselectedStylePre))
				{
					this.controlEl.setStyles(this.options.fxDeselectedStylePre);
				}
					
				// Hide with transitions effects
				this.fx.start(this.options.fxDeselectedStyle);
			}
			else
			{
				if (!$defined(this.options.deselectedClass))
				{
					// Hide using the visibility and display styles
					this.controlEl.setStyles({ visibility: 'hidden', display: 'none' });
				}
				else
				{
					if ($type(this.options.deselectedClass) === 'object')
					{
						// Hide using styles
						this.controlEl.setStyles(this.options.deselectedClass);
					}
					else
					{
						// Hide using class names
						if (this.options.deselectedClass !== "")
						{
							this.controlEl.addClass(this.options.deselectedClass);
						}
							
						if ($defined(this.options.selectedClass) && ($type(this.options.selectedClass) === 'string') && this.controlEl.hasClass(this.options.selectedClass))
						{
							this.controlEl.removeClass(this.options.selectedClass);
						}
					}
				}
			}
		}
		
		// fire the events
		if (!stopEventFiring)
		{
			this.fireEvent('onDeselected', this);
			this.fireEvent('onSelectedStateChange', this);
		}
	},
	toggleEnabled: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			if (this.isEnabled)
			{
				this.disable(stopEventFiring);
			}
			else
			{
				this.enable(stopEventFiring);
			}
		}
	
	},
	enable: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			// set the is open flag
			this.isEnabled = true;
			
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxEnabledStylePre) && (!this.inTransition))
				{
					this.controlEl.setStyles(this.options.fxEnabledStylePre);
				}
				
				// Show with transitions effects
				this.inTransition = true;
				this.fx.start(this.options.fxEnabledStyle);
			}
			else
			{
				if (!$defined(this.options.enabledClass))
				{
					// Show using the visibility and display styles
					this.controlEl.setStyles({ visibility: 'visible', display: 'block' });
				}
				else
				{
					if ($type(this.options.enabledClass) === 'object')
					{
						// Show using styles
						this.controlEl.setStyles(this.options.enabledClass);
					}
					else
					{
						// Show using class names
						if (this.options.enabledClass !== "")
						{
							this.controlEl.addClass(this.options.enabledClass);
						}
							
						if ($defined(this.options.disabledClass) && ($type(this.options.disabledClass) === 'string') && this.controlEl.hasClass(this.options.disabledClass))
						{
							this.controlEl.removeClass(this.options.disabledClass);
						}
					}
				}
			}
		}
		
		// fire the events
		if (!stopEventFiring)
		{
			this.fireEvent('onEnabled', this);
			this.fireEvent('onEnabledStateChange', this);
		}
	},
	disable: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the control
		if ($defined(this.controlEl))
		{
			// set the is open flag
			this.isEnabled = false;
			
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxDisabledStylePre))
				{
					this.controlEl.setStyles(this.options.fxDisabledStylePre);
				}
					
				// Hide with transitions effects
				this.fx.start(this.options.fxDisabledStyle);
			}
			else
			{
				if (!$defined(this.options.disabledClass))
				{
					// Hide using the visibility and display styles
					this.controlEl.setStyles({ visibility: 'hidden', display: 'none' });
				}
				else
				{
					if ($type(this.options.disabledClass) === 'object')
					{
						// Hide using styles
						this.controlEl.setStyles(this.options.disabledClass);
					}
					else
					{
						// Hide using class names
						if (this.options.disabledClass !== "")
						{
							this.controlEl.addClass(this.options.disabledClass);
						}
							
						if ($defined(this.options.enabledClass) && ($type(this.options.enabledClass) === 'string') && this.controlEl.hasClass(this.options.enabledClass))
						{
							this.controlEl.removeClass(this.options.enabledClass);
						}
					}
				}
			}
		}
		
		// fire the onhide event
		if (!stopEventFiring)
		{
			this.fireEvent('onDisabled', this);
			this.fireEvent('onEnabledStateChange', this);
		}
	},
	transitionStartHandler: function() {
		this.fireEvent('onTransitionStart', this);
	},
	transitionCompleteHandler: function() {
		// if a postfx style is available, set it
		if (this.isOpen)
		{
			if ($defined(this.options.fxOpenStylePost))
			{
				this.controlEl.setStyles(this.options.fxOpenStylePost);
			}
		}
		else
		{
			if ($defined(this.options.fxCloseStylePost))
			{
				this.controlEl.setStyles(this.options.fxCloseStylePost);
			}
		}
		
		if (this.isSelected)
		{
			if ($defined(this.options.fxSelectedStylePost))
			{
				this.controlEl.setStyles(this.options.fxSelectedStylePost);
			}
		}
		else
		{
			if ($defined(this.options.fxDeselectedStylePost))
			{
				this.controlEl.setStyles(this.options.fxDeselectedStylePost);
			}
		}
		
		if (this.isEnabled)
		{
			if ($defined(this.options.fxEnabledStylePost))
			{
				this.controlEl.setStyles(this.options.fxEnabledStylePost);
			}
		}
		else
		{
			if ($defined(this.options.fxDisabledStylePost))
			{
				this.controlEl.setStyles(this.options.fxDisabledStylePost);
			}
		}
		
		this.inTransition = false;
		
		this.fireEvent('onTransitionComplete', this);
	},
	getByUid: function(uid) {
		if (($defined(uid)))
		{
			// if I am the requested uid, return myself
			if ($defined(this.uid) && uid === this.uid)
			{
				return this;
			}
		}
		
		// no uid found, return null
		return null;
	},
	getByName: function(name) {
		if (($defined(name)))
		{
			// if I am the requested name, return myself
			if ($defined(this.options.name) && name === this.options.name)
			{
				return this;
			}
		}
		
		// no name found, return null
		return null;
	}
});

// *********************************************
// CHKCustomPopUp - 
// *********************************************
var CHKCustomPopUp = new Class ({
	// Events
	//	onShow
	//	onHide
	//	onTransitionStart
	//	onTransitionComplete
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		name: null,
		showEvent: 'mouseenter',
		hideEvent: 'mouseleave',
		enableTriggerToggle: false,
		enableTargetToggle: false,
		showTriggerClass: null,
		hideTriggerClass: null,
		showTargetClass: null,
		hideTargetClass: null,
		showDelay: null,
		hideDelay: null,
		alignment: null, // optional values are horiz_left, horiz_center, horiz_right, vert_top, vert_center, vert_bottom
		stopPropagation: true,
		preventDefault: false,
		enableKeypress: true,
		useFx: false,
		fxOpenStylePre: null,
		fxOpenStyle: null,
		fxOpenStylePost: null,
		fxCloseStylePre: null,
		fxCloseStyle: null,
		fxCloseStylePost: null,
		fxWait: false,
		fxDuration: 500,
		fxTransition: Fx.Transitions.Back.easeOut
	},
	triggerEl: null,
	targetEl: null,
	showEls: [],
	hideEls: [],
	triggerSize: null,
	popupSize: null,
	alignmentSet: false,
	isOpen: false,
	inTransition: false,
	timer: null,
	fx: null,
	uid: null,
	initialize: function(trigger, target, options) {
		var tempHash, keys, styles, count;
		
		this.triggerEl = $(trigger);
		this.targetEl = $(target);
		this.setOptions(options);
		this.setOverrides();
		tempHash = $H({});


		// get the sizes and store them for later.  NOTE: this does not work correctly when the element is hidden, needs work
		if($defined(this.triggerEl))
		{
			// bubble up the uid from the trigger element
			this.uid = this.triggerEl.uid;
			
			// if the name is not set, check for the name in the class
			if ((!$defined(this.options.name)) && (this.triggerEl.className.contains('js_name_')))
			{
				this.triggerEl.className.split(' ').each(function(item, index) {
					if (item.contains('js_name_')){
						this.options.name = item.replace('js_name_', '');
					}
				}.bind(this));
			}
			
			this.triggerSize = this.triggerEl.getSize();
			
			// if the size x and y comes back as 0, try to extract the size from the style
			if (this.triggerSize.x === 0 && this.triggerSize.y === 0)
			{
				this.triggerSize.x = this.triggerEl.getStyle('width').toInt();
				this.triggerSize.y = this.triggerEl.getStyle('height').toInt();
			}
			
			// isOpen detection
			if ($defined(this.options.showTriggerClass))
			{
				switch ($type(this.options.showTriggerClass))
				{
					case 'string':
						if ((this.options.showTriggerClass !== "") && (this.triggerEl.hasClass(this.options.showTriggerClass)))
						{
							this.isOpen = true;
						}
						break;
					case 'object':
						tempHash = $H(this.options.showTriggerClass);
						keys = tempHash.getKeys();
						styles = $H(this.triggerEl.getStyles(keys));
						count = 0;
						
						keys.each(function(item, index) {
							if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
							{
								count++;
							}
						}.bind(this));
						
						if (count === keys.length)
						{
							this.isOpen = true;
						}
						break;
				}
			}
			
			if ($defined(this.options.hideTriggerClass))
			{
				switch ($type(this.options.hideTriggerClass))
				{
					case 'string':
						if ((this.options.hideTriggerClass !== "") && (this.triggerEl.hasClass(this.options.hideTriggerClass)))
						{
							this.isOpen = false;
						}
						break;
					case 'object':
						tempHash = $H(this.options.hideTriggerClass);
						keys = tempHash.getKeys();
						styles = $H(this.triggerEl.getStyles(keys));
						count = 0;
						
						keys.each(function(item, index) {
							if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
							{
								count++;
							}
						}.bind(this));
						
						if (count === keys.length)
						{
							this.isOpen = false;
						}
						break;
				}
			}
			
		}
		
		// initialize the target element
		if($defined(this.targetEl))
		{
			// if there is no trigger, bubble up the uid from the target
			if (!$defined(this.uid))
			{
				this.uid = this.targetEl.uid;
			}
			
			// if the name is not set, check for the name in the class
			if ((!$defined(this.options.name)) && (this.targetEl.className.contains('js_name_')))
			{
				this.targetEl.className.split(' ').each(function(item, index) {
					if (item.contains('js_name_'))
					{
						this.options.name = item.replace('js_name_', '');
					}
				}.bind(this));
			}
				
			this.popupSize = this.targetEl.getSize();
			
			// if the size x and y comes back as 0, try to extract the size from the style
			if (this.popupSize.x === 0 && this.popupSize.y === 0)
			{
				this.popupSize.x = this.targetEl.getStyle('width').toInt();
				this.popupSize.y = this.targetEl.getStyle('height').toInt();
			}
			
			// isOpen detection
			if (($defined(this.options.useFx)) && (this.options.useFx))
			{
				if ($defined(this.options.fxOpenStyle))
				{
					if($type(this.options.fxOpenStyle) === 'object')
					{
						tempHash = $H(this.options.fxOpenStyle);
						keys = tempHash.getKeys();
						styles = $H(this.targetEl.getStyles(keys));
						count = 0;
						
						keys.each(function(item, index) {
							if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
							{
								count++;
							}
						}.bind(this));
						
						if (count === keys.length)
						{
							this.isOpen = true;
						}
					}
				}
				
				if ($defined(this.options.fxCloseStyle))
				{
					if($type(this.options.fxCloseStyle) === 'object')
					{
						tempHash = $H(this.options.fxCloseStyle);
						keys = tempHash.getKeys();
						styles = $H(this.targetEl.getStyles(keys));
						count = 0;
						
						keys.each(function(item, index) {
							if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
							{
								count++;
							}
						}.bind(this));
						
						if (count === keys.length)
						{
							this.isOpen = false;
						}
					}
				}
			}
			else
			{
				if ($defined(this.options.showTargetClass))
				{
					switch ($type(this.options.showTargetClass))
					{
						case 'string':
							if ((this.options.showTargetClass !== "") && (this.targetEl.hasClass(this.options.showTargetClass)))
							{
								this.isOpen = true;
							}
							break;
						case 'object':
							tempHash = $H(this.options.showTargetClass);
							keys = tempHash.getKeys();
							styles = $H(this.targetEl.getStyles(keys));
							count = 0;
							
							keys.each(function(item, index) {
								if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
								{
									count++;
								}
							}.bind(this));
							
							if (count === keys.length)
							{
								this.isOpen = true;
							}
							break;
					}
				}
				
				if ($defined(this.options.hideTargetClass))
				{
					switch ($type(this.options.hideTargetClass))
					{
						case 'string':
							if ((this.options.hideTargetClass !== "") && (this.targetEl.hasClass(this.options.hideTargetClass)))
							{
								this.isOpen = false;
							}
							break;
						case 'object':
							tempHash = $H(this.options.hideTargetClass);
							keys = tempHash.getKeys();
							styles = $H(this.targetEl.getStyles(keys));
							count = 0;
							
							keys.each(function(item, index) {
								if ((styles.has(item)) && (styles.get(item) === tempHash.get(item)))
								{
									count++;
								}
							}.bind(this));
							
							if (count === keys.length)
							{
								this.isOpen = false;
							}
							break;
					}
				}
			}
						
		}
		
		this.fx = new Fx.Morph(this.targetEl, {wait: this.options.fxWait, duration: this.options.fxDuration, transition: this.options.fxTransition});
		this.fx.addEvent('onComplete', this.transitionCompleteHandler.bind(this));
		this.fx.addEvent('onStart', this.transitionStartHandler.bind(this));
		
		
		// If the trigger is defined, wire up the event handlers.
		if ($defined(this.triggerEl))
		{
			// wire up the show events if they are defined
			if($defined(this.options.showEvent))
			{
				$splat(this.options.showEvent).each(function(event) {
					this.triggerEl.addEvent(event, this.showHandlerTrigger.bind(this));
				}.bind(this));
			}
			
			// wire up the hide events if they are defined
			if($defined(this.options.hideEvent))
			{
				$splat(this.options.hideEvent).each(function(event) {
					this.triggerEl.addEvent(event, this.hideHandlerTrigger.bind(this));
				}.bind(this));
			}
			
			if (this.options.enableKeypress)
			{
				this.triggerEl.addEvent('keypress', this.keypressHandlerTrigger.bind(this));
			}
		}
		
		// If the target is defined, wire up the event handlers.
		// do not wire up the events if the target and the trigger are the same, they will fight with each other.
		if ($defined(this.targetEl) && (this.targetEl !== this.triggerEl))
		{
			// wire up the show events if they are defined
			if($defined(this.options.showEvent))
			{
				$splat(this.options.showEvent).each(function(event) {
					this.targetEl.addEvent(event, this.showHandler.bind(this));
				}.bind(this));
			}
			
			// wire up the hide events if they are defined
			if($defined(this.options.hideEvent))
			{
				$splat(this.options.hideEvent).each(function(event) {
					this.targetEl.addEvent(event, this.hideHandler.bind(this));
				}.bind(this));
			}
			
			if (this.options.enableKeypress)
			{
				this.targetEl.addEvent('keypress', this.keypressHandler.bind(this));
			}
		}
	
		this.render(false); 
	},
	render: function(resize) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		this.fireEvent('onBeginRender', this);
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}
		
		this.fireEvent('onEndRender', this);
	},
	customRender: $empty,
	addShowElement: function(obj, showEvent) {
		if ($defined(obj))
		{
			// if not defined, default to click
			if (!$defined(showEvent))
			{
				showEvent = 'click';
			}
			
			// wire up the show event handlers, there can be multiple show events
			$splat(showEvent).each(function(event) {
				obj.addEvent(event, this.showHandlerTrigger.bind(this));
			}.bind(this));
			
			// add the obj to the showEls array
			this.showEls.push(obj);
		}
	},
	addHideElement: function(obj, hideEvent) {
		if ($defined(obj))
		{
			// if not defined, default to click
			if (!$defined(hideEvent))
			{
				hideEvent = 'click';
			}
			
			// wire up the hide event handlers, there can be multiple hide events
			$splat(hideEvent).each(function(event) {
				obj.addEvent(event, this.hideHandlerTrigger.bind(this));
			}.bind(this));

			// add the obj to the showEls array
			this.hideEls.push(obj);
		}
	},
	clearTimer: function() {
		$clear(this.timer);
	},
	show: function(stopEventFiring) {
		var triggerCoord, targetCoord, alignmentStyle, widthSign, widthSize, heightSign, heightSize;
			
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}


		// process the trigger
		if ($defined(this.triggerEl) && $defined(this.options.showTriggerClass)) 
		{
			if ($type(this.options.showTriggerClass) === 'object')
			{
				// Show using styles
				this.triggerEl.setStyles(this.options.showTriggerClass);
			}
			else
			{
				// Show using class names
				if(this.options.showTriggerClass !== "")
				{
					this.triggerEl.addClass(this.options.showTriggerClass);
				}
					
				if ($defined(this.options.hideTriggerClass) && ($type(this.options.hideTriggerClass) === 'string') && this.triggerEl.hasClass(this.options.hideTriggerClass))
				{
					this.triggerEl.removeClass(this.options.hideTriggerClass);
				}
			}
		}
		
		// set the is open flag
		this.isOpen = true;
		
		// process the target
		if ($defined(this.targetEl))
		{
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxOpenStylePre) && (!this.inTransition))
				{
					this.targetEl.setStyles(this.options.fxOpenStylePre);
				}
					
				// Show with transitions effects
				this.inTransition = true;
				this.fx.start(this.options.fxOpenStyle);
			}
			else
			{
				if (!$defined(this.options.showTargetClass))
				{
					// Show using the visibility and display styles
					this.targetEl.setStyles({ visibility: 'visible', display: 'block' });
				}
				else
				{
					if ($type(this.options.showTargetClass) === 'object')
					{
						//Show using styles
						this.targetEl.setStyles(this.options.showTargetClass);
					}
					else
					{
						// Show using class names
						if (this.options.showTargetClass !== "")
						{
							this.targetEl.addClass(this.options.showTargetClass);
						}
							
						if ($defined(this.options.hideTargetClass) && ($type(this.options.hideTargetClass) === 'string') && this.targetEl.hasClass(this.options.hideTargetClass))
						{
							this.targetEl.removeClass(this.options.hideTargetClass);
						}
					}
				}
			}
		}
		
		if (($defined(this.options.alignment)) && (this.alignmentSet === false))
		{
			if (($defined(this.triggerEl)) && ($defined(this.targetEl)))
			{
				triggerCoord = this.triggerEl.getCoordinates();
				targetCoord = this.targetEl.getCoordinates();
				widthSign = '';
				heightSign = '';

				
				// calculate the width size and sign
				if (targetCoord.width > triggerCoord.width)
				{
					widthSign = '-';
					widthSize = (targetCoord.width - triggerCoord.width);
				}
				else
				{
					widthSize = (triggerCoord.width - targetCoord.width);
				}
				
				// calculate the height size and sign
				if (targetCoord.height > triggerCoord.height)
				{
					heightSign = '-';
					heightSize = (targetCoord.height - triggerCoord.height);
				}
				else
				{
					heightSize = (triggerCoord.height - targetCoord.height);
				}
				
				 // optional values are horiz_left, horiz_center, horiz_right, vert_top, vert_center, vert_bottom
				switch(this.options.alignment)
				{
					case 'horiz_center':
						alignmentStyle = { left: widthSign + (widthSize/ 2 ) + 'px' };
						break;
					case 'horiz_right':
						alignmentStyle = { left: widthSign + widthSize + 'px' };
						break;
					case 'vert_top':
						alignmentStyle = { top: '0px' };
						break;
					case 'vert_center':
						alignmentStyle = { top: heightSign + (heightSize / 2) + 'px' };
						break;
					case 'vert_bottom':
						alignmentStyle = { top: heightSign + heightSize + 'px' };
						break;
					case 'horiz_left':
						alignmentStyle = { left: '0px' };
						break;
					case 'center_center':
						alignmentStyle = { left: widthSign + (widthSize/ 2 ) + 'px',  top: heightSign + (heightSize / 2) + 'px' };
						break;
					case 'center_left':
						alignmentStyle = { top: heightSign + (heightSize / 2) + 'px', left: '0px' };
						break;
					case 'center_right':
						alignmentStyle = { top: heightSign + (heightSize / 2) + 'px', left: widthSign + widthSize + 'px' };
						break;						
					case 'top_center':
						alignmentStyle = { top: '0px', left: widthSign + (widthSize/ 2 ) + 'px' };
						break;
					case 'top_left':
						alignmentStyle = { top: '0px', left: '0px' };
						break;
					case 'top_right':
						alignmentStyle = { top: '0px', left: widthSign + widthSize + 'px' };
						break;
					case 'bottom_center':
						alignmentStyle = { top: heightSign + heightSize + 'px', left: widthSign + (widthSize/ 2 ) + 'px' };
						break;
					case 'bottom_left':
						alignmentStyle = { top: heightSign + heightSize + 'px', left: '0px' };
						break;
					case 'bottom_right':
						alignmentStyle = { top: heightSign + heightSize + 'px', left: widthSign + widthSize + 'px' };
						break;
					default:
						alignmentStyle = { left: '0px' };
						break;
				}
				
				if ($defined(alignmentStyle))
				{
					this.alignmentSet = true;
					this.targetEl.setStyles(alignmentStyle);
				}
			}
		}
		
		// fire the onshow event
		if (!stopEventFiring)
		{
			this.fireEvent('onshow', this);
			this.fireEvent('onShowStateChange', this);
			this.fireEvent('onSelected', this);
		}
		
	},
	hide: function(stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		// process the trigger
		if ($defined(this.triggerEl) && $defined(this.options.hideTriggerClass)) 
		{
			if ($type(this.options.hideTriggerClass) === 'object')
			{
				// Hide using styles
				this.triggerEl.setStyles(this.options.hideTriggerClass);
			}
			else
			{
				// Hide using class names
				if (this.options.hideTriggerClass !== "")
				{
					this.triggerEl.addClass(this.options.hideTriggerClass);
				}
					
				if ($defined(this.options.showTriggerClass) && ($type(this.options.showTriggerClass) === 'string') && this.triggerEl.hasClass(this.options.showTriggerClass))
				{
					this.triggerEl.removeClass(this.options.showTriggerClass);
				}
			}
		}
		
		// set the is open flag
		this.isOpen = false;
		
		// process the target
		if ($defined(this.targetEl))
		{
			if (this.options.useFx)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.fxCloseStylePre) && (!this.inTransition))
				{
					this.targetEl.setStyles(this.options.fxCloseStylePre);
				}
					
				// Hide with transitions effects
				this.inTransition = true;
				this.fx.start(this.options.fxCloseStyle);
			}
			else
			{
				if (!$defined(this.options.hideTargetClass))
				{
					// Hide using the visibility and display styles
					this.targetEl.setStyles({ visibility: 'hidden', display: 'none' });
				}
				else
				{
					if ($type(this.options.hideTargetClass) === 'object')
					{
						// Hide using styles
						this.targetEl.setStyles(this.options.hideTargetClass);
					}
					else
					{
						// Hide using class names
						if (this.options.hideTargetClass !== "")
						{
							this.targetEl.addClass(this.options.hideTargetClass);
						}
							
						if ($defined(this.options.showTargetClass) && ($type(this.options.showTargetClass) === 'string') && this.targetEl.hasClass(this.options.showTargetClass))
						{
							this.targetEl.removeClass(this.options.showTargetClass);
						}
					}
				}
			}
		}
		
		// fire the onhide event
		if (!stopEventFiring)
		{
			this.fireEvent('onhide', this);
			this.fireEvent('onShowStateChange', this);
		}
	},
	showDelay: function(timeDelay, stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		if ($chk(timeDelay))
		{
//			this.timer = this.show(stopEventFiring).bind(this).delay(timeDelay);
			this.timer = this.show.bind(this).delay(timeDelay);
		}
	},
	hideDelay: function(timeDelay, stopEventFiring) {
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}

		if ($chk(timeDelay))
		{
//			this.timer = this.hide(stopEventFiring).bind(this).delay(timeDelay);
			this.timer = this.hide.bind(this).delay(timeDelay);
		}
	},
	showHandler: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true && $defined(event))
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true && $defined(event))
		{
			event.preventDefault();
		}
		
		// clear the timer delay to prevent it from firing
		$clear(this.timer);
		
		// only process if the popup is not open
		if (this.isOpen === false)
		{
			if ($defined(this.options.showDelay))
			{
				this.showDelay(this.options.showDelay);
			}
			else
			{
				this.show();
			}
		}
		else if (this.options.enableTargetToggle)
		{
			if ($defined(this.options.hideDelay))
			{
				this.hideDelay(this.options.hideDelay);
			}
			else
			{
				this.hide();
			}
		}
	},
	hideHandler: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true && $defined(event))
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true && $defined(event))
		{
			event.preventDefault();
		}
		// clear the timer delay to prevent it from firing
		$clear(this.timer);
		
		// only process if the popup is open
		if (this.isOpen === true)
		{
			
			if ($defined(this.options.hideDelay))
			{
				this.hideDelay(this.options.hideDelay);
			}
			else
			{
				this.hide();
			}
		}
	},
	showHandlerTrigger: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true && $defined(event))
		{
			 event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true && $defined(event))
		{
			event.preventDefault();
		}
		
		// clear the timer delay to prevent it from firing
		$clear(this.timer);
		
		// only process if the popup is not open
		if (this.isOpen === false)
		{
			// if a delay is defined, use it.
			if ($defined(this.options.showDelay))
			{
				this.showDelay(this.options.showDelay);
			}
			else
			{
				this.show();
			}
		}
		else if (this.options.enableTriggerToggle)
		{
			if ($defined(this.options.hideDelay))
			{
				this.hideDelay(this.options.hideDelay);
			}
			else
			{
				this.hide();
			}
		}
		
	},
	hideHandlerTrigger: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true && $defined(event))
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true && $defined(event))
		{
			event.preventDefault();
		}
		
		// clear the timer delay to prevent it from firing
		$clear(this.timer);
		
		// only process if the popup is open
		if (this.isOpen === true)
		{
			if ($defined(this.options.hideDelay))
			{
				this.hideDelay(this.options.hideDelay);
			}
			else
			{
				this.hide();
			}
		}
	},
	keypressHandlerTrigger: function(event) {
		this.keypressHandler(event);
		
		// if the enter key is pressed, set the focus to the target element
//		if (($defined(event.key)) && (event.key == 'enter') && ($defined(this.targetEl)))
//		{
//			this.targetEl.focus();
//		}
	},
	keypressHandler: function(event) {
		if ($defined(event) && $defined(event.key))
		{
			// stop event propagation if the flag is set
			if ((this.options.stopPropagation === true) && (event.key === 'enter' || event.key === 'esc'))
			{
				event.stopPropagation();
			}
			
			// prevent default behaviour if the flag is set
			if ((this.options.preventDefault === true) && (event.key === 'enter' || event.key === 'esc'))
			{
				event.preventDefault();
			}
			
			// clear the timer delay to prevent it from firing
			$clear(this.timer);
			
			switch(event.key)
			{
				case 'enter':
					// only process if the popup is not open
					if(this.isOpen === false)
					{
						this.show();
					}
					break;
				case 'esc':
					// only process if the popup is open
					if (this.isOpen === true)
					{
						this.hide();
					}
					break;
			}
		}
		
	},
	transitionStartHandler: function() {
		this.fireEvent('onTransitionStart', this);
	},
	transitionCompleteHandler: function() {
		// if a postfx style is available, set it
		if (this.isOpen)
		{
			if ($defined(this.options.fxOpenStylePost))
			{
				this.targetEl.setStyles(this.options.fxOpenStylePost);
			}
		}
		else
		{
			if ($defined(this.options.fxCloseStylePost))
			{
				this.targetEl.setStyles(this.options.fxCloseStylePost);
			}
		}
		this.inTransition = false;
		
		this.fireEvent('onTransitionComplete', this);
	}
});

// *********************************************
// CHKButton - 
// *********************************************
var CHKButton = new Class({
	Extends: CHKControl_Base,
	options: {
		selectEvent: 'click'
	},
	initialize: function(control, options) {
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			// wire up the selected events if they are defined
			if($defined(this.options.selectEvent))
			{
				$splat(this.options.selectEvent).each(function(event) {
					this.controlEl.addEvent(event, this.selectedHandler.bind(this));
				}.bind(this));
			}

			// wire up the keypress events
			this.controlEl.addEvent('keypress', this.keypressHandler.bind(this));
		}
		
		this.render(false);
	},
	selectFunc: $empty,
	keypressHandler: function(event) {
		// stop event propagation if the flag is set
		if (event.key === 'enter')
		{
			this.selectedHandler(event);
		}
	},
	selectedHandler: function(event) {
		// stop propogation of the event
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// if a function is defined, call it
		if (($defined(this.selectFunc)) && ($type(this.selectFunc) === 'function'))
		{
			this.selectFunc();
		}
		
		// fire off the onSelected Event
		this.fireEvent('onSelected', this);
	}
});

// *********************************************
// CHKInputForm - 
// When the trigger is fired, all input data found under control will be returned through the onSubmit event.
// *********************************************
var CHKInputForm = new Class ({
	// Events
	//	onSubmit
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		submitEvent: 'click'
	},
	controlEl: null,
	triggerEl: null,
	uid: null,
	initialize: function(control, trigger, options) {
		this.controlEl = $(control);
		this.triggerEl = $(trigger);
		this.setOptions(options);
		
		// bubble up the uid from the control element.
		if ($defined(this.controlEl))
		{
			this.uid = this.controlEl.uid;
		}
			
		// wire up the trigger event
		if ($defined(this.triggerEl))
		{
			if ($defined(this.options.submitEvent))
			{
				$splat(this.options.submitEvent).each(function(event) {
						this.triggerEl.addEvent(event, this.submitHandler.bind(this));
				}.bind(this));
			}
		}
		
		this.render(false);
	},
	render: function(resize) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		this.fireEvent('onBeginRender', this);
		this.fireEvent('onEndRender', this);
	},
	submitHandler: function() {
		this.fireEvent('onSubmit', this.get());
	},
	get: function() {
		// if the control is defined, return the input data
		if ($defined(this.controlEl))
		{
			return this.controlEl.getInputData();
		}
		
		// if the control is not defined return null
		return null;
	}
});

// *********************************************
// CHKBrowserResize - 
// *********************************************
var CHKBrowserResize = new Class({
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		delay: 300,
		widthThreshold: null,
		heightThreshold: null,
		defaultSize: null
	},
	currentSize: null,
	timer: null,
	initialize: function(options) {
		this.setOptions(options);
		this.setOverrides();
		
		// if the default size is defined, set the currentSize to the default.  Could impact the initialization.
		if ($defined(this.options.defaultSize))
		{
			this.currentSize = this.options.defaultSize;
		}
			
		window.addEvent('resize', this.resizeHandler.bind(this));
		
		this.render(false);
	},
	render: function(resize) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		this.fireEvent('onBeginRender', this);
		this.fireEvent('onEndRender', this);
	},
	getSize: function() {
		var winSize, isMin, size;
	
		winSize = window.getSize();
		isMin = false;

		
		// only check the widthThreshold if it is defined
		if (($defined(this.options.widthThreshold)) && (winSize.x <= this.options.widthThreshold))
		{
			isMin = true;
		}
		
		// only check the heightThreshold if it is defined
		if (($defined(this.options.heightThreshold)) && (winSize.y <= this.options.heightThreshold))
		{
			isMin = true;
		}
		
		// based on the min flag, assign the size to be broadcast		
		if (isMin)
		{
			size = 'min';
		}
		else
		{
			size = 'max';
		}
			
		// if there was an actual change from the current size, raise the event
		if (size !== this.currentSize)
		{
			this.currentSize = size;
			this.fireEvent('onResizeThreshold', this.currentSize);
		}
		
		this.fireEvent('onResize', size);
		
		return this.currentSize;
	},
	resizeHandler: function() {
		$clear(this.timer);
		if ($defined(this.options.delay))
		{
			this.timer = this.getSize.bind(this).delay(this.options.delay);
		}
		else
		{
			this.getSize();
		}
	}
});

// *********************************************
// CHKDrag - 
// *********************************************
var CHKDrag = new Class({
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		snap: 6, // the number of pixels that has to be moved before the event is fired (sensitivity).
		orientation: 'both', // values are 'both', 'vertical' and 'horizontal'
		stopPropagation: true,
		preventDefault: false
	},
	controlEl: null,
	dragEnabled: false,
	mousePosition: null,
	initialize: function(control, options) {
		this.controlEl = $(control);
		this.setOptions(options);
		this.setOverrides();
		
		if ($defined(this.controlEl))
		{
			// wire up the mouse down events
			this.controlEl.addEvent('mousedown', this.mouseDownHandler.bind(this));
			
			// wire up the mouse up events
			this.controlEl.addEvent('mouseup', this.mouseUpHandler.bind(this));
			this.controlEl.addEvent('mouseleave', this.mouseUpHandler.bind(this));
			
			// wire up the mouse move events
			this.controlEl.addEvent('mousemove', this.mouseDragHandler.bind(this));
		}
	},
	mouseDownHandler: function(event) {
		if (event.rightClick === false)
		{
			this.dragEnabled = true;
			
			// stop event propagation if the flag is set
/*			if (this.options.stopPropagation === true)
				event.stopPropagation();
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
				event.preventDefault();
*/			
		}
	},
	mouseUpHandler: function(event) {
		var enableflag = true;
		if ((event.type === 'mouseup') && (event.rightClick === true))
		{
			enableflag = false;
		}
		
		if (enableflag)
		{
			// stop event propagation if the flag is set
/*			if (this.options.stopPropagation === true)
				event.stopPropagation();
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
				event.preventDefault();
*/			
			this.dragEnabled = false;
			this.mousePosition = null; // clear the last mouse position
			this.fireEvent('onDragComplete', {now: event.page});
		}
	},
	mouseDragHandler: function(event) {
		var delta, showFlag, data;
		
		if (this.dragEnabled)
		{
			// stop event propagation if the flag is set
/*			if (this.options.stopPropagation === true)
				event.stopPropagation();
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
				event.preventDefault();
*/			
			delta = {x: null, y: null};
			if ($defined(this.mousePosition))
			{
				if (($defined(this.mousePosition.x)) && ($defined(event.page.x)))
				{
					delta.x = event.page.x - this.mousePosition.x;
				}
					
				if (($defined(this.mousePosition.y)) && ($defined(event.page.y)))
				{
					delta.y = event.page.y - this.mousePosition.y;
				}
			}
			
			showFlag = false;
			
			if ($defined(this.mousePosition))
			{
				if ($defined(this.options.snap))
				{
					if (($defined(this.options.orientation)) && ((this.options.orientation === 'both') || (this.options.orientation === 'vertical')))
					{
						if (($defined(delta.y)) && (Math.abs(delta.y) >= this.options.snap))
						{
							showFlag = true;
						}
					}
					
					if (($defined(this.options.orientation)) && ((this.options.orientation === 'both') || (this.options.orientation === 'horizontal')))
					{
						if (($defined(delta.x)) && (Math.abs(delta.x) >= this.options.snap))
						{
							showFlag = true;
						}
					}
					
				}
				else
				{
					showFlag = true;
				}
			}
			else
			{
				this.mousePosition = event.page;
			}
				
			if (showFlag)
			{
				data =  {start: this.mousePosition, now: event.page, delta: delta};
				this.mousePosition = event.page;
				
				this.fireEvent('onDrag', data);
			}
		}
	}});

// *********************************************
// CHKTabControl - 
// *********************************************
var CHKTabControl = new Class({
	Extends: CHKControl_Base,
	options: {
		tabClass: null,
		tabTarget: 'rel',
		tabTargetSelector: null,
		display: -1,
		keepHistory: false,
		loop: false,
		rotationDelay: 3000,
		rotationDirection: 'forward', // forward, backward
		tabSettings: {
			showEvent: 'click',
			hideEvent: null,
			showTriggerClass: null,
			hideTriggerClass: null,
			showTargetClass: null,
			hideTargetClass: null,
			showDelay: null,
			hideDelay: null
		}
	},
	tabs: [],
	history: [],
	totalTabs: 0,
	currentTab: null,
	stopHistory: false,
	stopEvent: false,
	rotationTimer: null,
	initialize: function(control, options) {
		var tabindex, target, els, popupOptions, temppopup;
		
		this.parent(control, options);
		
		tabindex = 0;
		
		if ($defined(this.controlEl))
		{
			
			if ($defined(this.options.tabClass))
			{
				this.controlEl.getElements(this.options.tabClass).each(function (item, index){
					// get the target
					target = null;
					switch (this.options.tabTarget)
					{
						case 'sibling':
							// if a Selector has been defined, use it, otherwise just get the next sibling element
							if ($defined(this.options.tabTargetSelector))
							{
								target = item.getNext(this.options.tabTargetSelector);
							}
							else
							{
								target = item.getNext();
							}
							break;
						case 'child':
							els = null;
							// if a Selector has been defined, use it, otherwise get the first child element
							if ($defined(this.options.tabTargetSelector))
							{
								els = item.getChildren(this.options.tabTargetSelector);
								if (els.length < 1)
								{
									els = item.getElements(this.options.tabTargetSelector);
								}
							}
							else
							{
								els = item.getChildren();
							}
							if (($defined(els)) && (els.length > 0))
							{
								target = els[0];
							}
							break;
						case 'rel':
							target = $(item.get('rel'));
							break;
						default:
							// get the target based on the value of the rel attribute
							target = $(item.get('rel'));
							break;
					}
					
					// added a name to the popup based on the tab index
					popupOptions = this.options.tabSettings;
					popupOptions.name = 'tab' + tabindex;
					
					// Create the popup
					temppopup = new CHKCustomPopUp(item, target, popupOptions);
					
					if (temppopup.isOpen === true)
					{
						this.currentTab = index;
					}
					
					// add it to the tab control and wire up the event handlers
					this.addTab(temppopup);
				}.bind(this));
			}
		}
		
		if (this.options.display >= 0)
		{
			this.showTab(this.options.display);
		}
			
		this.render(false);
	},
	isTabOpen: function() {
		var output = false;
		if ($defined(this.tabs) && this.tabs.length > 0)
		{
			this.tabs.each(function(item, index) { 
				if ($defined(item.isOpen) && item.isOpen)
				{
					output = true;
				}
			}.bind(this));
		}
		return output;
	},
	addTab: function(tab) {
		if ($defined(tab))
		{
			// wire up the event handlers
			tab.addEvent('onshow', this.tabShowHandler.bind(this));
			tab.addEvent('onhide', this.tabHideHandler.bind(this));
			tab.addEvent('onSelected', this.selectedHandler.bind(this));
			
			// add it to the collection
			this.tabs.push(tab);
			
			// increment the total variable
			this.totalTabs++;
		}
	},
	back: function() {
		if (($defined(this.history)) && (this.history.length > 0))
		{
			var lastIndex = this.history.getLast();
			this.history.splice((this.history.length -1), 1);
			
			this.stopHistory = true;
			this.showTab(lastIndex);
			this.stopHistory = false;
			
			return lastIndex;
		}
		return null;
	},
	next: function() {
		var showFlag, nextTab;

		showFlag = true;
		// get the next position
		if ($defined(this.currentTab))
		{
			nextTab = this.currentTab + 1;
		}
		else
		{
			nextTab = 0;
		}
		
		// check to see if you have reached the end.
		if (nextTab >= this.totalTabs)
		{
			if (this.options.loop)
			{
				nextTab = 0;
			}
			else
			{
				showFlag = false;
			}
		}
		
		if (showFlag)
		{
			this.showTab(nextTab, false);
			// return the tab number that was shown
			return nextTab;
		}
		
		// no tab was shown, so return null
		return null;
	},
	previous: function() {
		var showFlag, nextTab;

		showFlag = true;
		// get the next position
		if ($defined(this.currentTab))
		{
			nextTab = this.currentTab - 1;
		}
		else
		{
			nextTab = 0;
		}
		// check to see if you have reached the end.
		if (nextTab < 0)
		{
			if (this.options.loop)
			{
				nextTab = this.totalTabs - 1;
			}
			else
			{
				showFlag = false;
			}
		}
		
		if (showFlag)
		{
			this.showTab(nextTab, false);
			// return the tab number that was shown
			return nextTab;
		}
		
		// no tab was shown, so return null
		return null;
	},
	rotate: function() {
		var tabIndex;
		
		$clear(this.rotationTimer);
		
		switch(this.options.rotationDirection)
		{
			case 'backward':
				tabIndex = this.previous();
				break;
			case 'forward':
				tabIndex = this.next();
				break;
			default:
				tabIndex = this.next();
				break;
		}
		
		if ($defined(tabIndex))
		{
			if (($chk(this.options.rotationDelay)) && (this.options.rotationDelay > 0))
			{
				this.rotationTimer = this.rotate.bind(this).delay(this.options.rotationDelay);
			}
		}
	},
	rotateStart: function() {
		if (($chk(this.options.rotationDelay)) && (this.options.rotationDelay > 0))
		{
			this.rotationTimer = this.rotate.bind(this).delay(this.options.rotationDelay);
		}
	},
	rotateStop: function() {
		$clear(this.rotationTimer);
	},
	showTab: function(tabNumber, stopEventFiring) {
		// If the parameter is not defined, default it to true
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = true;
		}
		
		if (($chk(tabNumber)) && (tabNumber < this.tabs.length))
		{
			if (stopEventFiring)
			{
				this.stopEvent = true;
			}
			
			// Show the tab
			this.tabs[tabNumber].show();
			
			if (stopEventFiring)
			{
				this.stopEvent = false;
			}
		}
	},
	hideTab: function(tabNumber, stopEventFiring) {
		// If the parameter is not defined, default it to true
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = true;
		}
		
		if (tabNumber < this.tabs.length)
		{
			if (stopEventFiring)
			{
				this.stopEvent = true;
			}
			
			// Hide the tab
			this.tabs[tabNumber].hide();
			
			if (stopEventFiring)
			{
				this.stopEvent = false;
			}
		}
	},
	hideAllTabs: function(stopEventFiring) {
		// If the parameter is not defined, default it to true
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = true;
		}
		
		if (($defined(this.tabs)) && (this.tabs.length > 0))
		{
			if (stopEventFiring)
			{
				this.stopEvent = true;
			}
			
			// Hide all tabs
			this.tabs.each(function(item, index) {
				item.hide();
			}.bind(this));
			
			if (stopEventFiring)
			{
				this.stopEvent = false;
			}
		}
	},
	tabShowHandler: function(popup) {
		var temppopup = popup;
		
		// cycle through the tabs and close any that are open, other then the one being opened.
		this.tabs.each(function(item, index) {
			if (item.uid !== temppopup.uid)
			{
				item.hide();
			}
			else
			{
				// check to see if we are keeping a history
				if ((this.options.keepHistory) && (!this.stopHistory) && ($chk(this.currentTab)))
				{
					this.history.push(this.currentTab);
				}
				
				// set the index to the currently open tab
				this.currentTab = index;
				
				// fire the show tab event
				if (!this.stopEvent)
				{
					this.fireEvent('onShowTab', index);
				}
			}
		}.bind(this));
		
	},
	tabHideHandler: function(popup) {
		var numOpen = 0;
		// cycle through the tabs and if all of the popups are closed, fire off the event
		this.tabs.each(function(item, index) {
			if (item.isOpen)
			{
				numOpen++;
			}
			if ((item.uid === popup.uid) && (!this.stopEvent))
			{
				this.fireEvent('onHideTab', index);
			}
		}.bind(this));
		
		// the onHideAllTab event only get fired if all tabs are closed.
		if ((!this.stopEvent) && (numOpen === 0))
		{
			this.fireEvent('onHideAllTab', this);
		}
	},
	selectedHandler: function(obj) {
		if (($defined(obj)) && (!this.stopEvent))
		{
			this.fireEvent('onSelected', obj);
		}
	},
	getByUid: function(uid) {
		if (($defined(uid)) && ($defined(this.tabs)) && (this.tabs.length > 0))
		{
			// if I am the requested uid, return myself
			this.tabs.each(function(tab, index) {
				if ($defined(tab.uid) && uid === tab.uid)
				{
					return tab;
				}
			}.bind(this));			
		}
		
		// no uid found, return null
		return null;
	},	
	getByName: function(obj) {
		if (($defined(name)) && ($defined(this.tabs)) && (this.tabs.length > 0))
		{
			this.tabs.each(function(tab, index) {
				if ($defined(tab.options.name) && name === tab.options.name)
				{
					return tab;
				}
			}.bind(this));
		}

		// no name found, return null
		return null;
	}
});

// *********************************************
// CHKRepeater - 
// *********************************************
var CHKRepeater = new Class({
	Extends: CHKControl_Base,
	options: {
		value: null,
		frequency: 50,
		preventDefault: false
	},
	initialize: function(control, options) {
		this.parent(control, options);
		
		if($defined(this.controlEl))
		{
			
			this.controlEl.addEvent('mousedown', this.mousedownHandler.bind(this));
			this.controlEl.addEvent('mouseup', this.mouseupHandler.bind(this));
			this.controlEl.addEvent('mouseout', this.mouseoutHandler.bind(this));
		}
		
		this.render(false);
	},
	mousedownHandler: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		this.timer = (function(event){
			this.fireEvent('timerEvent', this.options.value);
		}.bind(this).periodical(this.options.frequency));
	},
	mouseupHandler: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// clear the time to prevent additionsl events from firing
		this.clearTimer();
	},
	mouseoutHandler: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// clear the time to prevent additionsl events from firing
		this.clearTimer();
	}
});

// *********************************************
// CHKSlider - 
// *********************************************
var CHKSlider = new Class({
	Extends: CHKControl_Base,
	options: {
		sliderName: 'page_slider',
		sliderHandleName: 'page_slider_handle',
		arrowLeftTopName: 'page_control_left',
		arrowRightBottomName: 'page_control_right',
		arrowTriggerFrequency: 50, 
		arrowScrollAmount: 5,
		wheelScrollAmount: 5,
		showClass: null,
		hideClass: null,
		orientation: 'horizontal',
		wheelLeftToRight: true,
		snap: false,
		steps: 100,
		wheel: true,
		leftToRight: true,
		initPosition: 0
	},
	sliderEl:null, 
	sliderHandleEl:null,
	sliderSize: null,
	sliderHandleSize: null,
	range: 0, // the actual size in pixels
	leftTopArrow:null, 
	rightBottomArrow:null, 
	stopEvent: false, 
	currentPosition: null, // the current step
	hasRendered: false,
	dragObj: null,
	isDragging: false,
	initialize: function(control, options) {
		var leftTopArrowEl, rightBottomArrowEl;
		
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			this.sliderEl = $(this.options.sliderName); 
			// If the slider is not defined, try getting it using the getElement from the controlEl.
			// This will try to get the element using selector functionality (class names, etc..)
			if ((!$defined(this.sliderEl)) && ($defined(this.options.sliderName)))
			{
				this.sliderEl = this.controlEl.getElement(this.options.sliderName);
			}
				
			this.sliderHandleEl = $(this.options.sliderHandleName); 
			// If the sliderHandle is not defined, try getting it using the getElement from the controlEl.
			// This will try to get the element using selector functionality (class names, etc..)
			if ((!$defined(this.sliderHandleEl)) && ($defined(this.options.sliderHandleName)))
			{
				this.sliderHandleEl = this.controlEl.getElement(this.options.sliderHandleName);
			}

			// Set up the arrow buttons
			leftTopArrowEl = $(this.options.arrowLeftTopName);
			// If the leftTopArrow is not defined, try getting it using the getElement from the controlEl.
			// This will try to get the element using selector functionality (class names, etc..)
			if ((!$defined(leftTopArrowEl)) && ($defined(this.options.arrowLeftTopName)))
			{
				leftTopArrowEl = this.controlEl.getElement(this.options.arrowLeftTopName);
			}
				
			rightBottomArrowEl = $(this.options.arrowRightBottomName);
			// If the rightBottomArrow is not defined, try getting it using the getElement from the controlEl.
			// This will try to get the element using selector functionality (class names, etc..)
			if ((!$defined(rightBottomArrowEl)) && ($defined(this.options.arrowRightBottomName)))
			{
				rightBottomArrowEl = this.controlEl.getElement(this.options.arrowRightBottomName);
			}
			
			// if the arrow control exists, create the repeater and wire up the event
			if($defined(leftTopArrowEl))
			{
				this.leftTopArrow  = new CHKRepeater(leftTopArrowEl, { frequency: this.options.arrowTriggerFrequency, value: -1 });
			}
			
			// if the arrow control exists, create the repeater and wire up the event
			if($defined(rightBottomArrowEl))
			{
				this.rightBottomArrow = new CHKRepeater(rightBottomArrowEl, { frequency: this.options.arrowTriggerFrequency, value: 1});
			}
				
			
			this.render();
			
			// preset the initial position
			// NOTE: do we need to fire the event on this?  currently it does not.
			this.setPosition(this.options.initPosition);
		
		}

	},
	render: function(resize) {
		var modifiers, limit, i;
		
		if (!$defined(resize))
		{
			resize = false;
		}
			
		this.fireEvent('onBeginRender', this);
		
		if (this.hasRendered)
		{
			this.detach();
		}
		
		if ($defined(this.sliderEl))
		{
			this.sliderSize = this.sliderEl.measure(function() { return { size: this.getSize(), coords: this.getCoordinates() }; });
			this.sliderHandleSize = this.sliderHandleEl.measure(function() { return { size: this.getSize(), coords: this.getCoordinates() }; });
			
			modifiers = { x: false, y: false };
			limit = {};
			i = false;
			switch (this.options.orientation)
			{
				case 'vertical':
					this.range = this.sliderSize.size.y - this.sliderHandleSize.size.y;
					limit.y = [0,this.range];
					modifiers.y = 'top';
					break;
				case 'horizontal':
					this.range = this.sliderSize.size.x - this.sliderHandleSize.size.x;
					limit.x = [0,this.range];
					if (this.options.leftToRight)
					{
						modifiers.x = 'left';
					}
					else
					{
						modifiers.x = 'right';
						i = true;
					}
					break;
				default:
					this.range = this.sliderSize.size.x - this.sliderHandleSize.size.x;
					limit.x = [0,this.range];
					if (this.options.leftToRight)
					{
						modifiers.x = 'left';
					}
					else
					{
						modifiers.x = 'right';
						i = true;
					}
					break;
			}
			
			
			this.dragObj = new Drag(this.sliderHandleEl, {
				snap: 0,
				limit: limit,
				modifiers: modifiers,
				invert: i,
				onDrag: this.draggedKnob.bind(this),
				onStart: this.draggedKnob.bind(this),
				onBeforeStart: function() { this.isDragging = true; }.bind(this),
				onCancel: function() { this.isDragging = true; }.bind(this),
				onComplete: function() { 
					this.isDragging = false; 
					this.draggedKnob();
				}.bind(this)
			});
		}
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}
		
		this.attach();
		
		// set the has rendered flag
		if (this.hasRendered === false)
		{
			this.hasRendered = true;
		}
		
		this.fireEvent('onEndRender', this);
	},
	attach: function() {
		if ($defined(this.sliderEl))
		{
			this.sliderEl.addEvent('mousedown', this.sliderClickHandler.bind(this));
		}
		
		if ($defined(this.leftTopArrow))
		{
			this.leftTopArrow.addEvent('timerEvent', this.arrowHandler.bind(this));
		}
			
		if ($defined(this.rightBottomArrow))
		{
			this.rightBottomArrow.addEvent('timerEvent', this.arrowHandler.bind(this));
		}
			
		if ($defined(this.controlEl))
		{
			// wire up the mouse wheel event to the window
			this.controlEl.addEvent('mousewheel', this.wheelHandler.bind(this));
			
			// wire up the key press event to the window
			this.controlEl.addEvent('keypress', this.keypressHandler.bind(this));
		}
		
//		if ($defined(this.dragObj))
//			this.dragObj.attach();
	},
	detach: function() {
		if ($defined(this.sliderEl))
		{
			this.sliderEl.removeEvent('mousedown', this.sliderClickHandler);
		}
		
		if ($defined(this.leftTopArrow))
		{
			this.leftTopArrow.removeEvent('timerEvent', this.arrowHandler);
		}
			
		if ($defined(this.rightBottomArrow))
		{
			this.rightBottomArrow.removeEvent('timerEvent', this.arrowHandler);
		}
			
		if ($defined(this.controlEl))
		{
			// wire up the mouse wheel event to the window
			this.controlEl.removeEvent('mousewheel', this.wheelHandler);
			
			// wire up the key press event to the window
			this.controlEl.removeEvent('keypress', this.keypressHandler);
		}
		
		if ($defined(this.dragObj))
		{
			this.dragObj.detach();
		}
	},
	setPosition: function(pos, stopEventFiring) {
		var per;
		
		// If the parameter is not defined, default it to true
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = true;
		}
			
		if (pos < 0){pos = 0;}
		if (pos > this.options.steps){ pos = this.options.steps;}
		
		// If snap is on, round the value to the whole number
		if (this.options.snap === true)
		{
			pos = pos.round();
		}
		
		// convert to percentage
		per = pos / this.options.steps;
		this.setPositionByPercentage(per, stopEventFiring);

	},
	setPositionByPercentage: function(per, stopEventFiring) {
		var handlePos, property, data;
		
		// If the parameter is not defined, default it to true
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = true;
		}
		
		// set the current step
		this.currentPosition = (per * this.options.steps).round();
		
		// get the position to set the handle to
		handlePos = per * this.range;
		if (handlePos < 0){handlePos = 0;}
		if (handlePos > this.range){ handlePos = this.range;}
		
		// get the correct property to set
		if (this.options.orientation === 'vertical')
		{
			property = 'top';
		}
		else
		{
			if (this.options.leftToRight)
			{
				property = 'left';
			}
			else
			{
				property = 'right';
			}
		}
		
		// Set the position
		this.sliderHandleEl.setStyle(property, handlePos);
		
		
		// raise the onChange event
		if (!stopEventFiring)
		{
			data = { position: this.currentPosition, percentage: per, obj: this };
			this.fireEvent('onChange', data);
			this.fireEvent('onComplete', data);
		}

	},
	draggedKnob: function() {
		var percentage, data;
		
		// get the percentage from the drag object based on actual pixels and range
		if (this.options.orientation === 'vertical')
		{
			percentage = this.dragObj.value.now.y / this.range;
		}
		else
		{
			percentage = this.dragObj.value.now.x / this.range;
		}
		
		// get the current step value based on percentage
		this.currentPosition = (percentage * this.options.steps).round();
		
		// if the snap is on and the dragging is completed, adjust the handle
		if ((this.isDragging === false) && (this.options.snap))
		{
			this.setPosition(this.currentPosition, true);
			percentage = this.currentPosition / this.options.steps;
		}
		
		// raise the onChange event
		data = { position: this.currentPosition, percentage: percentage, obj: this };
		this.fireEvent('onChange', data);
		
		if (this.isDragging === false)
		{
			this.fireEvent('onComplete', data);
		}
	},
	sliderClickHandler: function(event) {
		var per, pos, clickLoc;	
	
		// do not process if it is a right click or the handle is being dragged.
		if (event.rightClick){return;}
		if (this.isDragging || event.target === this.sliderHandleEl)
		{
			return;
		}

		// get the location of the click and calculate the percentage
		clickLoc = event.page;	
		
		// calculate the position
		if (this.options.orientation === 'vertical')
		{
			pos = clickLoc.y - this.sliderSize.coords.top - (this.sliderHandleSize.coords.height / 2);
		}
		else
		{
			pos = clickLoc.x - this.sliderSize.coords.left - (this.sliderHandleSize.coords.width / 2);
		}
		
		// make sure it is in range
		if (pos < 0){pos = 0;}
		if (pos > this.range){pos = this.range;}
		
		// if it is horizontal and right to left, flip the position
		if ((this.options.orientation !== 'vertical') && (this.options.leftToRight === false))
		{
			pos = this.range - pos;
		}
		
		// calculate the percentage
		per = pos / this.range;
		
		// If snap is on, round the value to the whole number
		if (this.options.snap === true)
		{
			per = ((per * this.options.steps).round()) / this.options.steps;
		}
		
		// set the position
		this.setPositionByPercentage(per, false);
	},
	arrowHandler: function(value) {
		// on right to left the value needs to be reversed.
		if (!this.options.leftToRight)
		{
			value = (-1 * value);
		}
		
		// set the position
		this.setPosition(this.currentPosition + (value * this.options.arrowScrollAmount), false);
	},
	getNewPosition: function(direction) {
		var newPosition, posPercentage;
		
		newPosition = this.currentPosition + (direction * this.options.wheelScrollAmount);
		
		// Ensure the new position is within range
		if (newPosition < 0){newPosition = 0;}
		if (newPosition > this.options.steps){newPosition = this.options.steps;}
		
		// If snap is on, round the value to the whole number
		if (this.options.snap === true)
		{
			newPosition = newPosition.round();
		}
		
		// get the percentage that the new position would be
		posPercentage = newPosition / this.options.steps;
		
		return { percentage: posPercentage, position: newPosition };
	},
	wheelHandler: function(event) {
		var value, data;
		
		if (this.options.wheel)
		{
			// stop event propagation if the flag is set
			if (this.options.stopPropagation === true)
			{
				event.stopPropagation();
			}
			
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
			{
				event.preventDefault();
			}
		
			// currently event.wheel returns a -1 on the down event and 1 on the up event.
			// we want the inverse of this for the coordinates.
			value = event.wheel;
			if (this.options.wheelLeftToRight)
			{
				value = (-1 * value);
			}
			
			// on right to left the value needs to be reversed.
			if (!this.options.leftToRight)
			{
				value = (-1 * value);
			}
			
			data = this.getNewPosition(value);
			data.obj = this;
			
			// set the position
			this.setPositionByPercentage(data.percentage, false);
		}
	},
	keypressHandler: function(event) {
		var value, data;
		
		value = 0;
		
		switch(event.key)
		{
			case 'up':
			case 'left':
				value = -1;
				break;
			case 'down':
			case 'right':
				value = 1;
				break;
		}
		
		if (value !== 0)
		{
			// stop event propagation if the flag is set
			if (this.options.stopPropagation === true)
			{
				event.stopPropagation();
			}
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
			{
				event.preventDefault();
			}
			
			// get the new position
			data = this.getNewPosition(value);
			data.obj = this;
			
			// set the position
			this.setPositionByPercentage(data.percentage, false);
		}
	}
});

// *********************************************
// CHKTabbedSlider - 
// *********************************************
var CHKTabbedSlider = new Class({
	Extends: CHKControl_Base,
	options: {
		tabControlName: null,
		tabSettings: {
		},
		sliderControlName: null,
		sliderSettings: {
			wheel: false, 
			snap: true, 
			arrowScrollAmount: 1,
			wheelScrollAmount: 1
		},
		wheelScrollAmount: 1,
		wheelLeftToRight: true
	},
	sliderObj: null,
	tabObj: null,
	initialize: function(control, options) {
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			// create the tab object
			this.tabObj = new CHKTabControl(this.options.tabControlName, this.options.tabSettings);
			
			// set the slider steps based on the number of tabs
			if ($defined(this.tabObj))
			{
				this.options.sliderSettings.steps = this.tabObj.totalTabs - 1;
			}
			
			// create the slider object
//			this.sliderObj = new CHKSlider_Base(this.options.sliderControlName, this.options.sliderSettings);
			this.sliderObj = new CHKSlider(this.options.sliderControlName, this.options.sliderSettings);
			
			// wire up the events on both the tab and slider objects to tie them together
			if ($defined(this.tabObj))
			{
				this.tabObj.addEvent('onShowTab',this.tabShowHandler.bind(this));
			}
			
			if ($defined(this.sliderObj))
			{
				this.sliderObj.addEvent('onComplete',this.sliderChangeHandler.bind(this));
			}
			
			// wire up the mouse wheel event to the entire control
			this.controlEl.addEvent('mousewheel', this.wheelHandler.bind(this));
			
			// wire up the keypress event to the entire control
			this.controlEl.addEvent('keypress', this.keypressHandler.bind(this));
		}
		
		this.render(false);
	},
	tabShowHandler: function(position) {
		this.sliderObj.setPosition(position);
		
		this.fireEvent('onChange', { position: position, percentage: (position/(this.tabObj.totalTabs - 1)), obj: this });
	},
	sliderChangeHandler: function(data) {
		this.tabObj.showTab(data.position);
		
		this.fireEvent('onChange', { position: data.position, percentage: data.percentage, obj: this });
	},
	show: function() { 
		if ($defined(this.sliderObj))
		{
			sliderObj.show();
		}
		
		if ($defined(this.tabObj))
		{
			tabObj.show();
		}
	}, 
	hide: function() { 
		if ($defined(this.sliderObj))
		{
			sliderObj.hide();
		}
		
		if ($defined(this.tabObj))
		{
			tabObj.hide();
		}
	},
	getNewPosition: function(direction) {
		var newPosition, posPercentage;
		
		newPosition = this.tabObj.currentTab + (direction * this.options.wheelScrollAmount);
		
		// Ensure the new position is within range
		if (newPosition < 0) 
		{
			newPosition = 0;
		}
		if (newPosition >= this.tabObj.totalTabs) 
		{
			newPosition = this.tabObj.totalTabs - 1;
		}
		
		// get the percentage that the new position would be
		posPercentage = newPosition / (this.tabObj.totalTabs - 1);
		
		return { percentage: posPercentage, position: newPosition };
	},
	wheelHandler: function(event) {
		var value, data;
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
	
		// currently event.wheel returns a -1 on the down event and 1 on the up event.
		// we want the inverse of this for the coordinates.
		value = event.wheel;
		if (this.options.wheelLeftToRight)
		{
			value = (-1 * value);
		}
		
		// get the new position
		data = this.getNewPosition(value);
		data.obj = this;
		
		this.sliderObj.setPosition(data.position, false);
	},
	keypressHandler: function(event) {
		var value, data;
		
		value = 0;
		
		switch(event.key)
		{
			case 'up':
			case 'left':
				value = -1;
				break;
			case 'down':
			case 'right':
				value = 1;
				break;
		}
		
		if (value !== 0)
		{
			// stop event propagation if the flag is set
			if (this.options.stopPropagation === true)
			{
				event.stopPropagation();
			}
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
			{
				event.preventDefault();
			}
			
			// get the new position
			data = this.getNewPosition(value);
			data.obj = this;
			
			// set the position
			this.setPosition(data.position, false);
		}
	}
});

// *********************************************
// CHKPanel - 
// *********************************************
var CHKPanel = new Class({
	Extends: CHKControl_Base,
	options: {
		panelPopupTarget: '.panel_popup',
		panelPopupShowEvent: 'mouseenter',
		panelPopupHideEvent: 'mouseleave',
		panelPopupShowDelay: 1000,
		panelPopupHideDelay: 500,
		currentClassName: null,
		maxWidth: 707,
		categoryName: '.category',
		categorySettings: {
			useFx: true,
			fxOpenStyle: { opacity: 1 },
			fxCloseStyle: { opacity: 0 }
		},
		menuName: '.above_title',
		menuSettings: {
			tabClass: '.preset',
			tabTarget: 'child',
			tabTargetSelector: 'div.preset_popup',
			tabSettings: {
				showEvent: 'mouseenter',
				hideEvent: 'mouseleave',
				showDelay: 150,
				hideDelay: 500
			}
		}
	},
	menuEl: null,
	menuTabs: [],
	menu: null,
	menuSize: null,
	categoryEl: null,
	category: null,
	panelPopup: null,
	isClosing: false,
	initialize: function(control, options) {
		var currentSize, target, els, panelPopupEl;
		
		this.parent(control, options);

		this.isOpen = false;
		
		if ($defined(this.controlEl))
		{
			if ($chk(this.options.maxWidth))
			{
				this.controlEl.setStyles({ 'max-width': this.options.maxWidth });
			}
				
			// wire up the category
			if ($defined(this.options.categoryName))
			{
				this.categoryEl = $(this.options.categoryName);
				if (!$defined(this.categoryEl))
				{
					this.categoryEl = this.controlEl.getElement(this.options.categoryName);	
				}

				if ($defined(this.categoryEl))
				{
					this.category = new CHKControl_Base(this.categoryEl, this.options.categorySettings);
				}
			}
			
			// wire up the menu
			if ($defined(this.options.menuName))
			{
				this.menuEl = $(this.options.menuName);
				if (!$defined(this.menuEl))
				{
					this.menuEl = this.controlEl.getElement(this.options.menuName);
				}
				
				if ($defined(this.menuEl))
				{
					// get the size of the menu
					currentSize = this.controlEl.getSize();
					this.controlEl.setStyles({ width: this.options.maxWidth + 'px'});
					this.menuSize = this.menuEl.measure(function() { return { size: this.getSize(), scrollsize: this.getScrollSize(), coordinates: this.getCoordinates() }; });
					this.controlEl.setStyles({ width: currentSize.x + 'px'});
					
					// create the tabControl with no predefined settings
					this.menu = new CHKTabControl(this.menuEl);
					this.menu.addEvent('onShowTab', this.tabShowHandler.bind(this));
					this.menu.addEvent('onHideAllTab', this.tabHideAllHandler.bind(this));
					this.menu.addEvent('onSelected', this.tabSelectedHandler.bind(this));
					
					// go through and get the triggers and targets for the tabControl
					this.menuEl.getElements(this.options.menuSettings.tabClass).each(function(item, index) {
						target = null;
						switch (this.options.menuSettings.tabTarget)
						{
							case 'sibling':
								// if a Selector has been defined, use it, otherwise just get the next sibling element
								if ($defined(this.options.menuSettings.tabTargetSelector))
								{
									target = item.getNext(this.options.menuSettings.tabTargetSelector);
								}
								else
								{
									target = item.getNext();
								}
								break;
							case 'child':

								// if a Selector has been defined, use it, otherwise get the first child element
								if ($defined(this.options.menuSettings.tabTargetSelector))
								{
									els = item.getChildren(this.options.menuSettings.tabTargetSelector);
									if (els.length < 1)
									{
										els = item.getElements(this.options.menuSettings.tabTargetSelector);
									}
								}
								else
								{
									els = item.getChildren();
								}
								if (($defined(els)) && (els.length > 0))
								{
									target = els[0];
								}
								break;
							case 'rel':
								target = $(item.get('rel'));
								break;
							default:
								// get the target based on the value of the rel attribute
								target = $(item.get('rel'));
								break;
						}
						
						// add only the targets to the tab control
						this.menu.addTab(new CHKCustomPopUp(null, target, this.options.menuSettings.tabSettings));
						
						// wire up the triggers to our own event handlers
						item.addEvent('click', function(event) { event.stopPropagation();	this.menuTriggerSelectorHandler(index); }.bind(this));
						item.addEvent(this.options.menuSettings.tabSettings.showEvent, function(event) { event.stopPropagation();	this.menuTriggerShowHandler(index); }.bind(this));
						item.addEvent(this.options.menuSettings.tabSettings.hideEvent, function(event) { event.stopPropagation();	this.menuTriggerHideHandler(index); }.bind(this));
						
						item.options = { name: null };
						if (item.className.contains('js_name_'))
						{
							item.className.split(' ').each(function(item2, index2) {
								if (item2.contains('js_name_'))
								{
									item.options.name = item2.replace('js_name_', '');
								}
							}.bind(this));
						}

						// add the trigger to the menuTabs collection
						this.menuTabs.push(item);
						
					}.bind(this));
					this.menu.hide();
				}
			}
			
			// wire up the panel popup
			panelPopupEl = this.controlEl.getElement(this.options.panelPopupTarget);
			if ($defined(panelPopupEl))
			{
				this.controlEl.addEvent(this.options.panelPopupShowEvent, this.panelPopupTriggerShowHandler.bind(this));
				this.controlEl.addEvent(this.options.panelPopupHideEvent, this.panelPopupTriggerHideHandler.bind(this));
				
				this.panelPopup = new CHKCustomPopUp(null, panelPopupEl, {
					showEvent: this.options.panelPopupShowEvent, 
					hideEvent: this.options.panelPopupHideEvent,
					showDelay: this.options.panelPopupShowDelay,
					hideDelay: this.options.panelPopupHideDelay
				}); 
				
				if ($defined(this.panelPopup))
				{
					this.panelPopup.hide();
					this.panelPopup.addEvent('onshow', this.panelPopupShowHandler.bind(this));
					this.panelPopup.addEvent('onhide', this.panelPopupHideHandler.bind(this));
				}
			}
		}
		
		this.render(false);
	},
	setCurrent: function(value) {
		this.panelPopup.hide();
		
		if (value)
		{
			if ($defined(this.controlEl))
			{
				this.controlEl.addClass(this.options.currentClassName);
			}
			
			if ($defined(this.menu))
			{
				this.menu.show();
			}
			
			if ($defined(this.category))
			{
				this.category.show();
			}
			
			this.isOpen = true;
		}
		else
		{
			if ($defined(this.controlEl))
			{
				this.controlEl.removeClass(this.options.currentClassName);
			}
				
			if ($defined(this.menu))
			{
				this.menu.hide();
			}
			
			this.isOpen = false;
		}
		
		//clear the isClosing flag.  used to control the panel popup during transitions
		this.isClosing = false;
	},
	isCurrent: function() {
		return this.controlEl.hasClass(this.options.currentClassName);
	},
	closeMenus: function() {
		if ($defined(this.menu))
		{
			this.menu.hideAllTabs();
		}
		
		// clear the panelpopup timer and close it if it is open
		this.panelPopup.clearTimer();
		if ($defined(this.panelPopup))
		{
			this.panelPopup.hide();
		}
		
		if ($defined(this.category))
		{
			this.category.hide();
		}
	},
	tabShowHandler: function() {
		this.controlEl.setStyles({ overflow: 'visible' });
	},
	tabHideAllHandler: function() {
		this.controlEl.setStyles({ overflow: 'hidden' });
	},
	tabSelectedHandler: function(obj) {
		if ($defined(obj))
		{
			this.fireEvent('onSelected', obj);
		}
	},
	panelPopupShowHandler: function(event) {
		// wired into the show event on the popup, controls the overflow
		this.controlEl.setStyles({ overflow: 'visible' });
	},
	panelPopupHideHandler: function(event) {
		// wired into the hide event on the popup, controls the overflow
		this.controlEl.setStyles({ overflow: 'hidden' });
	},
	panelPopupTriggerShowHandler: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// clear the timer delay to prevent it from firing
		this.panelPopup.clearTimer();
		
		// only process the panel popup if the panel and the popup is not open and it is not during a transition
		if ((this.isOpen === false) && (this.isClosing === false) && (this.panelPopup.isOpen === false))
		{
			// if a delay is defined, use it.
			if ($defined(this.options.panelPopupShowDelay))
			{
				this.panelPopup.showDelay(this.options.panelPopupShowDelay);
			}
			else
			{
				this.panelPopup.show();
			}
		}
	},
	panelPopupTriggerHideHandler: function(event) {
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// clear the timer delay to prevent it from firing
		this.panelPopup.clearTimer();
		
		// only process if the popup is open
		if (this.panelPopup.isOpen === true)
		{
			if ($defined(this.options.hideDelay))
			{
				this.panelPopup.hideDelay(this.options.panelPopupHideDelay);
			}
			else
			{
				this.panelPopup.hide();
			}
		}
	},
	menuTriggerShowHandler: function(index) {
		if (($chk(index)) && (index === this.menu.currentTab))
		{
			// clear the timer delay to prevent it from firing
			this.menu.tabs[index].clearTimer();
			
			// only process if the popup is not open
			if(this.menu.tabs[index].isOpen === false)
			{
				// if a delay is defined, use it.
				if ($defined(this.options.menuSettings.tabSettings.showDelay))
				{
					this.menu.tabs[index].showDelay(this.options.menuSettings.tabSettings.showDelay);
				}
				else
				{
					this.menu.tabs[index].show();
				}
			}
		}
	},
	menuTriggerHideHandler: function(index) {
		if ($chk(index))
		{
			// clear the timer delay to prevent it from firing
			this.menu.tabs[index].clearTimer();
			
			// only process if the popup is open
			if (this.menu.tabs[index].isOpen === true)
			{
				if ($defined(this.options.menuSettings.tabSettings.hideDelay))
				{
					this.menu.tabs[index].hideDelay(this.options.menuSettings.tabSettings.hideDelay);
				}
				else
				{
					this.menu.tabs[index].hide();
				}
			}
		}
	},
	menuTriggerSelectorHandler: function(index) {
		if ($chk(index))
		{
			this.menu.showTab(index, false);
			this.menuTabs.each(function(item, index) {
				if (item.hasClass('current'))
				{
					item.removeClass('current');
				}
			}.bind(this));
			this.menuTabs[index].addClass('current');
			if ($defined(this.menuTabs[index].options.name))
			{
				this.fireEvent('onSelected', this.menuTabs[index]);
			}
		}
	}
});

// *********************************************
// CHKToolBar - 
// *********************************************
var CHKToolBar = new Class({
	Extends: CHKControl_Base,
	options: {
		toolbarBuffer: 0,
		panelsName: '.panel',
		panelResizeEvent: 'click',
		panelPadding: 24,
		panelOpenStyle: null,
		panelCloseStyle: null,
		panelMenuOpenStyle: null,
		panelMenuCloseStyle: null,
		panelWidthSettings: [707, 707, 588, 436, 350],
		panelSettings: {
			maxWidth: 707,
			currentClassName: 'current',
			categoryName: '.category',
			categorySettings: {
				useFx: true,
				fxOpenStyle: { opacity: 1 },
				fxCloseStyle: { opacity: 0 }
			},
			menuName: '.above_title',
			menuSettings: {
				tabClass: '.preset',
				tabTarget: 'child',
				tabTargetSelector: 'div.preset_popup',
				tabSettings: {
					showEvent: 'mouseenter',
					hideEvent: 'mouseleave',
					showDelay: 150,
					hideDelay: 500
				}
			}
		},
		fxWait: false,
		fxDuration: 500
	},
	panelFx: null,
	panels: [],
	panelEls: [],
	menuEls: [],
	currentPanel: 0,
	panelMaxWidth: null,
	initialize: function(control, options) {
		var fxEls, obj, biggestPanel, newSize, dockSize, openStyle;
		
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			this.panelEls = this.controlEl.getElements(this.options.panelsName);
			this.menuEls = this.controlEl.getElements(this.options.panelSettings.menuName);
			fxEls = [];
			fxEls.combine(this.panelEls);
			fxEls.combine(this.menuEls);
			
			this.panelFx = new Fx.Elements(fxEls, {wait: this.options.fxWait, duration: this.options.fxDuration, transition: this.options.fxTransition});
			
			// set the panel maxwidth based on the number of panels found
			if (($defined(this.panelEls)) && (this.panelEls.length > 0) && this.panelEls.length <= this.options.panelWidthSettings.length)
			{
				this.panelMaxWidth = this.options.panelWidthSettings[(this.panelEls.length -1)];
			}
			else
			{
				this.panelMaxWidth = this.options.panelWidthSettings.getLast();
			}
			
			this.options.panelSettings.maxWidth = this.panelMaxWidth;
			
			// Create the panels and wire up the events
			if (($defined(this.panelEls)) && ($defined(this.options.panelResizeEvent)))
			{
				this.panelEls.each(function(panel, i) {
					$splat(this.options.panelResizeEvent).each(function(pevent) {
						panel.addEvent(pevent, function(event) { event.stopPropagation();	this.panelResizingHandler(i);	}.bind(this));
					}.bind(this));
					
					obj = new CHKPanel(panel, this.options.panelSettings);
					obj.addEvent('onSelected', this.panelSelectedHandler.bind(this));
					
					this.panels.push(obj);
				}.bind(this));
			}
			
			// set the controlEl width to the size of the panels with only one open
			biggestPanel = 0;
			this.panels.each(function(item, index) {
				newSize = item.menuSize.size.x + this.options.panelPadding;
				if (newSize > this.options.panelSettings.maxWidth)
				{
					newSize = this.options.panelSettings.maxWidth;
				}
				
				if (newSize > biggestPanel)
				{
					biggestPanel = newSize;
				}
			}.bind(this));
			
			dockSize = biggestPanel + this.options.toolbarBuffer + ( (this.panels.length - 1) * 120); // the extra panel is to compensate for the view controls area
			this.controlEl.setStyles({ width: dockSize });
			
			// Ensure the current panel is styled properly
			if (($defined(this.panels)) && (this.panels.length > 0) && ($defined(this.options.panelOpenStyle)))
			{
				this.panels.each(function(panel, i) {
					if (panel.isCurrent())
					{
						// get the correct size for the open panel
						newSize = (this.panels[i].menuSize.size.x + this.options.panelPadding);
						if (newSize > this.options.panelSettings.maxWidth)
						{
							newSize = this.options.panelSettings.maxWidth;
						}
						
						// style the open panel and set is as current
						openStyle = $merge(this.options.panelOpenStyle, { width: newSize + 'px' });
						panel.controlEl.setStyles(openStyle);
						panel.setCurrent(true);
					}
				}.bind(this));
			}
			
			this.panelFx.addEvent('onStart', this.panelResizingStart.bind(this));
			this.panelFx.addEvent('onComplete', this.panelResizingComplete.bind(this));
		}
		
		this.render(false);
	},
	setPanel: function(panelNum) {
		var o, newSize, openStyle;
		
		if (($chk(panelNum)) && (panelNum < this.panels.length))
		{
			// set the current panel number
			this.currentPanel = panelNum;
				
			if ((this.panels.length > 0) && (!this.panels[panelNum].isCurrent())) {
				o = {};
				
				// get the correct size for the open panel
				newSize = (this.panels[panelNum].menuSize.size.x + this.options.panelPadding);
				if (newSize > this.options.panelSettings.maxWidth)
				{
					newSize = this.options.panelSettings.maxWidth;
				}
					
				// set the transition fx's for the panels
				openStyle = $merge(this.options.panelOpenStyle, { width: newSize + 'px' });
				o[panelNum] = openStyle;
				this.panelEls.each(function(item, index) {
					if(panelNum !== index) {
						o[index] = this.options.panelCloseStyle;
					}
				}.bind(this));
				
				// set the transition fx's for the menus
				o[this.panels.length + panelNum] = this.options.panelMenuOpenStyle;
				this.panelEls.each(function(item, index) {
					if(panelNum !== index) {
						o[this.panels.length + index] = this.options.panelMenuCloseStyle;
					}
				}.bind(this));
				
				// close the menus on all panels
				this.panels.each(function(panel) {
					// set the isClosing flag for the transtion and close all menus and panel popup
					panel.isClosing = true;
					panel.closeMenus();
				});
				
				// start the transition effects
				this.panelFx.start(o);
			}
			
			this.fireEvent('onSelected', this.panels[panelNum]);
		}
	},
	panelResizingStart: function() {
	},
	panelResizingComplete: function() {
		this.panels.each(function(panel, index){
			if(index === this.currentPanel)
			{
				panel.setCurrent(true);
			}
			else
			{
				panel.setCurrent(false);
			}
		}.bind(this));
	},
	panelResizingHandler: function(panelNum) {
		this.setPanel(panelNum);
	},
	panelSelectedHandler: function(obj) {
		this.fireEvent('onSelected', obj);
	}

});

// *********************************************
// CHKMainNav - 
// *********************************************
var CHKMainNav = new Class({
	Extends: CHKControl_Base,
	options: {
		flyoutEnabled: true,
		sectionName: '.section',
		triggerName: 'main_nav_trigger',
		menuName: 'drop',
		menuTrayName: 'nav_mask_content',
		maskName: 'nav_mask',
		showEvent: 'mouseenter',
		hideEvent: 'mouseleave',
		leftToRight: true,
		closeDelay: 2000,
		pageLoadCloseDelay: 1000,
		tabName: '.main_nav',
		menuSettings: {
			showClass: {visibility: 'visible'},
			hideClass: {visibility: 'hidden'},
			tabClass: '.nav_dropdown', 
			tabTarget: 'sibling',
			tabSettings: {
				showEvent: 'mouseenter', 
				hideEvent: 'mouseleave', 
				showDelay: 150, 
				hideDelay: 150, 
				showTargetClass: {visibility: 'visible', display: 'block', opacity: 1, left: '0px', top: '56px'}, 
				hideTargetClass: {visibility: 'hidden', display: 'none', opacity: 0, left: '-1000em', top: '-1000em'}
			}
		},
		accordionTogglerName: '.accordToggler',
		accordionElementName: '.accordElement',
		accordionSettings: {
			display: -1,
			opacity: false, 
			alwaysHide: true,
			onActive: function(toggler, element){
				toggler.addClass('open');
				toggler.removeClass('closed');
				element.removeClass('gone');
			},
			onBackground: function(toggler, element){
				toggler.addClass('closed');
				toggler.removeClass('open');
			(function(){element.addClass('gone');}).delay(500);} 
		}
	},
	triggerEl: null,
	menuEl: null,
	sectionEl: null,
	menuTrayEl: null,
	maskEl: null,
	menuSize: null,
	triggerSize: null,
	sectionSize: 0,
	maskSize: null,
	tabObj: null,
	accords: [],
	fxMenu: null,
	fxTrigger: null,
	fxTarget: null,
	initialize: function(control, options) {
		var togglers, els, tempAccord;
		
		this.parent(control, options);
		
		// get the elements of the main navigation
		this.triggerEl = this.controlEl.getElement(this.options.triggerName);
		if (!$defined(this.triggerEl)){this.triggerEl = $(this.options.triggerName);}
		
		this.menuEl = this.controlEl.getElement(this.options.menuName);
		if (!$defined(this.menuEl)){this.menuEl = $(this.options.menuName);}
		
		this.menuTrayEl = this.controlEl.getElement(this.options.menuTrayName);
		if (!$defined(this.menuTrayEl)){this.menuTrayEl = $(this.options.menuTrayName);}
		
		this.sectionEl = this.controlEl.getElement(this.options.sectionName);
		if (!$defined(this.sectionEl)){this.sectionEl = $(this.options.sectionName);}
		
		//this.maskEl = this.controlEl.getElement(this.options.maskName);
		//if (!$defined(this.maskEl)) this.maskEl = $(this.options.maskName);
		this.maskEl = this.controlEl;
		
		// get the sizes of the mask, menu and section
		this.maskSize = this.maskEl.getCoordinates();
		this.menuSize = this.menuEl.getCoordinates();
		if ($defined(this.sectionEl))
		{
			this.sectionSize = this.sectionEl.getCoordinates();
		}

		
		// temporarily show the trigger so that we can get the size and then hide it again.
		this.triggerEl.setStyles({ display: 'block', visibility: 'visible' });
		this.triggerSize = this.triggerEl.getCoordinates();
		this.triggerEl.setStyles({ display: 'none', visibility: 'hidden' });
		
		// instantiate the transition object
		this.fxMenu = new Fx.Morph(this.menuTrayEl, {wait: this.options.fxWait, duration: this.options.fxDuration, transition: this.options.fxTransition});

		// Wire up the main navigation animation
		if (this.options.flyoutEnabled)
		{
			if ($defined(this.triggerEl))
			{
//				this.triggerEl.addEvent(this.options.showEvent, this.triggerShowHandler.bind(this));
				if ($defined(this.options.showEvent))
				{
					// wire up the events that were passed in via the options
					$splat(this.options.showEvent).each(function(event) {
						this.triggerEl.addEvent(event, this.triggerShowHandler.bind(this));
					}.bind(this));
					
					// wire up the keypress event handler
					this.triggerEl.addEvent('keypress', this.triggerKeypressHandler.bind(this));
				}
			}
			
			if ($defined(this.menuTrayEl))
			{
				if ($defined(this.options.showEvent))
				{
					$splat(this.options.showEvent).each(function(event) {
						this.menuTrayEl.addEvent(event, this.targetShowHandler.bind(this));
					}.bind(this));
				}
				
				if ($defined(this.options.hideEvent))
				{
					$splat(this.options.hideEvent).each(function(event) {
						this.menuTrayEl.addEvent(event, this.targetHideHandler.bind(this));
					}.bind(this));
				}
			}
		}
		
		// instantiate the tab control and wire up the events
		this.tabObj = new CHKTabControl(this.controlEl.getElement(this.options.tabName), this.options.menuSettings);
		this.tabObj.addEvent('onSelected', this.tabSelectedHandler.bind(this));
		this.tabObj.addEvent('onShowTab', this.tabShowHandler.bind(this));
		this.tabObj.addEvent('onHideAllTab', this.tabHideHandler.bind(this));
		
		// wire up the accordions in each tab
		this.tabObj.tabs.each(function(tab, index) {
			if ($defined(tab.targetEl))
			{
				togglers = [];
				els = tab.targetEl.getElements(this.options.accordionElementName);
				
				els.each(function(el, index) {
					togglers.push(el.getPrevious('a'));
				}.bind(this));
				
				tempAccord = new Accordion(tab.targetEl, togglers, els, this.options.accordionSettings);
				
				togglers.each(function(item2, index2) {
					item2.addEvent('keypress', function(event) {
						if (event.key === 'enter')
						{
							tempAccord.display(index2);
						}
					});
				}.bind(this));
				
				this.accords.push(tempAccord);
			}
		}.bind(this));
		
		// initiate the hide delay when the page is first loaded.
		if (this.options.flyoutEnabled)
		{
			this.hideDelay(this.options.pageLoadCloseDelay);
		}
		
		this.render(false);
	},
	show: function() {
		var me, stage1, stage2, stage3;

		me = this; 
		
		this.isOpen = true;
		
		// calculate the transition effects based on the leftToRight setting
		if (this.options.leftToRight)
		{ // left to right settings
			stage1 = { left: '-' + (this.triggerSize.width + this.menuSize.width) + 'px' };
			stage2 = { left: '-' + this.menuSize.width + 'px' };
			stage3 = { left: '0px' };
		}
		else
		{	// right to left settings - stage 2 is not need for a smooth transition
//			stage1 = { left: (this.maskSize.width - this.sectionSize.width) + 'px' };
//			stage3 = { left: (this.maskSize.width - (this.sectionSize.width + this.menuSize.width)) + 'px' };
			stage1 = { right: '-' + (this.triggerSize.width + this.menuSize.width) + 'px' };
			stage2 = { right: '-' + this.menuSize.width + 'px' };
			stage3 = { right: '0px' };
		}
		
		
		this.fxMenu.start(stage1).chain(function() {
				if ($defined(stage2))
				{
					this.menuTrayEl.setStyles(stage2);
				}
				
				this.triggerEl.setStyles({ display: 'none', visibility: 'hidden' });
				
				this.tabObj.show();
				if (($defined(this.tabObj)) && ($defined(this.tabObj.tabs)) && (this.tabObj.tabs.length > 0) && ($defined(this.tabObj.tabs[0].triggerEl)))
				{
					this.tabObj.tabs[0].triggerEl.focus();
				}
				
				this.fxMenu.start(stage3);
			}.bind(this)
		);
	},
	hide: function() {
		var me, stage1, stage2, stage3;
		
		me = this;
		
		this.isOpen = false;
		
		
		// calculate the transition effects based on the leftToRight setting
		if (this.options.leftToRight)
		{ // left to right settings
			stage1 = { left: ( '-' + this.menuSize.width + 'px') };
			stage2 = { left: ( '-' + (this.menuSize.width + this.triggerSize.width) + 'px') };
			stage3 = { left: '-' + this.menuSize.width + 'px' };
		}
		else
		{	// right to left settings - stage 2 is not need for a smooth transition
//			stage1 = { left: (this.maskSize.width - this.sectionSize.width) + 'px' };
//			stage3 = { left: (this.maskSize.width - (this.sectionSize.width + this.triggerSize.width)) + 'px' };
			stage1 = { right: ( '-' + this.menuSize.width + 'px') };
			stage2 = { right: ( '-' + (this.menuSize.width + this.triggerSize.width) + 'px') };
			stage3 = { right: '-' + this.menuSize.width + 'px' };
		}
		
		this.fxMenu.start(stage1).chain(function() {
				if ($defined(stage2))
				{
					this.menuTrayEl.setStyles(stage2);
				}
					
				this.triggerEl.setStyles({ display: 'block', visibility: 'visible' });
				this.tabObj.hide();
					
				this.fxMenu.start(stage3);
			}.bind(this)
		);
		
	},
	triggerKeypressHandler: function(event) {
		if (($defined(event.key)) && (event.key === 'enter'))
		{
			this.triggerShowHandler(event);
		}
	},
	triggerShowHandler: function(event) {
		if(this.isOpen){return;}
		
		this.show();
	},
	targetShowHandler: function(event) {
		if(this.isOpen)
		{
			$clear(this.timer);
		}
//		else
//			if (event.type == 'focus') this.show();
	},
	targetHideHandler: function(event) {
		if(!this.isOpen){return;}
		
		this.hideDelay(this.options.closeDelay);
	},
	tabSelectedHandler: function(obj) {
		if ($defined(obj))
		{
			this.fireEvent('onSelected', obj);
		}
	},
	tabShowHandler: function(event) {
		if (this.isOpen)
		{
			$clear(this.timer);
		}
			
		this.controlEl.setStyles({ overflow: 'visible' });
	},
	tabHideHandler: function(event) {
		this.addOverflow.delay(300, this);
		if (this.options.flyoutEnabled)
		{
			this.hideDelay(this.options.closeDelay);
		}
	}, 
	addOverflow: function() {
		this.controlEl.setStyles({ overflow: 'hidden' });
	}
});

// *********************************************
// CHKWindow_Base - Base class for all Windows.  Ensures that the basic object signature exists
//		and implements common code.
// *********************************************
var CHKWindow_Base = new Class({
	Extends: CHKControl_Base,
	options: {
		syncWindows: false
	},
	objs: [],
	lastPosPercentage: null,
	initialize: function(control, options) {
		this.parent(control, options);
	},
	render: function(resize, propogate) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		if (!$defined(propogate))
		{
			propogate = true;
		}
		
		this.fireEvent('onBeginRender', this);
		
		if ((propogate) && ($defined(this.objs)) && (this.objs.length > 0))
		{
			this.objs.each(function(item, index) { 
//				if ($defined(item.render))
				if (($defined(item.render))  && (item.isOpen))
				{
					item.render(resize); 
				}
			}.bind(this));
		}
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}
		
		this.fireEvent('onEndRender', this);
	},
	loadDataInit: function() {
		if (($defined(this.objs)) && (this.objs.length > 0))
		{
			this.objs.each(function(item, index) { 
				if (($defined(item)) && ($defined(item.loadDataInit)))
				{
					item.loadDataInit(); 
				}
			}.bind(this));
		}
	},
	loadData: function(data) {
	},
	addObj: function(obj) {
		if ($defined(this.objs))
		{
			this.objs.push(obj);
		}
	},
	setPosition: function(percentage) {
		if ($chk(percentage))
		{
			this.lastPosPercentage = percentage;
			
			if ((this.options.syncWindows) && ($defined(this.objs)) && (this.objs.length > 0))
			{
				this.objs.each(function(item, index) { 
					if ($defined(item.setPosition)) 
					{
						item.setPosition(percentage); 
					}
				}.bind(this));
			}
		}
	},
	getByUid: function(uid) {
		if (($defined(uid)))
		{
			// if I am the requested uid, return myself
			if ($defined(this.uid) && uid === this.uid)
			{
				return this;
			}
			
			// cycle through the objs collection and call their getByUid.
			//	if there is a response return it.
			if (($defined(this.objs)) && (this.objs.length > 0))
			{
				this.objs.each(function(item,i) {
					var results = item.getByUid(uid);
					
					if ($defined(results))
					{
						return results;
					}
				}.bind(this));
			}
		}
		
		// no uid found, return null
		return null;
	},
	getByName: function(name) {
		if (($defined(name)))
		{
			// if I am the requested name, return myself
			if ($defined(this.options.name) && name === this.options.name)
			{
				return this;
			}
			
			// cycle through the objs collection and call their getByUid.
			//	if there is a response return it.
			if (($defined(this.objs)) && (this.objs.length > 0))
			{
				this.objs.each(function(item,i) {
					var results = item.getByName(name);
					
					if ($defined(results))
					{
						return results;
					}
				}.bind(this));
			}
		}
		
		// no name found, return null
		return null;
	}

});

// *********************************************
// CHKWindow - 
//		The arrow keys are supported in the window, but you must put a tabindex on div tags so that
//		they can receive the focus.  tabindex of -1 means that it can receive focus only programatically,
//		tabindex of 0 means that it will fall in the natural flow of the document.
// *********************************************
var CHKWindow = new Class({
	Extends: CHKWindow_Base,
	options: {
		useScroll: true,
		content: null, // use this if the content window is other than the control element
		viewSize: null, // This is an override to the calculation done in the render function, this mimics getSize
		viewSizeEl: null,
		wheelScrollAmount: 25,
		orientation: 'vertical',
		wheelLeftToRight: true,
		enableDrag: true,
		dragSettings: {
			snap: 10,
			orientation: 'vertical'
		},
		fxOffset: {	x: 0, y: 0 },
		leftToRight: true
	},
	scrollFx: null,
	contentEl: null,
	windowSize: null,
	windowCoords: null,
	scrollRange: null,
	currentWindowPosition: 0,
	hasRendered: false, // used during the initialization and resizing of the scroll box to prevent extra padding being added.
	dragObj: null,
	initialize: function(control, options) {
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			if (this.options.useScroll)
			{
				this.scrollFx = new Fx.Scroll(this.controlEl, { wait: this.options.fxWait, duration: this.options.fxDuration, transition: this.options.fxTransition, offset: this.options.fxOffset });
			}
			else
			{
				this.scrollFx = new Fx.Morph(this.controlEl, {wait: this.options.fxWait, duration: this.options.fxDuration, transition: this.options.fxTransition});
			}

			if ($defined(this.options.content))
			{
				this.contentEl = $(this.options.content); 
				// If the contentEl is not defined, try getting it using the getElement from the controlEl.
				// This will try to get the element using selector functionality (class names, etc..)
				if (!$defined(this.contentEl))
				{
					this.contentEl = this.controlEl.getElement(this.options.content);
				}
			}
			else
			{
				this.contentEl = this.controlEl;
			}
				
			this.render(false);
			
			// wire up the scrollFx events
			this.scrollFx.addEvent('onComplete', this.scrollCompleteHandler.bind(this));
			
			// wire up the mouse whell event to the window
			this.controlEl.addEvent('mousewheel', this.wheelHandler.bind(this));
			
			// wire up the keypress event
			this.controlEl.addEvent('keypress', this.keypressHandler.bind(this));
			
			if (this.options.enableDrag)
			{
				this.dragObj = new CHKDrag(this.controlEl, this.options.dragSettings);
				this.dragObj.addEvent('onDrag', this.mouseDragHandler.bind(this));
			}
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
		}
	},
	render: function(resize, propogate) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		if (!$defined(propogate))
		{
			propogate = true;
		}
		
		this.fireEvent('onBeginRender', this);
		
		if ($defined(this.controlEl))
		{
			// get the scrollable size from the window.
			this.windowSize = this.controlEl.measure(function() { return { size: this.getSize(), scrollsize: this.getScrollSize() }; });
			
			// check for an override on the view size
			if ($defined(this.options.viewSizeEl))
			{
				this.options.viewSize = this.options.viewSizeEl.getSize();
			}
				
			if ($defined(this.options.viewSize))
			{
				this.windowSize.size = this.options.viewSize;
			}
				
			// calculate the scrollable range from the window size and the height/width of the window
			if (this.options.orientation === 'vertical')
			{
				this.scrollRange = this.windowSize.scrollsize.y - this.windowSize.size.y;
			}
			else
			{
				this.scrollRange = this.windowSize.scrollsize.x - this.windowSize.size.x; 
			}

			// set the flag for all future calls.
			this.hasRendered = true;
		}
		
		// sub Engine components
		if ((propogate) && ($defined(this.objs)) && (this.objs.length > 0))
		{
			this.objs.each(function(item, index) { 
//				if ($defined(item.render))
				if (($defined(item.render)) && (item.isOpen))
				{
					item.render(resize); 
				}
			}.bind(this));
		}
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}

		this.fireEvent('onEndRender', this);
	},
	loadData: function(data) {
		if (($defined(this.contentEl)) && ($defined(data)))
		{
			this.contentEl.set('html', data);
			this.render(false);
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
		}
	},
	setViewSize: function(obj) {
		if ($defined(obj))
		{
			this.options.viewSize = obj;
		}
	},
	scrollToElement: function(el) {
		var pos;
		
		if ($defined(el))
		{
			pos = this.controlEl.getPosition(el);
			if ($defined(pos))
			{
				if (($defined(this.options.orientation)) && (this.options.orientation === 'vertical'))
				{
					pos.x = 0;
				}
				else
				{
					pos.y = 0;
				}
					
				this.scrollTo(pos.x, pos.y);
				return pos;
			}
		}
		
		return null;
	},
	scrollTo: function(x, y) {
		var data, pos;
		
		if ($chk(x) && $chk(y))
		{
			data = { percentage: null, position: null };
			if ( $defined(this.scrollFx) && (this.options.useScroll))
			{
				//var scrollData = this.controlEl.getScroll;
				if (($defined(this.options.orientation)) && (this.options.orientation === 'vertical'))
				{
					data.percentage = (y / this.scrollRange);
					data.position = y ;
					x = 0;
				}
				else
				{
					data.percentage = (x / this.scrollRange);
					data.position = x;
					y = 0;
				}
			
				// start scrolling
				this.scrollFx.start(x, y);
			}
			else
			{
				
				if (($defined(this.options.orientation)) && (this.options.orientation === 'vertical'))
				{
					data.percentage = (Math.abs(y) / this.scrollRange);
					data.position = Math.abs(y);
					pos = { top: -data.position + 'px' };
				}
				else
				{
					data.percentage = (Math.abs(x) / this.scrollRange);
					data.position = Math.abs(x);
					if (this.options.leftToRight)
					{
						pos = { left: -data.position + 'px' };
					}
					else
					{
						pos = { right: -data.position + 'px' };
					}
				}
				
				// start scrolling
				this.scrollFx.start(pos);
			}
			
			data.obj = this;
			this.currentWindowPosition = data.position;
			this.lastPosPercentage = data.percentage;
			this.fireEvent('onPositionChange', data);
		}
	},
	setPosition: function(percentage) {
		var prop;
	
		if ($chk(percentage) && ($chk(this.scrollRange)) && (this.scrollRange > 0))
		{
			// Based on the percentage, calculate the new window position
			this.currentWindowPosition = percentage*this.scrollRange;
			
			// scroll the window based on the orientation
			if (this.options.orientation === 'vertical')
			{
				if (this.options.useScroll)
				{
					this.controlEl.scrollTo(0,this.currentWindowPosition);
				}
				else
				{
					this.controlEl.setStyle('top',-this.currentWindowPosition + 'px');
				}
			}
			else
			{
				if (this.options.useScroll)
				{
					this.controlEl.scrollTo(this.currentWindowPosition,0);
				}
				else
				{
					prop = (this.options.leftToRight) ? 'left': 'right';
					this.controlEl.setStyle(prop,-this.currentWindowPosition + 'px');
				}
			}
			this.parent(percentage);
		}
	},
	getPosition: function() {
		var pos, prop;
		
		if (this.options.useScroll)
		{
			if (this.options.orientation === 'vertical')
			{
				pos = this.controlEl.getScroll().y;
			}
			else
			{
				pos = this.controlEl.getScroll().x;
			}
		}
		else
		{
			if (this.options.orientation === 'vertical')
			{
				pos = Math.abs(this.controlEl.getStyle('top').toInt());
			}
			else
			{
				prop = (this.options.leftToRight) ? 'left': 'right';
				pos = Math.abs(this.controlEl.getStyle(prop).toInt());
			}
		}
		
		// if the currentWidnowPosition does not match what is being reported, set it.
		if (this.currentWindowPosition !== pos)
		{
			this.currentWindowPosition = pos;
		}
			
		return { percentage: (this.currentWindowPosition / this.scrollRange), position: pos };
	},
	getNewPosition: function(direction) {
		var newPosition, posPercentage;
		
		newPosition = this.currentWindowPosition + (direction * this.options.wheelScrollAmount);
		
		// Ensure the new position is within range
		if (newPosition < 0){newPosition = 0;}
		if (newPosition > this.scrollRange){newPosition = this.scrollRange;}
		
		// get the percentage that the new position would be
		posPercentage = newPosition / this.scrollRange;
		
		return { percentage: posPercentage, position: newPosition };
	},
	wheelHandler: function(event) {
		var value, data;
		
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// currently event.wheel returns a -1 on the down event and 1 on the up event.
		// we want the inverse of this for the coordinates.
		value = event.wheel;
		if (this.options.wheelLeftToRight)
		{
			value = (-1 * value);
		}
		
		data = this.getNewPosition(value);
		data.obj = this;
		
		// set the window to the new position
		this.setPosition(data.percentage);
		
		// based on the new percentage, fire off the mouse change event
		this.fireEvent('onPositionChange', data);
	},
	keypressHandler: function(event) {
		var value, data;
		
		value = 0;
		
		switch(event.key)
		{
			case 'up':
			case 'left':
				value = -1;
				break;
			case 'down':
			case 'right':
				value = 1;
				break;
		}
		
		if (value !== 0)
		{
			// stop event propagation if the flag is set
			if (this.options.stopPropagation === true)
			{
				event.stopPropagation();
			}
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
			{
				event.preventDefault();
			}
			
			// get the new position
			data = this.getNewPosition(value);
			data.obj = this;
			
			// set the position
			this.setPosition(data.percentage);
			
			// based on the new percentage, fire off the mouse change event
			this.fireEvent('onPositionChange', data);
		}
	},
	scrollCompleteHandler: function() {
		
//		var data = this.getPosition();
//		data.obj = this;
		// based on the new percentage, fire off the mouse change event
//		this.fireEvent('onPositionChange', data);
	},
	mouseDragHandler: function(event) {
		var value, data;
		
		value = 0;
		
		// check for deltas and only change the values if there was a change in the correct direction
		if (this.options.orientation === 'vertical')
		{
			if (($defined(event.delta)) && ($defined(event.delta.y)))
			{
				if (event.delta.y < 0)
				{
					value = -1;
				}
				if (event.delta.y > 0)
				{
					value = 1;
				}
			}
		}
		else
		{
			if (($defined(event.delta)) && ($defined(event.delta.x)))
			{
				if (event.delta.x < 0)
				{
					value = -1;
				}
				if (event.delta.x > 0)
				{
					value = 1;
				}
			}
		}
		
		if (value !== 0)
		{
			// get the new position
			data = this.getNewPosition(value);
			data.obj = this;
			
			// set the position
			this.setPosition(data.percentage);
			
			// based on the new percentage, fire off the mouse change event
			this.fireEvent('onPositionChange', data);
		}
		
		this.fireEvent('onDrag', event);
	}
});

// *********************************************
// CHKItemWindow - 
// *********************************************
var CHKItemWindow = new Class({
	Extends: CHKWindow_Base,
	options: {
		display: -1,
		itemClass: 'news_panel',
		itemSettings: {
			showEvent: null,
			hideEvent: null
		},
		wheelScrollAmount: 1,
		initPosition: null,
		wheelLeftToRight: true
	},
	items: [],
	totalItems: 0,
	currentItem: null,
	stopEvent: false,
	initialize: function(control, options) {
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			// add the items to the window
			this.controlEl.getElements(this.options.itemClass).each(function (item, index){
				this.addItem(new CHKCustomPopUp(null, item, this.options.itemSettings));
			}.bind(this));
			
			// wire up the mouse whell event to the window
			this.controlEl.addEvent('mousewheel', this.wheelHandler.bind(this));
			
			// wire up the keypress event to the window
			this.controlEl.addEvent('keypress', this.keypressHandler.bind(this));
			
			// set the initial open item
			if ($defined(this.options.initPosition))
			{
				this.showItem(this.options.initPosition, true);
			}
			
			this.render(false);
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
			
			if (this.options.display >= 0)
			{
				this.showItem(this.options.display);
			}
		}
	},
	loadData: function(data) {
		if (($defined(this.controlEl)) && ($defined(data)))
		{
			this.controlEl.set('html', data);
			this.render(false);
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
		}
	},
	setPosition: function(percentage) {
		var newPosition;
		
		if ($chk(percentage))
		{
			newPosition = (percentage * (this.totalItems - 1)).toInt();
			this.showItem(newPosition, true);
			
			this.parent(percentage);
		}
	},
	addItem: function(item) {
		if ($defined(item))
		{
			item.addEvent('onshow', this.showItemHandler.bind(this));
			
			this.items.push(item);
			this.totalItems++;
		}	
	},
	showItem: function(itemNumber, stopEventFiring) {
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}
		
		if (itemNumber < this.items.length)
		{
			if (stopEventFiring)
			{
				this.stopEvent = true;
			}
				
			this.items[itemNumber].show();
			
			if (stopEventFiring)
			{
				this.stopEvent = false;
			}
		}
	},
	showItemHandler: function(popup) {
		var temppopup, me;
		
		temppopup = popup;
		me = this;
		
		// cycle through the tabs and close any that are open, other then the one being opened.
		this.items.each(function(item, index) {
			if (item.uid !== temppopup.uid)
			{
				item.hide();
				if (!this.stopEvent)
				{
					me.fireEvent('onHideItem', index);
				}
			}
			else
			{
				me.currentItem = index;
				
				if (!this.stopEvent)
				{
					me.fireEvent('onShowItem', index);
				}
			}
		}.bind(this));
	},
	getNewPosition: function(direction) {
		var newPosition, posPercentage;
		
		newPosition = this.currentItem + (direction * this.options.wheelScrollAmount);
		
		// Ensure the new position is within range
		if (newPosition < 0) 
		{
			newPosition = 0;
		}
		if (newPosition >= this.totalItems) 
		{
			newPosition = this.totalItems - 1;
		}
		
		// get the percentage that the new position would be
		posPercentage = newPosition / (this.totalItems - 1);
		
		return { percentage: posPercentage, position: newPosition };
	},
	wheelHandler: function(event) {
		var value, data;
	
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// currently event.wheel returns a -1 on the down event and 1 on the up event.
		// we want the inverse of this for the coordinates.
		value = event.wheel;
		if (this.options.wheelLeftToRight)
		{
			value = (-1 * value);
		}
		
		// get the new position
		data = this.getNewPosition(value);
		data.obj = this;

		// set the window to the new position
		this.setPosition(data.percentage);
		
		// based on the new percentage, fire off the mouse change event
		this.fireEvent('onPositionChange', data);
	},
	keypressHandler: function(event) {
		var value, data;

		value = 0;
		
		switch(event.key)
		{
			case 'up':
			case 'left':
				value = -1;
				break;
			case 'down':
			case 'right':
				value = 1;
				break;
		}
		
		if (value !== 0)
		{
			// stop event propagation if the flag is set
			if (this.options.stopPropagation === true)
			{
				event.stopPropagation();
			}
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
			{
				event.preventDefault();
			}
			
			// get the new position
			data = this.getNewPosition(value);
			data.obj = this;
			
			// set the position
			this.setPosition(data.percentage);
			
			// based on the new percentage, fire off the mouse change event
			this.fireEvent('onPositionChange', data);
		}
	}
});

// *********************************************
// CHKAccordWindow - 
// *********************************************
var CHKAccordWindow = new Class({
	Extends: CHKWindow_Base,
	options: {
		display: -1,
		orientation: 'horizontal',
		itemOpenStylePre: { display: 'block', visibility: 'visible', opacity: 0 },
		itemOpenStyle: { opacity: 1 },
		itemOpenStylePost: null,
		itemCloseStylePre: null,
		itemCloseStyle: { opacity: 0 },
		itemCloseStylePost: { display: 'none', visibility: 'hidden' },
		itemPreviousStyle: null,
		itemNextStyle: null,
		itemClass: '.js_single_panel',
		wheelScrollAmount: 1,
		initPosition: null,
		wheelLeftToRight: true
	},
	itemEls: [],
	itemSize: [],
	totalItems: 0,
	currentItem: null,
	stopEvent: false,
	initialize: function(control, options) {
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			this.itemEls = this.controlEl.getElements(this.options.itemClass);
			this.totalItems = this.itemEls.length;
			
			if (($defined(this.itemEls)) && (this.itemEls.length > 0))
			{
				this.itemEls.each(function(item, index) {
					this.itemSize.push(item.measure(function() { return { size: this.getSize(), scrollsize: this.getScrollSize() }; }));
				}.bind(this));
			}
			
			this.panelFx = new Fx.Elements(this.itemEls, {wait: this.options.fxWait, duration: this.options.fxDuration, transition: this.options.fxTransition});
			
			this.panelFx.addEvent('onStart', this.itemResizingStart.bind(this));
			this.panelFx.addEvent('onComplete', this.itemResizingComplete.bind(this));
			
			// wire up the mouse whell event to the window
			this.controlEl.addEvent('mousewheel', this.wheelHandler.bind(this));
			
			// wire up the keypress event to the window
			this.controlEl.addEvent('keypress', this.keypressHandler.bind(this));
			
			// set the initial open item
			if ($defined(this.options.initPosition))
			{
				this.showItem(this.options.initPosition, true);
			}
			
			this.render(false);
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
			
			if (this.options.display >= 0)
			{
				this.showItem(this.options.display);
			}
		}
	},
	loadData: function(data) {
		if (($defined(this.controlEl)) && ($defined(data)))
		{
			this.controlEl.set('html', data);
			this.render(false);
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
		}
	},
	setPosition: function(percentage) {
		var newPosition;
		
		if ($chk(percentage))
		{
			newPosition = (percentage * (this.totalItems - 1)).toInt();
			this.showItem(newPosition, true);
			
			this.parent(percentage);
		}
	},
	showItem: function(itemNumber, stopEventFiring) {
		var o, previousItemNumber, nextItemNumber, openStyle, closeStyle;
		
		// If the parameter is not defined, default it to false
		if (!$defined(stopEventFiring))
		{
			stopEventFiring = false;
		}
		
		if ((itemNumber < this.itemEls.length) && (itemNumber >= 0))
		{
			if (stopEventFiring)
			{
				this.stopEvent = true;
			}
			
			if ((this.itemEls.length > 0) && (itemNumber !== this.currentItem)) {
				o = {};
				previousItemNumber = -1;
				nextItemNumber = -1;
				
				// find out the positions for the next and previous items if applicable.
				if (($defined(this.options.itemPreviousStyle)) && (itemNumber !== 0))
				{
					previousItemNumber = itemNumber - 1;
				}
				
				if (($defined(this.options.itemNextStyle)) && (itemNumber !== (this.itemEls.length - 1)))
				{
					nextItemNumber = itemNumber + 1;
				}
				
				// if a prefx style is available, set it
				if ($defined(this.options.itemOpenStylePre))
				{
					this.itemEls[itemNumber].setStyles(this.options.itemOpenStylePre);
				}
				
				// set the height/width open values based on orientation
				openStyle = this.options.itemOpenStyle;
				if (this.options.orientation === 'horizontal')
				{
					openStyle.width = this.itemSize[itemNumber].size.x + 'px';
				}
				else
				{
					openStyle.height = this.itemSize[itemNumber].size.y + 'px';
				}
					
				o[itemNumber] = openStyle;
				
				this.itemEls.each(function(other, j) {
					if(itemNumber !== j) {
						// if a prefx style is available, set it
						if ($defined(this.options.itemCloseStylePre))
						{
							this.itemEls[j].setStyles(this.options.itemCloseStylePre);
						}
						
						closeStyle = this.options.itemCloseStyle;
						if ((j === previousItemNumber) || (j === nextItemNumber))
						{
							if (j === previousItemNumber)
							{
								closeStyle = this.options.itemPreviousStyle;
							}
							
							if (j === nextItemNumber)
							{
								closeStyle = this.options.itemNextStyle;
							}
						}
						else
						{
							if (this.options.orientation === 'horizontal')
							{
								closeStyle.width = '0px';
							}
							else
							{
								closeStyle.height = '0px';
							}
						}
						o[j] = closeStyle;
					}
				}.bind(this));
				
				this.currentItem = itemNumber;
				this.panelFx.start(o);
			}
			
			if (stopEventFiring)
			{
				this.stopEvent = false;
			}
		}
	},
	itemResizingStart: function() {
		this.fireEvent('onTransitionStart', this);
	},
	itemResizingComplete: function() {
		var previousItemNumber, nextItemNumber;
		
		previousItemNumber = -1;
		nextItemNumber = -1;
		
		// find out the positions for the next and previous items if applicable.
		if (($defined(this.options.itemPreviousStyle)) && (this.currentItem !== 0))
		{
			previousItemNumber = this.currentItem - 1;
		}
		
		if (($defined(this.options.itemNextStyle)) && (this.currentItem !== (this.itemEls.length - 1)))
		{
			nextItemNumber = this.currentItem + 1;
		}
			
		this.itemEls.each(function(item, index) {
			if (index === this.currentItem)
			{
				// if a prefx style is available, set it
				if ($defined(this.options.itemOpenStylePost))
				{
					this.itemEls[index].setStyles(this.options.itemOpenStylePost);
				}
			}
			else
			{
				// if a prefx style is available, set it
				if (($defined(this.options.itemCloseStylePost)) && ((index !== previousItemNumber) && (index !== nextItemNumber)))
				{
					this.itemEls[index].setStyles(this.options.itemCloseStylePost);
				}
			}
		}.bind(this));
		this.fireEvent('onTransitionComplete', this);
	},
	getNewPosition: function(direction) {
		var newPosition, posPercentage;
		
		newPosition = this.currentItem + (direction * this.options.wheelScrollAmount);
		
		// Ensure the new position is within range
		if (newPosition < 0) 
		{
			newPosition = 0;
		}
		if (newPosition >= this.totalItems) 
		{
			newPosition = this.totalItems - 1;
		}
		
		// get the percentage that the new position would be
		posPercentage = newPosition / (this.totalItems - 1);
		
		return { percentage: posPercentage, position: newPosition };
	},
	wheelHandler: function(event) {
		var value, data;
		
		// stop event propagation if the flag is set
		if (this.options.stopPropagation === true)
		{
			event.stopPropagation();
		}
		
		// prevent default behaviour if the flag is set
		if (this.options.preventDefault === true)
		{
			event.preventDefault();
		}
		
		// currently event.wheel returns a -1 on the down event and 1 on the up event.
		// we want the inverse of this for the coordinates.
		value = event.wheel;
		if (this.options.wheelLeftToRight)
		{
			value = (-1 * value);
		}
		
		// get the new position
		data = this.getNewPosition(value);
		data.obj = this;
		
		// set the window to the new position
		this.setPosition(data.percentage);
		
		// based on the new percentage, fire off the mouse change event
		this.fireEvent('onPositionChange', data);
	},
	keypressHandler: function(event) {
		var value, data;

		value = 0;
		
		switch(event.key)
		{
			case 'up':
			case 'left':
				value = -1;
				break;
			case 'down':
			case 'right':
				value = 1;
				break;
		}
		
		if (value !== 0)
		{
			// stop event propagation if the flag is set
			if (this.options.stopPropagation === true)
			{
				event.stopPropagation();
			}
		
			// prevent default behaviour if the flag is set
			if (this.options.preventDefault === true)
			{
				event.preventDefault();
			}
			
			// get the new position
			data = this.getNewPosition(value);
			data.obj = this;
			
			// set the position
			this.setPosition(data.percentage);
			
			// based on the new percentage, fire off the mouse change event
			this.fireEvent('onPositionChange', data);
		}
	}
});

// *********************************************
// CHKScrollBox - 
// *********************************************
var CHKScrollBox = new Class({
	Extends: CHKWindow_Base,
	options: {
		wheelScrollAmount: 25,
		windowControlName: '.newsroom_article',
		sliderControlName: 'article_slider',
		sliderSettings: {
			orientation: 'vertical',
			sliderName: '.scrollbox_slider',
			sliderHandleName: '.handle',
			arrowTriggerFrequency: 50, 
			arrowScrollAmount: 25,
			arrowLeftTopName: null,
			arrowRightBottomName: null
		},
		windowSettings: {
			orientation: 'vertical'
		},
		leftToRight: true
	},
	sliderControlEl: null,
	windowEl: null,
	slider: null,
	window: null,
	windowSize: null,
	scrollRange: null,
	currentWindowPosition: 0,
	hasRendered: false, // used during the initialization and resizing of the scroll box to prevent extra padding being added.
	stopEvent: false,
	initialize: function(control, options) {
		this.parent(control, options);
		
		if ($defined(this.controlEl))
		{
			// grab the slider control
			this.sliderControlEl = $(this.options.sliderControlName);
			if ((!$defined(this.sliderControlEl)) && ($defined(this.options.sliderControlName)))
			{
				this.sliderControlEl = this.controlEl.getElement(this.options.sliderControlName);
			}
				
			// grab the window
			this.windowEl = $(this.options.windowControlName);
			if ((!$defined(this.windowEl)) && ($defined(this.options.windowControlName)))
			{
				this.windowEl = this.controlEl.getElement(this.options.windowControlName);
			}
			
			if (($defined(this.sliderControlEl)) && ($defined(this.windowEl)))
			{
				// calculate and set size specific positioning information 
				this.render(false);
				
				// wire up the slider events.
				if ($defined(this.slider))
				{
					this.slider.addEvent('onChange',this.sliderChangeHandler.bind(this));
				}
				
				// wire up the mouse whell event to the window
				if ($defined(this.window))
				{
					this.window.addEvent('onPositionChange', this.positionChangeHandler.bind(this));
				}
			}
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
		}
	},
	render: function(resize, propogate) {
		var tempsize, tempSliderPosition, tempSlider, data;
		if (!$defined(resize))
		{
			resize = false;
		}
		
		if (!$defined(propogate))
		{
			propogate = true;
		}
		
		this.fireEvent('onBeginRender', this);
		
		if (($defined(this.sliderControlEl)) && ($defined(this.windowEl)))
		{
			//Display the sliderbar to the right of the window
			tempsize = this.windowEl.measure(function() { return { size: this.getSize(), scrollSize: this.getScrollSize(), dimensions: this.getDimensions(), computedSize: this.getComputedSize() }; });
			if (this.options.sliderSettings.orientation === 'vertical')
			{
				if (this.options.leftToRight)
				{
					tempSliderPosition = {
						height: tempsize.size.y,
						position: 'absolute',
						top: '0px',
						left: tempsize.size.x+'px'
					};
				}
				else
				{
					tempSliderPosition = {
						height: tempsize.size.y,
						position: 'absolute',
						top: '0px',
						left: '0px'
					};
				}
			}
			else
			{
				tempSliderPosition = {
					width: tempsize.size.x+'px'
				};
			}
			
			// set the slider position
			if (this.options.sliderControlName === this.options.sliderSettings.sliderName)
			{
				this.sliderControlEl.setStyles(tempSliderPosition);
			}
			else
			{
				if (($defined(this.options.sliderSettings.sliderName)) && ($defined(this.sliderControlEl.getElement(this.options.sliderSettings.sliderName))))
				{
					tempSlider = this.sliderControlEl.getElement(this.options.sliderSettings.sliderName);
					tempSlider.setStyles(tempSliderPosition);
				}
			}
			
			// end moving the scroll bar
			
			// create the slider and window (only on init)
			if (!this.hasRendered)
			{
//				this.slider = new CHKSlider_Base(this.sliderControlEl, this.options.sliderSettings);
				this.slider = new CHKSlider(this.sliderControlEl, this.options.sliderSettings);
				this.window = new CHKWindow(this.windowEl, this.options.windowSettings);
			}
			else 
			{
				this.slider.render(resize);
				this.window.render(resize, propogate);
			}

			// if there is no scrollable range, hide the slider
			if (this.window.scrollRange <= 0)
			{
				this.slider.hide();
				this.setPosition(0);
			}
			else
			{
				this.slider.show();
			}
			
			if (resize)
			{
				data = this.window.getPosition();
				this.slider.setPositionByPercentage(data.percentage, false);
			}
			// set the flag for all future calls.
			this.hasRendered = true;
		}
		
		// sub engine components
		if ((propogate) && ($defined(this.objs)) && (this.objs.length > 0))
		{
			this.objs.each(function(item, index) { 
				if ($defined(item.render))
				{
					item.render(resize); 
				}
			}.bind(this));
		}
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}

		this.fireEvent('onEndRender', this);
	},
	loadData: function(data) {
		if (($defined(this.controlEl)) && ($defined(data)))
		{
			this.window.loadData(data);
			this.render(false);
			
			// call the initialization routine for everything in the window.
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
		}
	},
	loadDataInit: function() {
		
		// pass on initialization to the window object
		if (($defined(this.window)) && ($defined(this.window.loadDataInit)))
		{
			this.window.loadDataInit();
		}
		
		// pass on initialization to the slider object
		if (($defined(this.slider)) && ($defined(this.slider.loadDataInit)))
		{
			this.slider.loadDataInit();
		}
		
		this.parent();
	},
	show: function() {
		this.parent();
		
		if ($defined(this.window))
		{
			this.window.show();
		}
		if ($defined(this.slider))
		{
			this.slider.show();
		}
	},
	hide: function() {
		this.parent();
		
		if ($defined(this.window))
		{
			this.window.hide();
		}
		if ($defined(this.slider))
		{
			this.slider.hide();
		}
	},
	scrollToElement: function(el) {
		if ($defined(el) && ($defined(this.window)))
		{
			this.window.scrollToElement(el);
		}
	},
	scrollTo: function(x, y) {
		if ($chk(x) && $chk(y) && ($defined(this.window)))
		{
			this.window.scrollTo(x, y);
		}
	},
	setPosition: function(percentage, stopEventFiring) {
		if ($chk(percentage))
		{
			// If the parameter is not defined, default it to false
			if (!$defined(stopEventFiring))
			{
				stopEventFiring = false;
			}
			
			this.stopEvent = true;
			
			if ($defined(this.slider))
			{
				this.slider.setPositionByPercentage(percentage, stopEventFiring);
			}
			
			this.stopEvent = false;
			
			this.parent(percentage);
		}
	},
	sliderChangeHandler: function(data) {
		if (($defined(data)) && ($chk(data.percentage)))
		{
			this.window.setPosition(data.percentage);
			
			data.obj = this;
			
			if (!this.stopEvent)
			{
				this.fireEvent('onPositionChange', data);
			}
		}
	},
	positionChangeHandler: function(data) {
		if (($defined(data)) && ($chk(data.percentage)))
		{
			this.setPosition(data.percentage, true);
			
			data.obj = this;
			this.fireEvent('onPositionChange', data);
		}
	}
});

// *********************************************
//	CHKResultPane_Base - Base class for all result panes.  Ensures that the basic object signature exists
//		and implements common code.
//		Methods: loadData, setPosition, setView, setResults
// *********************************************
var CHKResultPane_Base = new Class({
	Extends: CHKControl_Base,
	loadDataInit: $empty,
	loadData: function(data) {
	},
	setPosition: function(percentage) {
	},
	setView: function(view) {
	},
	setResults: function(results) {
	}
});

// *********************************************
//	CHKResultPaneMulti - Takes multiple Window or ScrollBox objects and displays them one at a time.
//		Inherits: CHKResultPane_Base
//		Required object signature:
//			Events - onShow, onPositionChange
//			Properties - options.name, uid
//			Methods - setPosition, show, hide
//			Events: onPositionChange
//			Methods: addPane, setPosition, setView
// *********************************************
var CHKResultPaneMulti = new Class({
	Extends: CHKResultPane_Base,
	options: {
		syncWindows: true
	},
	windows: [],
	currentWindow: null,
	initialize: function(control, options) {
		this.parent(control, options);
		
		this.render(false);
			
		if ($defined(this.loadDataInit))
		{
			this.loadDataInit();
		}
	},
	render: function(resize) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		this.fireEvent('onBeginRender', this);
		
		// pass on the render command to all of the sub windows.
		if (($defined(this.windows)) && (this.windows.length > 0))
		{
			this.windows.each(function(item, index) 
			{ 
				if (item.isOpen)
				{
					item.render(resize);
				}
			}.bind(this));
		}
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}
		
		this.fireEvent('onEndRender', this);
	},
	loadData: function(data, view){
		if (($defined(data)) && (this.windows.length > 0))
		{
			this.windows.each(function(window, i) {
				if (($defined(window.options.name)) && (window.options.name === view))
				{
					window.loadData(data);
				}
				
//				if ($defined(window.loadData))
//					window.loadData(data, view);
			}.bind(this));
			this.render(false);
			
			if ($defined(this.loadDataInit))
			{
				this.loadDataInit();
			}
		}
	},
	loadDataInit: function() {
		if (($defined(this.windows)) && (this.windows.length > 0))
		{
			this.windows.each(function(item, index) { 
				if (($defined(item)) && ($defined(item.loadDataInit)))
				{
					item.loadDataInit(); 
				}
			}.bind(this));
		}
	},
	addPane: function(obj) {
		if ($defined(obj))
		{
			obj.addEvent('onshow', this.windowShowHandler.bind(this));
			obj.addEvent('onPositionChange', this.positionChangeHandler.bind(this));
			if (!$defined(this.currentWindow))
			{
				this.currentWindow = this.windows.length;
				obj.show();
			}
			else
			{
				obj.hide();
			}
			
			this.windows.push(obj);
		}
	},
	setPosition: function(percentage) {
		if (($defined(percentage)) && ($defined(this.windows)) && (this.windows.length > 0))
		{
			this.windows.each(function(window, i) {
				window.setPosition(percentage);
			}.bind(this));
		}
	},
	setView: function(view) {
		if (($defined(view)) && ($defined(this.windows)) && (this.windows.length > 0))
		{
			this.windows.each(function(window,i) {
				// if the window has the same name as view, show it
				if ($defined(window.options.name) && (window.options.name === view))
				{
					window.show();
					window.render();
				}
				
				// if the window has a setView function defined, call it
				if ($defined(window.setView))
				{
					window.setView(view);
				}
			}.bind(this));
		}
	},
	positionChangeHandler: function(event) {
		var newObj;
		
		if ($defined(event))
		{
			if (this.options.syncWindows)
			{
				this.windows.each(function(window, i) {
					if (window.uid !== event.obj.uid)
					{
						window.setPosition(event.percentage);
					}
				}.bind(this));
			}
			newObj = event;
			newObj.obj = this;
			this.fireEvent('onPositionChange', newObj);
		}
	},
	windowShowHandler: function(obj) {
		if (($defined(this.windows)) && (this.windows.length > 0))
		{
			this.windows.each(function(window, i) {
				if (window.uid !== obj.uid)
				{
					window.hide();
				}
				else
				{
					this.currentWindow = i;
				}
			}.bind(this));
		}
		
		if (this.isOpen === false){this.show();}
	},
	getByUid: function(uid) {
		if (($defined(uid)))
		{
			// if I am the requested uid, return myself
			if ($defined(this.uid) && uid === this.uid)
			{
				return this;
			}
			
			// cycle through the windows collection and call their getByUid.
			//	if there is a response return it.
			if (($defined(this.windows)) && (this.windows.length > 0))
			{
				this.windows.each(function(item,i) {
					var results = item.getByUid(uid);
					
					if ($defined(results))
					{
						return results;
					}
				}.bind(this));
			}
		}
		
		// no uid found, return null
		return null;
	},
	getByName: function(name) {
		if (($defined(name)))
		{
			// if I am the requested name, return myself
			if ($defined(this.options.name) && name === this.options.name)
			{
				return this;
			}
			
			// cycle through the windows collection and call their getByUid.
			//	if there is a response return it.
			if (($defined(this.windows)) && (this.windows.length > 0))
			{
				this.windows.each(function(item,i) {
					var results = item.getByName(name);
					
					if ($defined(results))
					{
						return results;
					}
				}.bind(this));
			}
		}
		
		// no name found, return null
		return null;
	}

});

// *********************************************
// CHKServicesHTML
// *********************************************
var CHKServicesHTML = new Class({
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		url: null,
		method: 'get'
	},
	request: null,
	initialize: function(options) {
		this.setOptions(options);
		this.setOverrides();
	},
	getData: function(options) {
		if ($defined(options))
		{
			this.request = new Request({
				url: $defined(options.url) ? options.url : this.options.url,
				method: $defined(options.method) ? options.method: this.options.method,
				onSuccess: this.requestOnSuccessHandler.bind(this),
				onFailure: this.requestOnFailureHandler.bind(this)
			});
		}
		else
		{
			this.request = new Request({
				url: this.options.url,
				method: this.options.method,
				onSuccess: this.requestOnSuccessHandler.bind(this),
				onFailure: this.requestOnFailureHandler.bind(this)
			});
		}
		if ($defined(this.request))
		{
			this.request.send();
		}
	},
	requestOnSuccessHandler: function(responseText, responseXML) {
		this.fireEvent('getDataSuccess', responseText);
	},
	requestOnFailureHandler: function(xhr) {
		this.fireEvent('getDataFail', xhr);
	}
});

// *********************************************
// CHKItemsManagerSimple - Simple Item Manager
// *********************************************
var CHKItemsManagerSimple = new Class({
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		name: null,
		pageSize: 6,
		keepPageOnSort: false,
		fxDuration: 0,
		fxTransition: Fx.Transitions.Sine.easeInOut,
		fxMode: 'horizontal'
	},
	currentPage: 0,
	totalCount: 0,
	totalActiveCount: 0,
	items: [], // List of id's (all items)
	activeSet: [], // list of id's that are currently active
	sortOrder: [], // list of id's in sorted order
	els: [], // list of elements
	itemElsIndex: null, // index positions into the els based on id's itemIndex
	itemHash: null, // index lookup.  Key is the id of the item and the value is the item object.  id: { id: id, isLoaded: true, controlEl: item, control: control }
	initialize: function(options) {
		this.setOptions(options);
		this.setOverrides();
		this.itemHash = $H({});
		this.itemElsIndex = $H({});
	},
	setPageSize: function(pSize) {
		if ($defined(pSize) && pSize !== '' && !isNaN(pSize))
		{
			this.options.pageSize = pSize;
		}
	},
	addItems: function(data, addToSort, addToActiveSet) {
		
		if (!$defined(addToSort))
		{
			addToSort = true;
		}
		
		if (!$defined(addToActiveSet))
		{
			addToActiveSet = true;
		}
		
		if ($defined(data))
		{
			data = $splat(data);
			// fire the BeginAddItems event
			this.fireEvent('onBeginAddItems', { data: data, obj: this });
			
			// cycle through the data to add to the manager
			data.each(function(item, index) {
				this.addItem(item, addToSort, addToActiveSet);
			}.bind(this));
			
			// fire the EndAddItems event
			this.fireEvent('onEndAddItems', { data: data, obj: this });
		}
	},
	addItem: function(item, addToSort, addToActiveSet) {
		var managedItem, tempViews, currentView;
		
		// set the default values for updateFxSort and addToActiveSet optional parameters
		if (!$defined(addToSort))
		{
			addToSort = true;
		}
		
		if (!$defined(addToActiveSet))
		{
			addToActiveSet = true;
		}
		
		// process the item if it is defined.
		if ($defined(item))
		{
			// fire the BeginAddItem event
			this.fireEvent('onBeginAddItem', { id: item.id, obj: this });
			
			// Check to see if the id already exists in the manager.
			if (this.itemHash.has(item.id))
			{
				// retrieve the item from the manager
				managedItem = this.itemHash.get(item.id);
				
				// merge the two together
				item = $merge(managedItem, item);
			}
			else // Add the item to the manager
			{
				// Item needs to be added
				this.items.push(item.id);
			}
			
			// add/update the item hash
			this.itemHash.set(item.id, item);
				
			// add the item els and update the indexes for sorting purposes
			if ($defined(item.controlEl))
			{
				if (this.itemElsIndex.has(item.id))
				{
					// existing item ???????????? do I need to do anything ???????
				}
				else
				{
					// new item added it to the els and index
					this.els.push(item.controlEl);
					this.itemElsIndex.set(item.id, this.els.length - 1);
				}
			}
			
			// If the flag is true and the sort order does not already contain the item, add the item to the sort order.
			if (addToSort && !this.sortOrder.contains(item.id))
			{
				this.sortOrder.push(item.id);
			}
			
			// If the flag is true and the active set does not already contain the item, add the item to the active set.
			if (addToActiveSet && !this.activeSet.contains(item.id))
			{
				this.activeSet.push(item.id);
			}
		
			// update the total count
			this.totalCount = this.itemHash.getLength();
			this.totalActiveCount = this.activeSet.length;

			// fire the EndAddItem event
			this.fireEvent('onEndAddItem', { item: item, obj: this });
				
		}
		
	},
	removeItems: function(data) {
		if ($defined(data))
		{
			data = $splat(data);
			// fire the BeginRemoveItems event
			this.fireEvent('onBeginRemoveItems', { data: data, obj: this });
			
			// cycle through the data to remove from the manager
			data.each(function(item, index) {
				this.removeItem(item);
			}.bind(this));
			
			// fire the EndRemoveItems event
			this.fireEvent('onEndRemoveItems', { data: data, obj: this });
		}
	},
	removeItem: function(id) {
		var viewNames, itemIndex;
		
		if ($defined(id) && id.length > 0)
		{
			// fire the BeginRemoveItem event
			this.fireEvent('onBeginRemoveItem', { id: id, obj: this });
			
			// remove from the els and index collections
			
			// get the index of the id into the els array
			itemIndex = this.itemElsIndex.get(id);
			
			// remove the el fromthe els array
			if ($defined(itemIndex))
			{
//				this.els.erase(this.els[itemIndex]);
				this.els.splice(itemIndex, 1);
			}
			
			// remove the id from the index
			this.itemElsIndex.erase(id);
			
			// update the index values
			if ($defined(itemIndex))
			{
				this.itemElsIndex.each(function(value, key) {
					if (value > itemIndex)
					{
						this.itemElsIndex.set(key, (value - 1));
					}
				}.bind(this));
			}
			
			// remove from active set
			this.activeSet.erase(id);
			
			// remove from sort order
			this.sortOrder.erase(id);
			
			// remove from items
			this.items.erase(id);
			
			// remove from item hash
			this.itemHash.erase(id);
		
			// update the total count
			this.totalCount = this.itemHash.getLength();
			this.totalActiveCount = this.activeSet.length;
			
			// fire the EndRemoveItem event
			this.fireEvent('onEndRemoveItem', { id: id, obj: this });
		}
	},
	activateItems: function(data, showPageFlag) {
		if ($defined(data))
		{
			// Set the default value for the showPageFlag if it is not defined
			if (!$defined(showPageFlag))
			{
				showPageFlag = true;
			}
			
			// fire the BeginActivateItems event
			this.fireEvent('onBeginActivateItems', this);
						
			// cycle through the data to actvate in the manager
			$splat(data).each(function(item, index) {
				this.activateItem(item, showPageFlag);
			}.bind(this));

			// fire the EndActivateItems event
			this.fireEvent('onEndActivateItems', this);
		}
	},
	activateItem: function(id, showPageFlag) {
		if ($defined(id) && id.length > 0)
		{
			// Set the default value for the showPageFlag if it is not defined
			if (!$defined(showPageFlag))
			{
				showPageFlag = true;
			}
			
			// fire the BeginActivateItem event
			this.fireEvent('onBeginActivateItem', this);
			
			// add to the active set the id of new item to activate
			if (!this.activeSet.contains(id))
			{
				this.activeSet.push(id);
			}
			
			if (showPageFlag)
			{
				// show the page to redisplay the active items
				this.showPage(this.currentPage);
			}
			// update the total count
			this.totalActiveCount = this.activeSet.length;
			
			// fire the EndActivateItem event
			this.fireEvent('onEndActivateItem', this);
		}
	},
	deactivateItems: function(data, showPageFlag) {
		if ($defined(data))
		{
			// Set the default value for the showPageFlag if it is not defined
			if (!$defined(showPageFlag))
			{
				showPageFlag = true;
			}
			
			// fire the BeginDeactivateItems event
			this.fireEvent('onBeginDeactivateItems', this);
						
			// cycle through the data to deactvate in the manager
			$splat(data).each(function(item, index) {
				this.deactivateItem(item, showPageFlag);
			}.bind(this));
			
			// fire the EndDeactivateItems event
			this.fireEvent('onEndDeactivateItems', this);
		}
	},
	deactivateItem: function(id, showPageFlag) {
		var itemData;
		
		if ($defined(id) && id.length > 0)
		{
			// Set the default value for the showPageFlag if it is not defined
			if (!$defined(showPageFlag))
			{
				showPageFlag = true;
			}
			
			// fire the BeginDeactivateItem event
			this.fireEvent('onBeginDeactivateItem', { id: id, obj: this });
		
			// remove the id from the activeSet
			this.activeSet.erase(id);
			
			// hide instance of the id
			itemData = this.itemHash.get(id);
			if ($defined(itemData) && $defined(itemData.control))
			{
				itemData.control.hide();
			}
			
			if (showPageFlag)
			{
				// show the page to redisplay the active items
				this.showPage(this.currentPage);
			}
			
			// update the total count
			this.totalActiveCount = this.activeSet.length;
			
			// fire the EndDeactivateItem event
			this.fireEvent('onEndDeactivateItem', { id: id, obj: this });
		}
	},
	applyActiveSet: function(data, showPageFlag) {
		var itemData;
		 
		if ($defined(data))
		{
			// Set the default value for the showPageFlag if it is not defined
			if (!$defined(showPageFlag))
			{
				showPageFlag = true;
			}
			
			// fire the BeginApplyActiveSet event
			this.fireEvent('onBeginApplyActiveSet', this);
			
			// active and deactivate all of the items in the manager based on the set given.
			// set the active set to the data given
			
			// make sure there are no duplicates in the array
			this.activeSet = [].combine($splat(data));
			
			// hide all of the elements
			this.items.each(function(item, index) {
				itemData = this.itemHash.get(item);
				if ($defined(itemData) && $defined(itemData.control))
				{
					itemData.control.hide();
				}
			}.bind(this));
			
			if (showPageFlag)
			{
				// show the page to redisplay the active items
				this.showPage(this.currentPage);
			}
			
			// update the total count
			this.totalActiveCount = this.activeSet.length;
			
			// fire the EndApplyActiveSet event
			this.fireEvent('onEndApplyActiveSet', this);
		}
	},
	applySort: function(data, showPageFlag) {
		var mySort, fxsort;
		
		// Set the default value for the showPageFlag if it is not defined
		if (!$defined(showPageFlag))
		{
			showPageFlag = true;
		}
		
		// takes the data and combines it with the existing sort order to derive a new sort order
		if ($defined(data))
		{
			if ($defined(this.sortOrder))
			{
				this.sortOrder = $splat(data).combine(this.sortOrder);
			}
			else
			{
				this.sortOrder = $splat(data);
			}
		}
		
		if ($defined(this.sortOrder))
		{
			// fire the BeginApplySort event
			this.fireEvent('onBeginApplySort', this);
			
			// apply the sort
			mySort = [];
			
			// cyle through the sort order and get the indexes into the internal els
			this.sortOrder.each(function(item2, index2) {
				mySort.push(this.itemElsIndex.get(item2));
			}.bind(this));
			
			// create the fxsort with the internal els
			fxsort = new Fx.Sort(this.els, {mode: this.options.fxMode, transition: this.options.fxTransition, duration: this.options.fxDuration});
			
			// sort and rearrange the DOM
			fxsort.sort(mySort).chain(fxsort.rearrangeDOM.bind(fxsort));
				
			if (showPageFlag)
			{
				// show the page after the sorting has been applied
				this.showPage( (this.options.keepPageOnSort) ? this.currentPage : 1);
			}
			
			// fire the EndApplySort event
			this.fireEvent('onEndApplySort', this);
		}
	},
	showPage: function(page) {
		var ids = [], saItems, itemData, pageStartIndex, pageStopIndex;
			
		if ($defined(page) && !isNaN(page))
		{
			// fire the BeginAddItems event
			this.fireEvent('onBeginShowPage', { page: page, obj: this });
			
			if (this.currentPage !== page)
			{
				this.currentPage = page;
			}
			
			saItems = this.sortOrder.filter(function(item, index){
				return this.activeSet.contains(item);
			}.bind(this));
				
			if (page > 0)
			{
				pageStopIndex = (page * this.options.pageSize) - 1;
				pageStartIndex = pageStopIndex - this.options.pageSize + 1;
				saItems.each(function(item, index) {
					itemData = this.itemHash.get(item);
					if ($defined(itemData))
					{
						
						
						if (index >= pageStartIndex && index <= pageStopIndex)
						{
							if (!itemData.isLoaded)
							{
								ids.push(item);
							}
							
							if ($defined(itemData.control))
							{
								itemData.control.show();
							}
							
						}
						else
						{
							
							if ($defined(itemData.control))
							{
								itemData.control.hide();
							}

						}
					}
				}.bind(this));
			}
			else
			{
				saItems.each(function(item, index) {
					itemData = this.itemHash.get(item);
					if ($defined(itemData))
					{
						if (!itemData.isLoaded)
						{
							ids.push(item);
						}
						
						if ($defined(itemData.control))
						{
							itemData.control.show();
						}
				
					}
				}.bind(this));
			}
			
			// fire the ItemsRequest event when there are items in the current page that are not loaded yet.
			this.fireEvent('onItemsRequest', ids);
			
			// fire the EndShowPage event
			this.fireEvent('onEndShowPage', { page: page, obj: this });
		
		}
	},
	hasItem: function(id) {
		if ($defined(this.itemHash))
		{
			return this.itemHash.has(id);
		}
		
		return false;
	},
	hasActiveItem: function(id) {
		if ($defined(this.activeSet))
		{
			return this.activeSet.contains(id);
		}
		
		return false;
	},
	getItemById: function(id) {
		if ($defined(id) && $defined(this.itemHash) && this.hasItem(id))
		{
			return this.itemHash.get(id);
		}
		
		return null;
	},
	getItemsByPage: function(page) {
		var ids = [], saItems, itemData, pageStartIndex, pageStopIndex;
		if (!$defined(page) || isNaN(page))
		{
			page = this.currentPage;
		}
		
		saItems = this.sortOrder.filter(function(item, index){
			return this.activeSet.contains(item);
		}.bind(this));		
		pageStopIndex = (page * this.options.pageSize) - 1;
		pageStartIndex = pageStopIndex - this.options.pageSize + 1;

		saItems.each(function(item, index) {
			itemData = this.itemHash.get(item);
			if ($defined(itemData))
			{
				if (index >= pageStartIndex && index <= pageStopIndex)
				{
					ids.push(item);
				}
			}
		}.bind(this));
		return ids;
	},	
	getPageIndex: function(pageNum) {
		var pageStartIndex, pageStopIndex;
		
		if (!$defined(pageNum))
		{
			pageNum = this.currentPage;
		}
		
		if ($defined(pageNum))
		{
			if (pageNum > 0)
			{
				pageStopIndex = (pageNum * this.options.pageSize) - 1;
				pageStartIndex = pageStopIndex - this.options.pageSize + 1;
				
				// ensure that stop index does not go out of bounds of the current active set.
				if (pageStopIndex >= this.totalActiveCount)
				{
					pageStopIndex = this.totalActiveCount - 1;
				}
			}
			else
			{
				pageStartIndex = 0;
				pageStopIndex = this.totalActiveCount - 1;
			}
			
		}
		
		return { start: pageStartIndex, stop: pageStopIndex};
	},
	getTotalPages: function() {
		var totalPages = 0;
		
		if ($defined(this.totalActiveCount) && this.totalActiveCount > 0 && $defined(this.options.pageSize) && this.options.pageSize > 0)
		{
			totalPages = Math.abs(Math.ceil(this.totalActiveCount / this.options.pageSize));
		}
		
		return totalPages;
	},
	filterItemsBy: function(filterName, filterValue) {
		// This method will apply and active set based on a property (filterName) and it's value (filterValue)
		// found in the item.
		// NOTE: The filterName supports a path into the item via dot notation. ('person.address.city')
		var oids = [], tempHash;
		
		if ($defined(this.itemHash) && $defined(filterName) && filterName.length > 0 && $defined(filterValue))
		{
			// Loop through every item in the item Hash
			this.itemHash.each(function(value, key){
				// Make sure the value object is a Hash
				tempHash = $H(value);
				
				// get the value using the getFromPath method in the hash
				var obj = tempHash.getFromPath(filterName);
				
				// if the property is defined and it equals the filterValue, add the oid to the list
				if ($defined(obj) && obj === filterValue)
				{
					oids.push(key);
				}
			}.bind(this));

			// Make sure oids is defined and there is at least one item in it.
			// Then pass the oid collection into applyActiveSet, which will turn
			// off anything that isn't active (i.e. hide them on the page)
			
			if($defined(oids) && (oids.length > 0))
			{
				this.applyActiveSet(oids);
				// raise event on success
			}
			else {
				// raise event on failure.
			}
		}
		else
		{
			// raise event on failure
		}
	}
});

// *********************************************
// CHKQueue - Queue
// *********************************************
var CHKQueue = new Class({
	Implements: [Events, Options, CHKOverrides],
	options: {
		enforceUnique: false
	},
	queue: [],
	initialize: function(options) {
		this.setOptions(options);
		this.setOverrides();
	},
	enqueue: function(item) {
		var enqueueFlag = false;
		
		// check to make sure the item is defined
		if ($defined(item))
		{
			// check to see if the enforceUnique option is on. if so only add the item if it doesn't already exist in the que
			if (this.options.enforceUnique)
			{
				if (!this.queue.contains(item))
				{
					this.queue.push(item);
					enqueueFlag = true;
				}
			}
			else
			{
				this.queue.push(item);
				enqueueFlag = true;
			}
		}
		
		// fire off the enqueue event
		this.fireEvent('enqueue', { item: item, success: enqueueFlag, obj: this});
	},
	dequeue: function() {
		var output = null,
		dequeueFlag = false;
		
		// check to make sure that the queue is properly defined and that it has values.
		if ($defined(this.queue) && this.queue.length > 0)
		{
			// shift the first item off of the array and return it in the output variable.
			output = this.queue.shift();
			dequeueFlag = true;
		}
		
		// fire off the dequeue event
		this.fireEvent('dequeue', { item: output, success: dequeueFlag, obj: this});
		
		return output;
	},
	clearQueue: function() {
		if ($defined(this.queue) && this.queue.length > 0)
		{
			this.queue = this.queue.empty();
			
			// fire off the clearqueue event
			this.fireEvent('clearQueue', this);
		}
	},
	getSize: function() {
		// check to make sure that the queue is properly defined and that it has values
		if ($defined(this.queue) && this.queue.length > 0)
		{
			// return the length of the queue
			return this.queue.length;
		}
		
		// the queue was not defined or it had nothing in it.  return 0
		return 0;
	},
	hasItems: function() {
		// if the size is greater than 0, we have items.  return true
		if (this.getSize() > 0)
		{
			return true;
		}
		
		// there are no items, return false
		return false;
	},
	hasItem: function(obj) {
		var output = false;
		
		// check to make sure that the obj and the queue are properly defined.
		if ($defined(obj) && $defined(this.queue) && this.queue.length > 0 && this.queue.contains(obj))
		{
			// a match was found. set the flag
			output = true;
		}
		
		// return the flag
		return output;
	},
	removeItem: function(obj) {
		var output = false;
		
		// only remove the item if it exists in the queue
		if ($defined(obj) && $defined(this.queue) && this.queue.length > 0 && this.queue.contains(obj))
		{
			this.queue = this.queue.erase(obj);
			output = true;
		}
		
		// fire off the removeItem event
		this.fireEvent('removeItem', { item: obj, success: output, obj: this});
		
		return output;
	}
});

// *********************************************
// CHKRequestMulti - Multiple Request object.
// *********************************************
var CHKRequestMulti = new Class({
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	options: {
		poolSize: 1
	},
	requestObjs: null,
	initialize: function(options) {
		this.setOptions(options);
		this.requestObjs = $H({});
		
		if ($defined(this.options.poolSize) && this.options.poolSize > 0)
		{
			// loop through the pool size and set up the event handlers
			for(i=0; i<this.options.poolSize; i++)
			{
				// get a reference to myself for use in the delegate functions below.
				var reqMultiObj = this;
				
				// use the current iteration as a unique id for the request object by passing it in as an option.
				// the parseInt as well as the options breaks the reference binding to the value.
				this.options.uid = parseInt(i,10);
				
				// instantiate a new request object
				var req = new Request(this.options);
				
				// wire up the delegate event handlers using the loop number as an id.
				// binding was not implemented on the delegate so that I could gain access to the current request object
				// and access the unique id (uid).
				req.addEvent('onComplete', function() {
					reqMultiObj.onCompleteHandler(this.options.uid);
				});
				
				req.addEvent('onCancel', function() {
					reqMultiObj.onCancelHandler(this.options.uid);
				});
				
				req.addEvent('onSuccess', function(responseText, responseXML) {
					reqMultiObj.onSuccessHandler(responseText, responseXML, this.options.uid);
				});
				
				req.addEvent('onFailure', function(xhr) {
					reqMultiObj.onFailureHandler(xhr, this.options.uid);
				});
				
				req.addEvent('onException', function(headerName, value) {
					reqMultiObj.onExceptionHandler(headerName, value, this.options.uid);
				});
				
				req.addEvent('onTimeout', function() {
					reqMultiObj.onTimeoutHandler(this.options.uid);
				});
				
				// add the request object to the internal collection.
				this.requestObjs.set(i, { isOpen: true, obj: req });
			}
		}
	},
	send: function(options) {

		if ($defined(this.requestObjs) && this.requestObjs.getLength() > 0)
		{
			var req = null;
			
			// Loop through the requestObjs collection and see if any of them are available to handle a request.
			this.requestObjs.each(function(value, key){
				if (!$defined(req) && $defined(value) && $defined(value.isOpen) && value.isOpen === true && $defined(value.obj))
				{
					// set the isOpen flag on this request to false.
					value.isOpen = false;

					// make the request.
					req = value.obj;
				}
			}.bind(this));
			
			if ($defined(req))
			{
				return req.send(options);
			}
		}
		
		// none of the request objects were available
		return null;
	},
	isOpen: function() {
		var isOpen = false;
		
		if ($defined(this.requestObjs) && this.requestObjs.getLength() > 0)
		{
			// Loop through the requestObjs collection and see if any of them are available to handle a request.
			this.requestObjs.each(function(value, key){
				if ($defined(value) && $defined(value.isOpen) && value.isOpen === true)
				{
					isOpen = true;
				}
			}.bind(this));
		}
		
		// none of the request objects were available
		return isOpen;
	},
	onCompleteHandler: function(id) {
		// set the isOpen flag on the request object to true;
		if ($defined(this.requestObjs) && this.requestObjs.has(id) && $defined(this.requestObjs.get(id)))
		{
			var requestObj = this.requestObjs.get(id);
			if ($defined(requestObj.isOpen))
			{
				requestObj.isOpen = true;
			}
		}
		
		// fire the event
		this.fireEvent('onComplete', [id]);
	},
	onCancelHandler: function(id) {
		// set the isOpen flag on the request object to true;
		if ($defined(this.requestObjs) && this.requestObjs.has(id) && $defined(this.requestObjs.get(id)))
		{
			var requestObj = this.requestObjs.get(id);
			if ($defined(requestObj.isOpen))
			{
				requestObj.isOpen = true;
			}
		}
		
		// fire the event
		this.fireEvent('onCancel', [id]);
	},
	onSuccessHandler: function(responseText, responseXML, id) {
		// set the isOpen flag on the request object to true;
		if ($defined(this.requestObjs) && this.requestObjs.has(id) && $defined(this.requestObjs.get(id)))
		{
			var requestObj = this.requestObjs.get(id);
			if ($defined(requestObj.isOpen))
			{
				requestObj.isOpen = true;
			}
		}
		
		// fire the event
		this.fireEvent('onSuccess', [responseText, responseXML, id]);
	},
	onFailureHandler: function(xhr, id) {
		// set the isOpen flag on the request object to true;
		if ($defined(this.requestObjs) && this.requestObjs.has(id) && $defined(this.requestObjs.get(id)))
		{
			var requestObj = this.requestObjs.get(id);
			if ($defined(requestObj.isOpen))
			{
				requestObj.isOpen = true;
			}
		}
		
		// fire the event
		this.fireEvent('onFailure', [xhr, id]);
	},
	onExceptionHandler: function(headerName, value, id) {
		// set the isOpen flag on the request object to true;
		if ($defined(this.requestObjs) && this.requestObjs.has(id) && $defined(this.requestObjs.get(id)))
		{
			var requestObj = this.requestObjs.get(id);
			if ($defined(requestObj.isOpen))
			{
				requestObj.isOpen = true;
			}
		}
		
		// fire the event
		this.fireEvent('onException', [headerName, value, id]);
	},
	onTimeoutHandler: function(id) {
		// set the isOpen flag on the request object to true;
		if ($defined(this.requestObjs) && this.requestObjs.has(id) && $defined(this.requestObjs.get(id)))
		{
			var requestObj = this.requestObjs.get(id);
			if ($defined(requestObj.isOpen))
			{
				requestObj.isOpen = true;
			}
		}
		
		// fire the event
		this.fireEvent('onTimeout', [id]);
	}
});

// *********************************************
// CHKCoreEngine_Base - 
// *********************************************
var CHKCoreEngine_Base = new Class({
	Implements: [Events, Options, CHKOverrides, CHKClassName],
	results: null, 
	resizeControl: null,
	toolbar: null, 
	pagemenus: [], 
	headerPopups: [], 
	headerTabControls: [],
	pagePopups: [], 
	pageTabControls: [],
	pageAccordions: [],
	footerPopups: [], 
	footerTabControls: [],
	pageScrollBoxes: [],
	buttons: [],
	sliders: [],
	view: [],
	sorter: null,
	services: [], 
	options: {
	},
	initialize: function(options) {
		this.setOptions(options);
		this.setOverrides();
		
		this.render(false);
	},
	render: function(resize) {
		if (!$defined(resize))
		{
			resize = false;
		}
		
		this.fireEvent('onBeginRender', this);
		
		if ($defined(this.customRender))
		{
			this.customRender(resize);
		}
		
		this.fireEvent('onEndRender', this);
	},
	customRender: $empty,
	setResults: function(obj) {
		if ($defined(obj)) 
		{
			// Save the results object
			obj.addEvent('onPositionChange', this.onPositionChangeReultsHandler.bind(this));
			this.results = obj;
		}
	},
	setResize: function(obj) {
		if ($defined(obj))
		{
			obj.addEvent('onResize', this.resizeHandler.bind(this));
			obj.addEvent('onResizeThreshold', this.resizeHandlerThreshold.bind(this));
			this.resizeControl = obj;
		}
	},
	setToolbar: function(obj) {
		// Save the toolbar object
		if ($defined(obj))
		{
			this.toolbar = obj;
		}
	},
	addSlider: function(obj) {
		if ($defined(obj))
		{
			obj.addEvent('onChange', this.onChangeSliderHandler.bind(this));
			this.sliders.push(obj);
		}
	},
	addView: function(obj) {
		if ($defined(obj)) 
		{
			// Wire up the event handlers
			obj.addEvent('onSelected', this.viewSelectedHandler.bind(this));
			this.view.push(obj);
		}
	},
	addServices: function(obj) {
		if ($defined(obj)) 
		{
			// Wire up the event handlers
			obj.addEvent('getDataSuccess', this.getDataSuccessHandler.bind(this));
			obj.addEvent('getDataFail', this.getDataFailHandler.bind(this));
			this.services.push(obj);
		}
	},
	addMenu: function(obj) {
		if ($defined(obj)) 
		{
			this.pagemenus.push(obj);
		}
	},
	addHeaderPopup: function(obj) {
		if ($defined(obj)) 
		{
			this.headerPopups.push(obj);
		}
	},
	addHeaderTabControls: function(obj) {
		if ($defined(obj)) 
		{
			this.headerTabControls.push(obj);
		}
	},
	addPagePopup: function(obj) {
		if ($defined(obj)) 
		{
			this.pagePopups.push(obj);
		}
	},
	addPageTabControls: function(obj) {
		if ($defined(obj)) 
		{
			this.pageTabControls.push(obj);
		}
	},
	addPageScrollBox: function(obj) {
		if ($defined(obj))
		{
			this.pageScrollBoxes.push(obj);
		}
	},
	addPageAccordions: function(obj) {
		if ($defined(obj)) 
		{
			this.pageAccordions.push(obj);
		}
	},
	addFooterPopup: function(obj) {
		if ($defined(obj)) 
		{
			this.footerPopups.push(obj);
		}
	},
	addFooterTabControls: function(obj) {
		if ($defined(obj)) 
		{
			this.footerTabControls.push(obj);
		}
	},
	addButton: function(obj) {
		if ($defined(obj)) 
		{
			this.buttons.push(obj);
		}
	},
	getBroswerSize: function() {
		if ($defined(this.resizeControl))
		{
			return this.resizeControl.getSize();
		}
		return null;
	},
	viewSelectedHandler: function(obj){
		// If a results obj has been set, set the view
		if (($defined(this.results)) && ($defined(obj)) && ($defined(obj.options)) && ($defined(obj.options.name)))
		{
			this.results.setView(obj.options.name);
			
			if (($defined(this.pageScrollBoxes)) && (this.pageScrollBoxes.length > 0))
			{
				this.pageScrollBoxes.each(function(item, index) { item.render(false); }.bind(this));
			}
		}
	},
	onChangeSliderHandler: function(data) {
		// Update the other sliders
		if (($defined(this.sliders)) && (this.sliders.length > 0))
		{
			this.sliders.each(function(slider, i) {
				if(slider.uid !== data.obj.uid)
				{
					slider.setPositionByPercentage(data.percentage);
				}
			}.bind(this));
		}
		
		// update the results panel
		if ($defined(this.results))
		{
			this.results.setPosition(data.percentage);
		}
	},
	onPositionChangeReultsHandler: function(data) {
		// update the sliders
		if (($defined(this.sliders)) && (this.sliders.length > 0))
		{
			this.sliders.each(function(slider, i) {
				if(slider.uid !== data.obj.uid)
				{
					slider.setPositionByPercentage(data.percentage, true);
				}
			}.bind(this));
		}
	},
	onChangeTabbedHandler: function(data) {
		// If a results obj has been set, adjust the position
		if ($defined(this.results))
		{
			this.results.setPosition(data.position);
		}
	},
	getDataSuccessHandler: function(data) {
		if ($defined(this.results))
		{
			this.results.loadData(data);
		}
	},
	getDataFailHandler: function(data) {
		alert('Get Data Failure - ' + JSON.encode(data));
	},
	resizeHandler: function(size) {
	},
	resizeHandlerThreshold: function(size) {
	}
});
function loadScript(url, callback){
    var script = document.createElement("script")
    script.type = "text/javascript";
    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function(){
            callback();
        };
    }
    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
};