﻿/*
	YO!script - A Javascript Framework for faster web development
	
	copyright 2006, YO!creations
	visit <www.YOcreations.com/YOscript> for more information.
	
	This code is made available under the GNU General Public License.
	Please feel free to use, examine, modify, improve upon, redistribute
	this software. Under the terms of the GNU GPL, any derivative works
	should be published with the same license permissions.
*/

/*
	Formatting Notes:
	
	Global Variables are prefixed with 'm_'
		m_VersionNumber
	Local Variables are prefixed with '_' 
		_Counter
	Parameters are prefixed with 'p_'
		p_Element
	Internal methods are prefixed with '__'
		__Init
		
	This notation allows easy identification of variable scope
	and makes it easier to compress the script without obfuscating
	public method/variable names.
*/

//Current Version Number
var m_VersionNumber = '1.2';
var m_LastUpdatedOn = '20 September 2006';

var YO = 
{
	//Returns the current version number
	Version : function()
	{
		return m_VersionNumber;
	},
	//Returns the last udpate date for this script
	LastUpdatedOn : function()
	{
		return m_LastUpdatedOn;
	}
}

//-------------------------
//Document (doc) object
//-------------------------
var Doc = {
	//Returns the width of the document
	Width : function ()
	{
		var _Width = 0;
		if (self.innerWidth)
			_Width = self.innerWidth; // all except Explorer
		else
		{
			if (document.documentElement && document.documentElement.clientWidth)
				_Width = document.documentElement.clientWidth; // Explorer 6 Strict Mode
			else
				if (document.body)
					_Width = document.body.clientWidth; // other Explorers
		}
		return _Width;
	},
	//Returns the height of the document
	Height : function ()
	{
		var _Height = 0;
		if (self.innerHeight)
			_Height = self.innerHeight; // all except Explorer
		else
		{
			if (document.documentElement && document.documentElement.clientHeight)
				_Height = document.documentElement.clientHeight; // Explorer 6 Strict Mode
			else
				if (document.body)
					_Height = document.body.clientHeight; // other Explorers
		}	
		return _Height;
	},
	//Returns an array of elements...
	GetEl : 
	{
		//...that have the specified CSS class name within the list of CSS classes
		WithClassName: function(p_ClassName)
		{
			//First, get all elements
			var _Elements = document.body.getElementsByTagName('*');

			//Define return collection			
			var _ReturnValue = new Array();

			//Now, add nodes with specified class (ignoring functions) into return array
			for (var _Key in _Elements)
				if (typeof _Elements[_Key] == 'object')
				{
					try
					{
						//get array of class names
						var _ClassNames = _Elements[_Key].className.split(' ');
						for (var _Counter = 0; _Counter < _ClassNames.length; _Counter++)
						{
							if (_ClassNames[_Counter] == p_ClassName)
							{
								_ReturnValue.push(_Elements[_Key]);
								continue;
							}
						}
					}
					catch(e)
					{
					}
			}

			return _ReturnValue;
		},
		//...that contains the specified string within its name
		ContainingName: function(p_Element)
		{
			//First, get all elements
			var _Elements = document.body.getElementsByTagName('*');

			//Define return collection			
			var _ReturnValue = new Array();

			//Now, add nodes with specified class (ignoring functions) into return array
			var x=0;
			var y = 0;
			ForEach(_Elements, function(_Element)
				{
					var _ElementName = _Element.id || _Element.name;
					if (_ElementName != null)
						if (_ElementName.indexOf(p_Element) > -1)
							_ReturnValue.push(_Element);
				}
			);

			return _ReturnValue;
		}
	},
	AddElement : function()
	{
		//If 1 parameter, add specified HTML to document
		//If 2 parameters, add specified HTML (1st parm) to specified parent element (2nd parm)
		var _ParentElement = El.Get(arguments[1]);
		_ParentElement.appendChild(arguments[0]);
	}
}

//--------------------------
//Element object
//--------------------------
var El = {
	//Returns the specified element
	Get : function(p_Element)
	{
		if (p_Element == 'body')
			return document.body;
		if (p_Element == 'document')
		    return document;
		if (typeof p_Element == 'string')
			return document.getElementById(p_Element);
		else
			return p_Element;
	},
	//Gets/Sets the value of the element
	Value : function()
	{
		//The value function is an aggregation of GetValue and SetValue
		//and is provided only for convenience
		if (arguments.length == 1)
		{
			var _Element = El.Get(arguments[0]);
			return _Element.value;
		}
		if (arguments.length == 2)
		{
			var _Element = El.Get(arguments[0])
			if (_Element != null)
				if (_Element.value)
					_Element.value = arguments[1];  //IE
				else
					_Element.innerHTML = arguments[1];  //Other browsers
		}
	},
	//Gets a boolean value indicating whether or not the element is visible
	IsVisible: function(p_Element)
	{
		var _Element = El.Get(p_Element);
		if (_Element == null)
			return false;
		else
			return El.Get(p_Element).style.display != 'none';
	},
	//Makes the element invisible
	Hide: function()
	{
		for (var _Counter = 0; _Counter < arguments.length; _Counter++)
		{
			var _Element = El.Get(arguments[_Counter]);
			if (_Element != null)
				_Element.style.display = 'none';
		}
	},
	//Makes the element visible
	Show: function()
	{
		for (var _Counter = 0; _Counter < arguments.length; _Counter++)
		{
			var _Element = El.Get(arguments[_Counter]);
			if (_Element != null)
				_Element.style.display = '';
		}
	},
	//Hides/shows the element based on its current state
	Toggle: function()
	{
		for (var _Counter = 0; _Counter < arguments.length; _Counter++)
		{
			var _Element = El.Get(arguments[_Counter]);
			if (_Element != null)
				if (El.IsVisible(_Element))
					El.Hide(_Element);
				else
					El.Show(_Element);
		}
	},
	//Gets an array containing the width and height of the element
	Dimensions: function()
	{
		if (arguments.length == 1)
		{
			//Get dimensions returns an array with Width and Height in it
			var _Return = new Array();
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
			{
				_Return.push(parseInt(_Element.style.width.replace('px','')));
				_Return.push(parseInt(_Element.style.height.replace('px','')));
			}
			return _Return;
		}
		if (arguments.length == 3)
		{
			//Set dimensions sets the length and width
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
			{
				_Element.style.width = arguments[1] + 'px';
				_Element.style.height = arguments[2] + 'px';
			}
		}
	},
	//Gets/Sets the width of the element
	Width: function()
	{
		if (arguments.length == 1)
		{
			//Get the width
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				return parseInt(_Element.style.width.replace('px',''));
			else
				return 0;
		}
		if (arguments.length == 2)
		{
			//Set the width
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				_Element.style.width = arguments[1] + 'px';
		}
	},
	//Gets/Sets the height of the element
	Height: function()
	{
		if (arguments.length == 1)
		{
			//Get the height
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				return parseInt(_Element.style.height.replace('px',''));
			else
				return 0;
		}
		if (arguments.length == 2)
		{
			//Set the height
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				_Element.style.height = arguments[1] + 'px';
		}
	},
	//Gets a formatted string of the current element size
	DimensionsString: function(p_Element)
	{
		//Returns the dimensions of the element in the format 'width x height'
		var _Element = El.Get(p_Element);
		if (_Element != null)
			return _Element.style.width.replace('px','') + ' x ' + _Element.style.height.replace('px','');
		else
			return '';
	},
	//Gets an array containing the Left and Top of the element
	Location: function()
	{
		//Takes 1 argument to Get the location (as an array)
		//and 3 arguments to Set the location
		if (arguments.length == 1)
		{
			//Get the location returns and array with Left and Top in it
			var _Return = new Array();
			_Return.push(El.Left(arguments[0]));
			_Return.push(El.Top(arguments[0]));
			return _Return;
		}
		if (arguments.length == 3)
		{
			//Sets the elements left and top
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
			{
				El.Left(arguments[0], arguments[1]);
				El.Top(arguments[0], arguments[2]);
			}
		}
	},
	//Gets/Sets the left property of the element
	Left: function()
	{
		//Takes 1 argument to Get the left property
		//and 3 arguments to Set it
		if (arguments.length == 1)
		{
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				return parseInt(_Element.style.left.replace('px',''));
			else
				return 0;
		}
		if (arguments.length == 2)
		{
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				_Element.style.left = arguments[1] + 'px';
		}
	},
	//Gets/Sets the top property of the element
	Top: function()
	{
		//Takes 1 argument to Get the left property
		//and 3 arguments to Set it
		if (arguments.length == 1)
		{
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				return parseInt(_Element.style.top.replace('px',''));
			else
				return 0;
		}
		if (arguments.length == 2)
		{
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				_Element.style.top = arguments[1] + 'px';
		}
	},
	//Gets a formatted string with the elements location
	LocationString: function(p_Element)
	{
		//Returns a string in the format 'Left, Top'
		var _Element = El.Get(p_Element);
		if (_Element != null)
			return _Element.style.left.replace('px','') + ', ' + _Element.style.top.replace('px','');
		else
			return '';
	},
	//Centers the element relative to the browser
	Center: function ()
	{
		//Centers each element passed in as a parameter
		for (var _Counter=0; _Counter < arguments.length; _Counter++)
		{
			var _Element = El.Get(arguments[_Counter]);
			var _Width = parseInt(Element.style.width.replace('px',''));
			var _Height = parseInt(Element.style.height.replace('px',''));
			var _doc = new Doc();
			var _Left = Math.max(0, _doc.Width() / 2 - _Width / 2);
			var _Top = Math.max(0, _doc.Height() / 2 - _Height / 2);
			El.SetLeft(_Element, _Left);
			El.SetTop(_Element, _Top);
		}
	},
	//Gets/Sets the opacity (see-through-edness) of the element
	Opacity: function ()
	{
		//Takes 1 argument to get the opacity and 2 to set it
		if (arguments.length == 1)
		{
			var _Element = El.Get(arguments[0]);

			if (_Element != null)
			{
				if (_Element.style.opacity) 
				{
					try
					{
						return _Element.style.opacity * 100;		//Mozilla
					}
					catch (ex)
					{
						//If no opacity is set, the default is 100
						return 100;
					}
				}
				else if (_Element.style.filter)
				{
					try
					{
						var _Opacity = parseInt(_Element.style.filter.replace('alpha(opacity=','').replace(')', ''));    //IE
						if (isNaN(_Opacity))
							return 100;
						else
							return _Opacity;
					}
					catch (ex)
					{
						//If no opacity is set, the default is 100
						return 100;
					}				
				}
				else
					return 100;
			}
			else
				return -1;
		}
		if (arguments.length == 2)
		{
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
			{
				_Element.style.opacity = arguments[1] / 100;		//Mozilla
				_Element.style.filter = 'alpha(opacity=' + arguments[1] + ')';    //IE
			}
		}

	},
	//Gets/Sets the src property of the element
	Src: function()
	{
		//Gets or Sets the .src property of the specified element.
		if (arguments.length == 1)
		{
			var _Element = El.Get(arguments[0]);
			if (_Element == null)
				return '';
			else
				return _Element.src;
		}
		if (arguments.length == 2)
		{
			var _Element = El.Get(arguments[0]);
			if (_Element != null)
				_Element.src = arguments[1];
		}
	},
	//Gets/Sets the CSS class of the element
	CSSClass : function(p_Element, p_ClassName)
	{
		var _Element = El.Get(p_Element);
		if (_Element != null)
		{
			if (arguments.length == 1)
				return _Element.className;
			if (arguments.length == 2)
				_Element.className = p_ClassName;
		}
	},
	//Adds the specified class name to the element's list of css classes
	AddCSSClass: function (p_Element, p_ClassName)
	{
		var _Element = El.Get(p_Element);
		if (_Element != null)
		{
			//get array of class names
			var _ClassNames = _Element.className.split(' ');
			for (var _Counter = 0; _Counter < _ClassNames.length; _Counter++)
			{
				if (_ClassNames[_Counter] == p_ClassName)
					return;
			}

			_Element.className = (_Element.className + ' ' + p_ClassName).replace('  ',' ');
		}
	},
	//Removes the specified class name from the element's list of classes
	RemoveCSSClass: function (p_Element, p_ClassName)
	{
		var _Element = El.Get(p_Element);
		if (_Element != null)
		{
			//get array of class names
			var _ClassNames = _Element.className.split(' ');
			for (var _Counter = 0; _Counter < _ClassNames.length; _Counter++)
			{
				if (_ClassNames[_Counter] == p_ClassName)
					_ClassNames[_Counter] = '';
			}
			_Element.className = _ClassNames.join(' ').replace('  ', ' ');
		}
	},
	//Gets/Sets the style of the element
	CSSStyle : function()
	{
		var _Element = El.Get(p_Element);
		if (_Element != null)
		{
			if (arguments.length == 1)
				return _Element.style;
			if (arguments.length == 2)
				_Element.style = p_ClassName;
		}
	},
	//Places the cursor/focus in the element
	Focus: function(p_Element)
	{
		var _Element = El.Get(p_Element);
		if (_Element != null)
		{
			_Element.focus();
		}
	}
}


//--------------------------
//Top-Level, Public Methods
//--------------------------

//Provides an easy way to iterate an array
function ForEach(p_IterableType, p_IteratorFunction)
{
	for	(var _Counter=0; _Counter<p_IterableType.length; _Counter++) 
		p_IteratorFunction(p_IterableType[_Counter]);
	return;
}

//--------------------------
//Event handling
//--------------------------
var Evt = {
     m_Cache : null,
     //Internal function
     __Init : function()
     {
		if (this.m_Cache == null)
		{
             this.m_Cache = new Array();

             // Make sure we clean up all events when the window is unloaded
             Evt.Add(window, "unload", this.__Dispose, false);
         }
     },
     //Adds an event handler
     Add : function(p_Element, p_Event, p_Handler, p_UseCapture)
     {
        this.__Init();

		//Get the actual element
        var _Element = El.Get(p_Element);

        //Validate element and handler
        if (_Element == null || p_Handler == null)
        {
			return false;
        }
         
        //Check to see if event already exists
        var _EventAlreadyHandled = false;
        ForEach(this.m_Cache, function(p_CachedEvent)
			{
				if (p_CachedEvent.Element.id == _Element.id && p_CachedEvent.Event == p_Event)
					_EventAlreadyHandled = true;
			}
		);
		if (_EventAlreadyHandled)
			return;

        // Attach event for IE
        if (_Element.attachEvent && _Element.attachEvent("on" + p_Event, p_Handler))
        {
            this.m_Cache.push({Element: _Element, Event: p_Event, Handler: p_Handler, UseCapture: p_UseCapture});
            return true;
        }
		else
        {
	        // Attach event for all other browsers
            _Element.addEventListener(p_Event, p_Handler, p_UseCapture);
            this.m_Cache.push({Element: _Element, Event: p_Event, Handler: p_Handler, UseCapture: p_UseCapture});
            return true;
        }

        return false;
     },
     //Removes an event handler
     Remove: function (p_Element, p_Event, p_Handler, p_UseCapture)
     {
		var _Element = El.Get(p_Element);
		
		//Detach IE event
		if (_Element.detachEvent)
		{
			_Element.detachEvent("on" + p_Event, p_Handler);
		}
		
		//Detach events for other browsers
		if (_Element.removeEventListener)
		{	
			_Element.removeEventListener(p_Event, p_Handler, p_UseCapture);
		}
		
		//Remove from cache
		for (var _Counter = 0; _Counter<Evt.m_Cache.length; _Counter++)
		{
			if (Evt.m_Cache[_Counter].Element == _Element &&
				Evt.m_Cache[_Counter].Event == p_Event)
			{
				Evt.m_Cache.splice(_Counter, 1);
				break;
			}
		}
     },
     //Internal function
     __Dispose : function()
     {
         ForEach(Evt.m_Cache, function(p_RegisteredEvent)
			{
				with (p_RegisteredEvent)
				{
					//Detach IE event
					if (Element.detachEvent)
					{
						Element.detachEvent("on" + Event, Handler);
					}
					
					//Detach events for other browsers
					if (Element.removeEventListener)
					{	
						Element.removeEventListener(Event, Handler, UseCapture);
					}
				}
			}
		)
		//Now that all events have been detached, eliminate cache object
         Evt.m_Cache = null;
     },
     //Gets the element that raised the event
     GetTarget : function(p_Event)
	{
		//Determine (in a cross-browser fashion) which element raised the event
		
		//Get the actual event
		if (!p_Event)
			p_Event = event;
			
		//Find the target of the event
		var _TargetElement;
		if (p_Event.target) _TargetElement = p_Event.target;
		if (p_Event.srcElement) _TargetElement = p_Event.srcElement;
		if (_TargetElement.nodeType == 3) // defeat Safari bug
			_TargetElement = _TargetElement.parentNode;
		
		return _TargetElement;
	 },
	 //Gets the name of the element that raised the event
	GetTargetName : function(p_Event)
	{
		var _TargetElement = Evt.GetTarget(p_Event);

		//Get name of element that raised this event
		var _ElementName = _TargetElement.id || _TargetElement.name;
		
		//Check to see if the click came on a text node with no ID
		while(_ElementName == undefined)
		{
			_ElementClicked = _ElementClicked.parentElement;
			_ElementName = _ElementClicked.id || _ElementClicked.name;
		}

		return _ElementName;
	 },
	 //Gets the event itself (in cross-browser format)
	GetEvent : function(p_Event)
	{
		if (!p_Event)
			p_Event = event;
		return p_Event;
	},
	//Gets the key pressed for applicable events
	GetKeyPressed : function(p_Event)
	{
		var _Event = Evt.GetEvent(p_Event);
		return _Event.keyCode;
	}
};




//--------------------------
//UI Helper Methods
//--------------------------

//Sets up a rollover effect on the specified element
function Rollover(Element, HoverSource)
{
	var Source = El.Src(Element);
	Evt.Add(Element, 'mouseover', function(){El.Src(Element, HoverSource);}, true);
	Evt.Add(Element, 'mouseout', function(){El.Src(Element, Source);}, true);
}
//Preloads each image url provided in the arguments ('image1.jpg', 'image2.jpg', ...)
function PreloadImages()
{
	ForEach(arguments, function(p_Argument)
		{
			var _PreloadedImage = new Image();
			_PreloadedImage.src = p_Argument;
		}
	)
}