// This file was dynamicaly created for 

// JavaScript Document

// displaying "Loading Framework..." message
document.writeln('<div id="loading_message" class="hidden" style="padding:10px; background:#FFFFFF; color:#000000; font-weight:bold; font-family:Arial,Tahoma; position:absolute;">Loading Framework...<div id="loaded_modules"></div></div>');

// Definitions
var framework_location = 'http://vitaminxp.com/framework/JavaScript/';

// Framework Start
var VitaminXP = window.VitaminXP || {};

// Detect Web browser
VitaminXP.DetectBrowser = function() 
{
    var agt=navigator.userAgent.toLowerCase();
    if (agt.indexOf("opera") != -1) return 'Opera';
    if (agt.indexOf("staroffice") != -1) return 'Star Office';
    if (agt.indexOf("webtv") != -1) return 'WebTV';
    if (agt.indexOf("beonex") != -1) return 'Beonex';
    if (agt.indexOf("chimera") != -1) return 'Chimera';
    if (agt.indexOf("netpositive") != -1) return 'NetPositive';
    if (agt.indexOf("phoenix") != -1) return 'Phoenix';
    if (agt.indexOf("firefox") != -1) return 'Firefox';
    if (agt.indexOf("safari") != -1) return 'Safari';
    if (agt.indexOf("skipstone") != -1) return 'SkipStone';
    if (agt.indexOf("msie") != -1) return 'Internet Explorer';
    if (agt.indexOf("netscape") != -1) return 'Netscape';
    if (agt.indexOf("mozilla/5.0") != -1) return 'Mozilla';
    if (agt.indexOf('\/') != -1) {
    if (agt.substr(0,agt.indexOf('\/')) != 'mozilla') {
    return navigator.userAgent.substr(0,agt.indexOf('\/'));}
    else return 'Netscape';} else if (agt.indexOf(' ') != -1)
    return navigator.userAgent.substr(0,agt.indexOf(' '));
    else return navigator.userAgent;
}

var Browser = VitaminXP.DetectBrowser();

var loaded_modules = 0;

// Creates (if doesn't exist) and returns the namespace passed
VitaminXP.Namespace = function(ns)
{
    if (!ns || !ns.length)
	{
        return null;
    }
	
    var levels = ns.split(".");
    var nsobj = VitaminXP;

    // "VitaminXP" is implied, so it is ignored if it is included
    for (var i = (levels[0] == "VitaminXP") ? 1 : 0; i < levels.length; ++i)
	{
        nsobj[levels[i]] = nsobj[levels[i]] || {};
        nsobj = nsobj[levels[i]];
    }
	
	loaded_modules++;
	
	document.getElementById("loaded_modules").innerHTML = "Loaded Modules: " + loaded_modules;

    return nsobj;
};

// Load prerequisit namespace
VitaminXP.Import = function(ns)
{
    var levels = ns.split(".");
    var nsobj = VitaminXP;
    var exists = true;
    
    // check if this namespace is already imported
    for (var i = (levels[0] == "VitaminXP") ? 1 : 0; i < levels.length; ++i)
	{
	    if(nsobj[levels[i]])
	    {
            nsobj = nsobj[levels[i]];
	    }
        else
        {
	        exists = false;
	        i = levels.length;
        }
    }
    
    if(!exists)
    {
        document.writeln('<script src="' + framework_location + ns.toLowerCase() + '.js" type="text/javascript"></script>');
    }
};

VitaminXP.Exception = function(error, func)
{
	var message = (typeof error == 'object') ? error.message : error;
	
	alert("JavaScript Error Occured: ''" + message + "'' in function " + func + "()");
};

// String of javascript to execute when page loads
VitaminXP.StartupScript = '';

// On Page Load
window.onload = function()
{
	try
	{
		if(VitaminXP.StartupScript != '')
		{
			eval(VitaminXP.StartupScript);
			VitaminXP.StartupScript = '';
		}
	}
	catch(ex)
	{
		window.status = ex.message;
	}
}

// Adds passed script to variable and will be executed when page loads
VitaminXP.StartUp = function(script)
{
	VitaminXP.StartupScript += script + ";";
}

// Returns Element that has ID same as passed
function element(el)
{
	return VitaminXP.Element.Get(el);
}

function $(el)
{
	return VitaminXP.Element.Get(el);
}

// Opens a new pop up window 
VitaminXP.OpenWindow = function(url,id,width,height)
{ // Additional args: 5) left, 6) top.
	var args = open_window.arguments
	
	var left = (args.length > 4)? args[4] : (screen.availWidth/2)-(width/2)
	var top = (args.length > 5)? args[5] : (screen.availHeight/2)-(width/2)
	setup = 'toolbar=no,location=no,directories=no,left='+left+',top='+top+',menubar=no,width='+width+',height='+height
	setup += 'scrollbars=no,resizable=no'
	window.open(url,id,setup)
}

// Reloads page (not just refreshes)
VitaminXP.ReloadPage = function()
{
	if(Browser == "Internet Explorer"){
		history.go(0)
	}else{
		window.location.reload(true)
	}
}

// hide "loading..." message
VitaminXP.HideLoadingStatusMessage = function()
{
	VitaminXP.Animation.Animate($('loading_message'), {opacity:{to:0}}, 1, 'EaseBoth');
	
	// just hide it in case animation failed
	setTimeout('$(\'loading_message\').style.display = \'none\'', 1000);
}

VitaminXP.StartUp("VitaminXP.HideLoadingStatusMessage()");

// VitaminXP Javascript Framework
// Module: Ajax
// Copyright: www.VitaminXP.com
// Author: Dmitriy Kulikovskiy

// Create NameSpaces
VitaminXP.Namespace("Ajax");


// Create a Blank request instence which will be used everytime the request is made
VitaminXP.Ajax.Request = function(obj, url){
	this.Document = null;
	this.TargetObject = obj;
	this.SuccessAction = "html";
	this.Method = "GET";
	this.URL = url;
	this.Parameters = "";
	this.ExecuteFunction = "";
	this.Asynchronous = true;
	this.MicrosoftProgramIDs = "";
	this.States = new Array("uninitialized","loading","loaded","interacting","complete")
	this.MicrosoftProgramIDs = ["MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
};

// Requests a URL and passes the request to aother function to handle the state change event
VitaminXP.Ajax.RequestUrl = function(obj,url){ // Object,URL,Parameters,Method,Action,Function Name
	
	// Create a copy of blank request
	var Request = new VitaminXP.Ajax.Request(obj, url);
	
	// Optinal arguments
	var args = VitaminXP.Ajax.RequestUrl.arguments;
	if(args.length > 2) Request.Parameters = args[2];
	if(args.length > 3) Request.Method = args[3].toUpperCase()
	if(args.length > 4) Request.SuccessAction = args[4].toLowerCase()
	if(args.length > 5) Request.ExecuteFunction = args[5];
	
	// Try to create an HTTP Request object
	try
	{
		if (window.XMLHttpRequest) // Mozilla, Safari,...
			Request.Document = new XMLHttpRequest();
		else if (window.ActiveXObject) // IE
		{
			while (!Request.Document && Request.MicrosoftProgramIDs.length)
			{
				try
				{
					Request.Document = new ActiveXObject(Request.MicrosoftProgramIDs[0]);
				}
				catch (e)
				{
					Request.Document = null;
				}
				
				if (!Request.Document) Request.MicrosoftProgramIDs.splice(0, 1);
			}
		}
	}
	catch (e)
	{
		Request.Document = null;
	}
	
	if(!Request.Document) return false;
	
	// Initialize request
	Request.Document.onreadystatechange = function(){VitaminXP.Ajax.ProcessStateChange(Request)};
	Request.Document.open(Request.Method, Request.URL, Request.Asynchronous);
	Request.Document.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	Request.Document.setRequestHeader("Content-length", Request.Parameters.length);
	Request.Document.setRequestHeader("Connection", "close");
	Request.Document.send(Request.Parameters);
	return true;
};

// Handles state change event of the request passed to this function
VitaminXP.Ajax.ProcessStateChange = function(Request){
	window.status = 'Ajax: ' + Request.States[Request.Document.readyState];
	
	if(Request.Document.readyState == 4){ // Complete
		if(Request.Document.status == 200 || Request.Document.status == 0){ // OK response
			if(Request.SuccessAction == "html")
			{
				Request.TargetObject.innerHTML = Request.Document.responseText;
			}
			else if(Request.SuccessAction == "text")
			{
				Request.TargetObject.innerText = Request.Document.responseText;
			}
			else if(Request.SuccessAction == "function")
			{
				eval(Request.ExecuteFunction)(Request.Document.responseText, Request.TargetObject)
			}
			else if(Request.SuccessAction == "value")
			{
				Request.TargetObject.value = Request.Document.responseText
			}
			else if(Request.SuccessAction == "link")
			{
				if(Request.Document.responseText.toUpperCase() == "OK")
				{
					window.location = Request.ExecuteFunction
				}
				else
				{
					alert(Request.Document.responseText)
				}
			}
			else if(Request.SuccessAction.toLowerCase() == "ok")
			{
				if(Request.Document.responseText.toUpperCase() == "OK")
				{
					if(Request.ExecuteFunction != "")
					{
						eval(Request.ExecuteFunction)(Request.TargetObject)
					}
				}
				else
				{
					alert(Request.Document.responseText)
				}
			}
			Request = null
		}
		else
		{
			window.status = 'Ajax: problem ' + Request.Document.statusText + ', status: ' + Request.Document.status
		}
	}
};

// Create NameSpaces
VitaminXP.Namespace("VitaminXP.Animation");

VitaminXP.Animation.FramesPerSecond = 200;
VitaminXP.Animation.FrameLength = 1000 / VitaminXP.Animation.FramesPerSecond; // In miliseconds
VitaminXP.Animation.Timer = null; // Container of the timer
VitaminXP.Animation._animations = new Array();

// Adds an instanse of new animation to an array of currently running animations
VitaminXP.Animation.RegisterAnimation = function(animation)
{
	// If [animation] instance is working on same element as currently running instances and works on same attributes,
	// the attributes has to be deleted from currently running instances so only last added instance works on one instance for that element
	
	// Loop through every instance that is registered
	for(i = 0; i < VitaminXP.Animation._animations.length; i++)
	{
		// Check if that instance is using same element as the new instance that is currently registering
		if(VitaminXP.Animation._animations[i].element == animation.element)
		{
			// Loop through every attribute in a new instance that is about to be registered
			for(new_attribute in animation._attributes)
			{
				// Remove matching attribute so only new instance would have those attributes
				if(VitaminXP.Animation._animations[i]._attributes.hasOwnProperty(new_attribute))
				{
					delete VitaminXP.Animation._animations[i]._attributes[new_attribute];
				}
			}
			
			// If the instance doesn't have any more atributes, then remove it
			if(VitaminXP.Animation._animations[i]._attributes.properties() == 0)
			{
				VitaminXP.Animation.UnregisterAnimation(VitaminXP.Animation._animations[i]);
				delete VitaminXP.Animation._animations[i];
			}
		}
	}
	
	VitaminXP.Animation._animations.push(animation);
	
	if(VitaminXP.Animation._animations.length == 1) VitaminXP.Animation.Timer = setInterval(VitaminXP.Animation.AnimateFrame, VitaminXP.Animation.FrameLength);
}

// Removes passed instance of animation from an array of running animations
VitaminXP.Animation.UnregisterAnimation = function(animation)
{
	VitaminXP.Animation._animations.Remove(animation);
	
	if(VitaminXP.Animation._animations.length == 0)
	{
		clearInterval(VitaminXP.Animation.Timer);
	}
}

// Loops through list of running animations and executes one frame for each animation
VitaminXP.Animation.AnimateFrame = function()
{
	for(i = 0; i < VitaminXP.Animation._animations.length; i++)
	{
		try
		{
			VitaminXP.Animation._animations[i].ExecuteFrame();
		}
		catch(ex)
		{
			VitaminXP.Exception(ex, "VitaminXP.Animation.AnimateFrame");
		}
	}
}

// Creates a new instance of Animation, starts it, and then returns it
VitaminXP.Animation.Animate = function(element, _attributes, seconds, method)
{
	try
	{
		if(element && _attributes && seconds > 0 && method != "")
		{
			var NewAnimation = new VitaminXP.Animation.InitializeAnimation(element, _attributes, seconds, method);
			NewAnimation.Start();
			
			return NewAnimation;
		}
	}
	catch(ex)
	{
		VitaminXP.Exception(ex, "VitaminXP.Animation.Animate");
	}
}

// Creates a new instance of Animation and returns it
VitaminXP.Animation.InitializeAnimation = function(element, _attributes, seconds, method)
{
	this.element = VitaminXP.Element.Get(element)
	this._attributes = _attributes || {};
	this.seconds = seconds;
	this.method = VitaminXP.Animation.Method(method);
	this.current_frame = 0;
	this.total_frames = Math.ceil(this.seconds / (1 / VitaminXP.Animation.FramesPerSecond));
	this._value = new Array(this.total_frames);
	this.start_time = new Date();
	this.last_frame_execution_time = new Date();
	
	// Set values for each attribute for each frame
	for(attribute in this._attributes)
	{
		if(attribute != 'properties') // because object has properties that is not needed in this case
		{
			if(this._attributes[attribute].from == null)
			{
				this._attributes[attribute].from = parseFloat(VitaminXP.Element.GetAttribute(this.element, attribute));
			}
			
			for(this.current_frame = 1; this.current_frame <= this.total_frames; this.current_frame++)
			{
				if(!this._value[this.current_frame]) this._value[this.current_frame] = new Array(this._attributes.length)
				
				this._value[this.current_frame][attribute] = Math.round(this.method(this.current_frame, this._attributes[attribute].from, this._attributes[attribute].to - this._attributes[attribute].from, this.total_frames));
			}
			
			this._attributes[attribute]['unit'] = VitaminXP.Animation.GetUnitByAttribute(attribute);
		}
	}
	
	// Reset Frame Number
	this.current_frame = 0;
	
	// This function sets the value to the property
	this.ExecuteFrame = function()
	{
		try
		{
			// Figure out what frame should be executed next
			var next_frame = parseInt(((this.last_frame_execution_time.valueOf() - this.start_time.valueOf()) / VitaminXP.Animation.FrameLength) + 1);
			
			if(next_frame > this.total_frames)
			{
				// If last frame was going to be droped, then just execute last frame
				this.current_frame = this.total_frames;
			}
			else if(next_frame > this.current_frame + 1)
			{
				// Drop Frames (skip frames)
				this.current_frame = next_frame;
			}
			else
			{
				// Next frame
				this.current_frame++;
			}
			
			// Loop through each attribute and...
			for(attribute in this._attributes)
			{
				if(attribute != 'properties') // because object has properties that is not needed in this case
				{
					if(this._value[this.current_frame] != undefined)
					{
						// check if element is an instance of VitaminXP.Forms.Control
						if((attribute == 'top' || attribute == 'left') && typeof this.element.MoveTo == 'function' && typeof this.element.location == 'object')
						{
							switch(attribute)
							{
								case 'left':
									this.element.MoveTo(this._value[this.current_frame][attribute], this.element.location.y);
									break;
									
								case 'top':
									this.element.MoveTo(this.element.location.x, this._value[this.current_frame][attribute]);
									break;
							}
						}
						else
						{
							// ... set style of elemnt
							VitaminXP.Element.SetStyle(this.element, attribute, this._value[this.current_frame][attribute] + this._attributes[attribute]['unit']);
						}
					}
				}
			}
			
			// Detect end of animation
			if(this.current_frame >= this.total_frames)
			{
				this.Stop();
				this.Dispose();
			}
			
			// Log last execution time
			this.last_frame_execution_time = new Date();
			}
		catch(ex)
		{
			VitaminXP.Exception(ex, 'VitaminXP.Animation.Animate.ExecuteFrame');
		}
	}
	
	// Starts animation
	this.Start = function()
	{
		VitaminXP.Animation.RegisterAnimation(this);
		this.start_time = new Date();
	}
	
	// Stops animation, but does not dispose it, so it can be started again to continue
	this.Stop = function()
	{
		VitaminXP.Animation.UnregisterAnimation(this);
	}
	
	this.Dispose = function()
	{
		this.Stop();
		//delete this;
	}
	
	return this;
}

VitaminXP.Animation.Method = function(method)
{
	switch(method)
	{
		case "EaseNone":
			
			return function (t, b, c, d) {
				return c*t/d + b;
			}
			
			break;
		
		case "EaseIn":
			
			return function(c, s, e, t)
			{
				return e*(c/=t)*c + s;
			}
			
			break;
		
		case "EaseOut":
			
			return function(c, s, e, t)
			{
				return -e *(c/=t)*(c-2) + s;
			}
			
			break;
		
		case "EaseBoth":
			
			return function(c, s, e, t)
			{
				if ((c/=t/2) < 1) {
					return e/2*c*c + s;
				}
				
				return -e/2 * ((--c)*(c-2) - 1) + s;
			}
			
			break;
		
		case "EaseInStrong":
			
			return function(c, s, e, t)
			{
				return e*(c/=t)*c*c*c + s;
			}
			
			break;
		
		case "EaseOutStrong":
			
			return function(c, s, e, t)
			{
				return -e * ((c=c/t-1)*c*c*c - 1) + s;
			}
			
			break;
		
		case "EaseBothStrong":
			
			return function(c, s, e, t)
			{
				if ((c/=t/2) < 1) return e/2*c*c*c*c + s;
   				return -e/2 * ((c-=2)*c*c*c - 2) + s;
			}
			
			break;
		
		case "BackIn":
			
			return function (t, b, c, d, s) {
				if (typeof s == 'undefined') {
					s = 1.70158;
				}
				return c*(t/=d)*t*((s+1)*t - s) + b;
			}
			
			break;
		

		case "BackOut":
			
			return function(c, s, e, t, o)
			{
				if (typeof o == 'undefined') o = 1.70158;
   				return e*((c=c/t-1)*c*((o+1)*c + o) + 1) + s;
			}
			
			break;
		
		case "BackBoth":
			
			return function(c, s, e, t, o)
			{
				if (typeof o == 'undefined') o = 1.70158; 
				if ((c/=t/2) < 1) return e/2*(c*c*(((o*=(1.525))+1)*c - o)) + s;
				return e/2*((c-=2)*c*(((o*=(1.525))+1)*c + o) + 2) + s;
			}
			
			break;
		
		case "BounceOut":
			
			return function(c, s, e, t)
			{
				if ((c/=t) < (1/2.75)) {
					return e*(7.5625*c*c) + s;
				} else if (c < (2/2.75)) {
					return e*(7.5625*(c-=(1.5/2.75))*c + .75) + s;
				} else if (c < (2.5/2.75)) {
					return e*(7.5625*(c-=(2.25/2.75))*c + .9375) + s;
				} else {
					return e*(7.5625*(c-=(2.625/2.75))*c + .984375) + s;
				}
			}
			
			break;
		
		case "BounceIn":
			
			return function(c, s, e, t)
			{
				c = t-c;
				s = 0;
				
				if ((c/=t) < (1/2.75)) {
					return e - (e*(7.5625*c*c) + s) + s;
				} else if (c < (2/2.75)) {
					return e - (e*(7.5625*(c-=(1.5/2.75))*c + .75) + s) + s;
				} else if (c < (2.5/2.75)) {
					return e - (e*(7.5625*(c-=(2.25/2.75))*c + .9375) + s) + s;
				} else {
					return e - (e*(7.5625*(c-=(2.625/2.75))*c + .984375) + s) + s;
				}
			}
			
			break;
		
		case "ElasticIn":
			
			return function (t, b, c, d, a, p) {
				if (t == 0) {
					return b;
				}
				if ( (t /= d) == 1 ) {
					return b+c;
				}
				if (!p) {
					p=d*.3;
				}
				
				if (!a || a < Math.abs(c)) {
					a = c; 
					var s = p/4;
				}
				else {
					var s = p/(2*Math.PI) * Math.asin (c/a);
				}
				
				return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
			}
			
			break;
		
		case "ElasticOut":
			
			return function (t, b, c, d, a, p) {
				if (t == 0) {
					return b;
				}
				if ( (t /= d) == 1 ) {
					return b+c;
				}
				if (!p) {
					p=d*.3;
				}
				
				if (!a || a < Math.abs(c)) {
					a = c;
					var s = p / 4;
				}
				else {
					var s = p/(2*Math.PI) * Math.asin (c/a);
				}
				
				return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
			}
			
			break;
		
		default:
			// This is same as EaseIn
			return function(c, s, e, t)
			{
				return e*(c/=t)*c + s;
			}
			
			break;
	}
}

VitaminXP.Animation.GetUnitByAttribute = function(attribute)
{
	attribute = VitaminXP.Element.toHyphen(attribute);
	
	switch(attribute)
	{
		case "opacity":
			return "";
			break;
			
		case "scroll-top":
			return "";
			break;
			
		case "scroll-left":
			return "";
			break;
		
		default:
			return "px";
			break;
	}
}



VitaminXP.Namespace("VitaminXP.AudioPlayer");

var sound_OnPlayStateChange;

VitaminXP.AudioPlayer = function(playlist_url, autoplay, parent)
{
	// Create Player Object
	var Player = document.createElement('div');
	Player.id = "player";
	
	// Properties
	Player.playlist_url = playlist_url;
	Player._files = playlist_url; // new Array();
	Player.current_track = 1;
	Player.length = 0;
	Player.position = 0;
	Player.volume = 0;
	Player.mute = false;
	Player.speed = 1;
	Player.repeat = false;
	Player.changing_track = false;
	Player.autoplay = autoplay;
	Player.buffer = 0; // Buffered %
	Player.browser = "Internet Explorer"; // it's only initial value, but will be overwritten with correct value in a second
	Player.parent = parent;
	Player.parent.appendChild(Player);
	Player.object = null;
	
	Player.error = -1;
	Player._errors = new Array("Could not load playlist","Windows Media Player is not installed","QuickTime player is not installed");
	
	Player.state = 5; // Loading Playlist
	Player._states = new Array("Stopped","Playing","Paused","Fast Forwarding","Rewinding","Loading Playlist...","Buffering","ERROR");
	
	// This is used to convert from Windows Media Player status code to this player's state code
	Player.WMPStates = new Array(0, 0, 2, 1, 6, 6, 6, 6, 0, 6, 0, 6);
	
	// This is used to convert from Real Player status code to this player's state code
	Player.RPStates = new Array(0, 6, 6, 1, 2, 2);
	
	// This is used to convert from Flash Player state code to this player's state code
	Player.FPStates = new Array(0, 1, 2, 3, 6);
	
	// This is used to convert from Flash Player state code to this player's state code
	Player.HTML5PStates = new Array(6, 0, 1, 2, 7);
	
	Player.timer_fast = null;
	Player.timer_state_check = null;
	
	// Events
	Player.onplaylistloaded = null; // occures when playlist has been loaded
	Player.onstatechange = null;
	Player.onpositionchange = null;
	
	Player.Initialize = function()
	{
		// Detect Player installed and figure out best player to use
		Player.browser = VitaminXP.System.DetectBrowser();
		
		// check if HTML5 Audion is supported
		if(typeof HTML5AudioPlayer == 'function')
		{
			var html5player = new HTML5AudioPlayer('');
			if(html5player.canPlayMP3())
			{
				Player.type = 'html5';
			}
		}
		
		if(Player.type == undefined)
		{
			if(Player.browser == 'Opera' && VitaminXP.System.isPlayerInstalled("flash"))
			{
				Player.type == 'flash';
			}
			
			//Player.type = ((Player.browser == 'Internet Explorer' || Player.browser == 'Netscape')) ? 'windows_media' : 'other';
			Player.type = ((Player.browser == 'Internet Explorer' || Player.browser == 'Netscape') && VitaminXP.System.getFlashVersion() > 6) ? 'flash' : 'other';
			
			if(Player.type == 'other')
			{
				if(VitaminXP.System.isPlayerInstalled("flash") && VitaminXP.System.getFlashVersion() > 6)// && Player.browser == 'Safari'
				{
					Player.type = 'flash';
				}
				else if(VitaminXP.System.isPlayerInstalled('real') && VitaminXP.System.Browser != 'Safari')
				{
					Player.type = 'real';
				}
				else if(VitaminXP.System.isPlayerInstalled('quicktime'))
				{
					Player.type = 'quicktime';
				}
				else if(VitaminXP.System.isPlayerInstalled("windows_media"))
				{
					Player.type = 'windows_media';
				}
				else if(VitaminXP.System.isPlayerInstalled("flash")) // this time accept any version of flash
				{
					Player.type = 'flash';
				}
				else
				{
					var message = 'Your computer does not have a Real Player or Quicktime player to use all features of this player in your browser: ' + Player.browser;
					
					if(VitaminXP.System.isPlayerInstalled('windows_media'))
					{
						message += ' Please use Internet Explorer to play music using Windows Media Player using all features of this player or install Real Player or Quicktime Player on this computer and try again.';
					}
					else
					{
						message += ' Install Real Player or Quicktime Player to be able to play music in this browser.';
					}
					
					alert(message);
				}
			}
		}
		
		if(Player.object != null)
		{
			Player.object = null;
		}
		
		//if(VitaminXP.System.isPlayerInstalled('quicktime')) Player.type = 'quicktime'; // this is for testing qt only
		//if(Player.type == 'real') Player.type = 'quicktime'; // this is for testing qt only
		
		switch(Player.type)
		{
			case 'windows_media':
				
				Player.innerHTML = '' +
'<object id="sound" classid="clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6" ' +
'	codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701" ' +
'	type="application/x-oleobject"> ' +
'	<param name="url" value="' + Player._files[Player.current_track - 1] + '"> ' +
'	<param name="volume" value="100"> ' +
'	<param name="autostart" value="false">' +
'</object>' +
'<SCRIPT FOR="sound" EVENT="playStateChange(NewState)">' +
'document.getElementById(\'sound\').parent.WindowsMediaPlayerStateChange(NewState)' +
'</SCRIPT>';
				break;
			
			case 'real':
				
				// http://www17.real.com/help/library/guides/extend/embed.htm
				Player.innerHTML = '<object><embed name="sound" id="sound" src="' + Player._files[Player.current_track - 1] + '" volume="100" controls="default" type="audio/x-pn-realaudio-plugin" autostart="true" height="60" scriptcallbacks="onPlayStateChange"></object>Real Player';
				
				break;
			
			case 'quicktime':
				
				Player.innerHTML = '<object><embed name="sound" id="sound" src="' + Player._files[Player.current_track - 1] + '" volume="100" enablejavascript="true" autostart="1" AUTOPLAY="true" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" ></embed></object>';
//				Player.innerHTML = '<OBJECT '
//+ 'CLASSID="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" '
//+ 'ID="sound" '
//+ 'CODEBASE="http://www.apple.com/qtactivex/qtplugin.cab">'
//+ '<PARAM name="SRC" VALUE="">'
//+ '<PARAM name="AUTOPLAY" VALUE="true">'
//+ '<PARAM name="CONTROLLER" VALUE="false">'
//+ '<PARAM name="VOLUME" VALUE="100">'
//+ '<PARAM name="ENABLEJAVASCRIPT" VALUE="true">'
//+ '<PARAM name="TYPE" VALUE="audio/wav">'
//+ '<embed classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"' 
//+ 'name="sound"'
//+ 'id="sound"' 
//+ 'src=""' 
//+ 'pluginspage="http://www.apple.com/quicktime/download/"'
//+ 'volume="100"' 
//+ 'enablejavascript="true" '
//+ 'type="audio/wav" '
//+ 'autostart="true"'
//+ '> </embed>'
//+ '</OBJECT>';
				break;
			
			case 'flash':
				
			    FlashMP3Player.onstatechange = function(new_state)
                {
	                new_state = Player.FPStates[new_state];
                    document.title = Player._states[new_state];
            		
	                // Detect if player needs to switch to a next song
	                if(new_state == 3)
	                {
		                Player.Next();
	                    Player.StateChanged(6, "FlashPlayerStateChange");
	                }
	                else
	                {
                        Player.StateChanged(new_state, "FlashPlayerStateChange");
                    }
                };
        	
                FlashMP3Player.onpositionchange = function(new_position)
                {
                    Player.position = Math.floor(Player.object.position / 1000);
            		
	                Player.PositionChanged(Player.position, "FlashPlayerPositionChange");
                };
        	    
                FlashMP3Player.oninitialize = function(obj)
                {
	                Player.StateChanged(6, "FlashPlayerInitialized");
                };
                
				FlashMP3Player.Initialize();
			    //FlashMP3Player.play(Player._files[Player.current_track - 1]);
				
//				Player.innerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="165" height="37" id="sound">'
//				+ '	 <param name=movie value="' + framework_location + '../Flash/NiftyMP3Player.swf?file=' + Player._files[Player.current_track - 1] + '&as=1">'
//				+ '	 <param name=quality value=high>'
//				+ '	 <param name=bgcolor value=#FFFFFF>'
//				+ '	 <embed src="' + framework_location + '../Flash/NiftyMP3Player.swf?file=' + Player._files[Player.current_track - 1] + '&as=1" name="sound" align="" type="application/x-shockwave-flash" swLiveConnect="true" pluginspage="http://www.macromedia.com/go/getflashplayer">'
//				+ '	</embed>'
//				+ '</object>';
				
				break;
			case 'html5':
				html5player.eventHandler = function(state)
				{
					//alert('State: '+state);
					new_state = Player.HTML5PStates[state];
                    document.title = Player._states[new_state];
                    
					switch(state)
					{
						case 1:
							if(Player.object.ended())
							{
								Player.Next();
								Player.StateChanged(6, "html5player.eventHandler");
							}
							else
							{
								Player.StateChanged(new_state, "html5player.eventHandler");
							}
							break;
						case 2:
							Player.StateChanged(new_state, "html5player.eventHandler");
							break;
						case 4:
							Player.Exception(Player.object.getErrorMessage(), 'html5player.eventHandler');
							Player.StateChanged(new_state, "html5player.eventHandler");
							break;
						default:
							Player.StateChanged(new_state, "html5player.eventHandler");
							break;
					}
				}
				
				Player.state = 6;
				break;
			default:
				Player.state = 7; // Error
				break;
		}
		
		if(Player.type == 'flash')
		{
			Player.object = FlashMP3Player;
			
			return true;
		}
		else if(Player.type == 'html5')
		{
			Player.object = html5player;
			
			return true;
		}
		else if(Player.type != 'other')
		{
			Player.object = document.getElementById('sound');
			
			if(Player.object && Player.type == 'windows_media') Player.object.parent = Player; // For Windows Media Player to call state changed function
			
			return true;
		}
		else
		{
			return false;
		}
	}
	
	Player.Initialize();
	
	// Arguments: String command, obj value
	Player.ControlWindowsMediaPlayer = function()
	{
		var _args = Player.ControlWindowsMediaPlayer.arguments;
		
		switch(_args[0])
		{
			case 'play':
				
				if(Player.object.url != Player._files[Player.current_track - 1])
				{
					Player.Initialize();
					
					Player.object.url = Player._files[Player.current_track - 1];
					
					Player.StateChanged(6, "ControlWindowsMediaPlayer"); // Buffering
				}
				
				Player.object.controls.play();
						
				return true;
					
				break;
			
			case 'stop':
				
				Player.object.controls.stop();
				Player.StateChanged(0, "ControlWindowsMediaPlayer") // Stoped
						
				return true;
				
				break;
			
			case 'pause':
				
				try
				{
					Player.object.controls.pause();
					Player.StateChanged(2, "ControlWindowsMediaPlayer") // Paused
				}
				catch(ex)
				{
					Player.Exception(ex, "-mute Player.ControlWindowsMediaPlayer");
					
					return false;
				}
				
				return true;
				
				break;
			
			case 'mute':
				
				if(typeof Player.object.settings.mute == 'boolean')
				{
					Player.object.settings.mute = _args[1];
				}
				else
				{
					return false;
				}
				
				return true;
				
				break;
			
			case 'volume':
				
				Player.object.settings.volume = _args[1];
						
				return true;
				
				break;
				
			case 'position':
				
				Player.object.controls.currentPosition = _args[1];
						
				return true;
				
				break;
				
			case 'state':
				
				// Position
				Player.length = Math.floor(Player.object.currentMedia.duration);
				
				var old_position = Player.position;
				Player.position = Math.floor(Player.object.controls.currentPosition);
				
				if(Player.position != old_position)
				{
					Player.PositionChanged(Player.position);
				}
				
				// State
				new_state = Player.WMPStates[Player.object.playState];
				
				// If buffering
				if(new_state == 6) Player.buffer = Player.object.network.bufferingProgress;
				
				if(Player.state == 6 && Player.buffer > 90) Player.Play();
				
				// Detect if it's time to play Next track (for vista, because in vista play state doesn't fire on Stop)
				if(Player.position >= Player.length && Player.length > 0 && (Player.state == 6 || Player.state == 1))
				{
					Player.Next();
				}
				
				break;
		}
		
		return false;
	}
	
	Player.WindowsMediaPlayerStateChange = function(new_state)
	{
		// Detect if player needs to switch to a next song (I use 15 seconds in advance because often song stops too early)
		if((new_state == 10 || new_state == 1) && (Player.state == 6 || Player.state == 1) && Player.length > 0 && Player.position > Player.length - 15 )
		{
			Player.Next();
		}
		
		Player.StateChanged(Player.WMPStates[new_state], "WindowsMediaPlayerStateChange");
	}
	
	// Arguments: String command, obj value
	Player.ControlRealPlayer = function()
	{
		var _args = Player.ControlRealPlayer.arguments;
		
		switch(_args[0])
		{
			case 'play':
				
				if(Player.object.src != Player._files[Player.current_track - 1])
				{
					Player.Initialize();
					
					Player.object.src = Player._files[Player.current_track - 1];
				}
				
				if(typeof Player.object.DoPlay == 'function' && Player.object.CanPlay())
				{
					try
					{
						Player.object.DoPlay();
						
						return true;
					}
					catch(ex)
					{
						
					}
				}
				
				break;
			
			case 'stop':
				
				if(typeof Player.object.DoStop == 'function')
				{
					try
					{
						Player.object.DoStop();
						
						Player.StateChanged(0, 'ControlRealPlayer'); // Stoped (this line is required so it doesn't go to next track when stoped manualy)
						Player.PositionChanged(0);
						
						return true;
					}
					catch(ex)
					{
						
					}
				}
				else
				{
					return true; // to make sure actions "next" and "previouse" work
				}
				
				break;
			
			case 'pause':
				
				if(typeof Player.object.DoPause == 'function' && Player.object.CanPause())
				{
					try
					{
						Player.object.DoPause();
						
						return true;
					}
					catch(ex)
					{
						window.status = 'Cannot Pause. Error Occured!';
					}
				}
				else
				{
					window.status = 'Cannot Pause';
				}
				
				break;
			
			case 'mute':
				
				if(typeof Player.object.SetMute == 'function')
				{
					try
					{
						Player.object.SetMute(_args[1]);
						
						return true;
					}
					catch(ex)
					{
						return false;
					}
				}
				else
				{
					return false;
				}
				
				break;
			
			case 'volume':
				
				if(typeof Player.object.SetVolume == 'function')
				{
					try
					{
						Player.object.SetVolume(_args[1]);
						
						return true;
					}
					catch(ex)
					{
						return false;
					}
				}
				
				break;
			
			case 'position':
				
				if(typeof Player.object.SetPosition == 'function')
				{
					try
					{
						Player.object.SetPosition(_args[1] * 1000);
						
						return true;
					}
					catch(ex)
					{
						return false;
					}
				}
				else
				{
					return false;
				}
				
				break;
				
			case 'state':
				
				var old_position = Player.position;
				var new_state = Player.state;
				var total_packets = 0;
				var received_packets = 0;
				
				try
				{
					// Position
					
					if(typeof Player.object.GetLength == 'function')
					{
						Player.length = Math.floor(Player.object.GetLength() / 1000);
					}
					
					if(typeof Player.object.GetPosition == 'function')
					{
						Player.position = Math.floor(Player.object.GetPosition() / 1000);
					}
					
					if(Player.position != old_position)
					{
						Player.PositionChanged(Player.position);
					}
					
					// Buffering
					
					if(typeof Player.object.GetPacketsTotal == 'function')
					{
						total_packets = Player.object.GetPacketsTotal();
					}
					
					if(typeof Player.object.GetPacketsReceived == 'function')
					{
						received_packets = Player.object.GetPacketsReceived();
					}
					
					if(total_packets > 0)
					{
						Player.buffer = Math.floor((received_packets / total_packets) * 100);
					}
					
					// State
					
					if(typeof Player.object.GetPlayState == 'function')
					{
						new_state = Player.RPStates[Player.object.GetPlayState()];
						
						// Check if player needs to play, because it doesnts start playing when src is changed
						if(Player.state == 6 || (Player.state == 1 && new_state == 0))
						{
							if(typeof Player.object.DoPlay == 'function' && Player.object.CanPlay())
							{
								Player.object.DoPlay();
								
								return true;
							}
						}
						
						// This is needed for backup in case Player.RealPlayerStateChange doesn't execute in older firefox or other browser
						if(Player.state != new_state)
						{
							Player.StateChanged(new_state, "RealPlayerStateChange");
						}
					}
					
					// Detect if it's time to play Next track (in case it's not detected in Player.RealPlayerStateChange)
					if(Player.position >= Player.length && Player.length > 0 && (Player.state == 6 || Player.state == 1))
					{
						Player.Next();
					}
				}
				catch(ex)
				{
					Player.Exception(ex, "-state Player.ControlRealPlayer");
				}
				
				break;
		}
		
		return false;
	}
	
	Player.RealPlayerStateChange = function(old_state, new_state)
	{
		new_state = Player.RPStates[new_state];
		old_state = Player.RPStates[old_state];
		
		//document.getElementById("st").value = new_state + '/' + Player.state + '/' + old_state;
		
		// Detect if player needs to switch to a next song
		if(new_state == 0 && (Player.state == 6 || Player.state == 1) && Player.length > 0)
		{
			Player.Next();
		}
		
		Player.StateChanged(new_state, "RealPlayerStateChange");

	}
	
	// this is just a variavle that real player calls like a function passing new and old states to it
	// so here I change this function to my custom function
	sound_OnPlayStateChange = Player.RealPlayerStateChange;
	
	// Arguments: String command, obj value
	Player.ControlQuicktimePlayer = function()
	{
		var _args = Player.ControlQuicktimePlayer.arguments;
		
		switch(_args[0])
		{
			case 'play':
				
				if(Player.object.src != Player._files[Player.current_track - 1])
				{
					Player.Initialize();
					
					if(typeof Player.object.SetURL == 'function')
					{
						Player.object.SetURL(Player._files[Player.current_track - 1]);
					}
					
					Player.object.src = Player._files[Player.current_track - 1];
					
					Player.StateChanged(6, "ControlQuicktimePlayer"); // Buffering
				}
				
				if(typeof Player.object.Play == 'function')
				{
					try
					{
						Player.object.Play();
						
						if(Player.position > 0) Player.position -= 1; // to prevent status to jump to paused and then back to play
						
						Player.StateChanged(1, "ControlQuicktimePlayer") // Playing
						
						return true;
					}
					catch(ex)
					{
						
					}
				}
				else
				{
					Player.StateChanged(6, "ControlQuicktimePlayer"); // Buffering
						
					return true;
				}
				
				break;
			
			case 'stop':
				try
				{
					Player.object.Stop();
					Player.object.SetTime(0);
					
					Player.StateChanged(0, "ControlQuicktimePlayer") // Stoped
						
					return true;
				}
				catch(ex)
				{
					return false;
				}
				
				break;
			
			case 'pause':
				try
				{
					Player.object.Stop();
					
					Player.StateChanged(2, "ControlQuicktimePlayer") // Stoped
					
					return true;
				}
				catch(ex)
				{
					return false;
				}
				
				break;
			
			case 'mute':
				
				if(typeof Player.object.SetMute == 'function')
				{
					try
					{
						Player.object.SetMute((_args[1] == true) ? 1 : 0);
						
						return true;
					}
					catch(ex)
					{
						return false;
					}
				}
				else
				{
					return false;
				}
				
				break;
			
			case 'volume':
				if(typeof Player.object.SetVolume == 'function')
				{
					try
					{
						Player.object.SetVolume(_args[1]);
						
						return true;
					}
					catch(ex)
					{
						return false;
					}
				}
				else
				{
					return false;
				}
				
				break;
			
			case 'position':
				Player.object.SetTime(_args[1] * Player.object.GetTimeScale());
						
				return true;
				break;
				
			case 'state':
				
				var new_position = 0;
				
				// Position
				try
				{
					var scale = Player.object.GetTimeScale();
					if(scale == 0) scale = 1; // prevent division by 0 by any chance
					Player.length = Math.floor(Player.object.GetDuration() / scale);
					new_position = Math.floor(Player.object.GetTime() / scale);
				}
				catch(ex)
				{
					Player.length = 0;
					Player.position = 0;
				}
				
				// State
				if(typeof Player.object.GetPluginStatus == 'function')
				{
					var player_status = "Buffering...";
					
					// catch error because sometimes error occures when calling this method
					try
					{
						var player_status = Player.object.GetPluginStatus();
					}
					catch(ex)
					{
						// do nothing
					}
					
					player_status = player_status.toLowerCase();
					var can_play = (player_status == 'playable' || player_status == 'complete');
					
					var new_state = Player.state;
					
					if(Player.state == 1 && !can_play)
					{
						new_state = 6; // Buffering
					}
					else if(can_play && Player.state == 6)
					{
						new_state = 1; // Playing
						Player.buffer = 100;
						
						if(typeof Player.object.Play == 'function')
						{
							try
							{
								Player.object.Play();
							}
							catch(ex)
							{
								window.status = ex.message;
							}
						}
					}
					else if(Player.state == 1 && Player.position == new_position) // Detect pause state by new and old position
					{
						//new_state = 2;
					}
					else if(Player.state == 2 && Player.position != new_position && Player.position > 0) // detect play state by new and old position
					{
						//new_state = 1;
					}
					else if(Player.state == 1 && Player.position == 0 && new_position == 0)
					{
						new_state = 0;
					}
				}
				else
				{
					//new_state = 7;
				}
				
				// Check if position changed
				if(Player.position != new_position)
				{
					Player.PositionChanged(new_position, "ControlQuicktimePlayer");
				}
				
				if(Player.state != new_state && new_state != undefined)
				{
					Player.StateChanged(new_state, "ControlQuicktimePlayer");
				}
				
				// Detect end of track
				if(Player.length > 0 && (Player.state == 6 || Player.state == 1) && Player.position >= Player.length - 5)
				{
					if(!player.changing_track)
					{
						setTimeout(Player.Next, 5000);
						
						player.changing_track = true;
					}
				}
				
				break;
		}
		
		return false;
	}
	
	// Arguments: String command, obj value
	Player.ControlFlashPlayer = function()
	{
		var _args = Player.ControlFlashPlayer.arguments;
	    
		switch(_args[0])
		{
			case 'play':
				
				if(Player.object.fileName != Player._files[Player.current_track - 1])
				{
					Player.object.loadFile(Player._files[Player.current_track - 1]);
				}
				
				Player.object.play();
				
				break;
			case 'stop':
				Player.object.stop();
				break;
			case 'pause':
				Player.object.pause();
				break;
			case 'mute':
				Player.object.mute(_args[1]);
				break;
			case 'volume':
				Player.object.setVolume(_args[1]);
				break;
			case 'position':
				Player.object.setPosition(_args[1]);
				break;
			case 'state':
				Player.length = Math.floor(Player.object.duration / 1000);
				break;
		}
		
		return true;
	}
	
	// Arguments: String command, obj value
	Player.ControlHTML5Player = function()
	{
		try
		{
			var _args = Player.ControlHTML5Player.arguments;
		    
			switch(_args[0])
			{
				case 'play':
					if(Player.object.src() != Player._files[Player.current_track - 1])
					{
						Player.object.play(Player._files[Player.current_track - 1]);
					}
					else
					{
						Player.object.play();
					}
					
					break;
				case 'stop':
					Player.object.stop();
					break;
				case 'pause':
					Player.object.pause();
					break;
				case 'mute':
					Player.object.muted(_args[1]);
					break;
				case 'volume':
					Player.object.setVolume(_args[1]);
					break;
				case 'position':
					Player.object.setPosition(_args[1]);
					break;
				case 'state':
					Player.length = Math.round(Player.object.duration());
					Player.position = Math.round(Player.object.position());
					break;
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "Player.ControlHTML5Player");
		}
		
		return true;
	}
	
	// Parameters: int TrackNumber
	Player.Play = function() 
	{
		//alert('playing...');
		if(Player.state == 7 || Player.object == null) return false;
		
		var _args = Player.Play.arguments;
		
		//alert(_args);
		var result = false;
		try
		{
			var new_track = (_args.length > 0);
			new_track = (new_track && _args[0] != Player.current_track);
			
			if(new_track) // If different track than just loaded
			{
				if(Player.state != 0) Player.Stop();
				Player.PositionChanged(0);
				Player.current_track = _args[0];
				
				switch(Player.type)
				{
					case 'windows_media':
						result = Player.ControlWindowsMediaPlayer('play', _args[0]);
						break;
					
					case 'real':
						result = Player.ControlRealPlayer('play', _args[0]);
						break;
					
					case 'quicktime':
						result = Player.ControlQuicktimePlayer('play', _args[0]);
						break;
					
					case 'flash':
						result = Player.ControlFlashPlayer('play', _args[0]);
						break;
					
					case 'html5':
						result = Player.ControlHTML5Player('play', _args[0]);
						break;
				}
				
				if(result)
				{
					Player.buffer = 0;
				}
			}
			else
			{
				switch(Player.type)
				{
					case 'windows_media':
						result = Player.ControlWindowsMediaPlayer('play');
						break;
					
					case 'real':
						result = Player.ControlRealPlayer('play');
						break;
					
					case 'quicktime':
						result = Player.ControlQuicktimePlayer('play');
						break;
					
					case 'flash':
						result = Player.ControlFlashPlayer('play');
						break;
					
					case 'html5':
						result = Player.ControlHTML5Player('play');
						break;
				}
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "Play");
		}
		
		return result;
	}
	
	Player.Stop = function()
	{
		if(Player.state == 7 || Player.object == null) return false;
		
		var result = true;
		
		try
		{
			switch(Player.type)
			{
				case 'windows_media':
					result = Player.ControlWindowsMediaPlayer('stop');
					break;
				
				case 'real':
					result = Player.ControlRealPlayer('stop');
					break;
				
				case 'quicktime':
					result = Player.ControlQuicktimePlayer('stop');
					break;
				
				case 'flash':
					result = Player.ControlFlashPlayer('stop');
					break;
				
				case 'html5':
					result = Player.ControlHTML5Player('stop');
					break;
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "Stop");
		}
		
		if(result)
		{
			Player.PositionChanged(0);
		}
		
		return result;
	}
	
	Player.Pause = function()
	{
		if(Player.state == 7 || Player.object == null) return false;
		
		var result = false;
		
		if(Player.state == 1 || Player.state == 3 || Player.state == 4 || Player.state == 6)
		{
			try
			{
				switch(Player.type)
				{
					case 'windows_media':
						result = Player.ControlWindowsMediaPlayer('pause');
						break;
					
					case 'real':
						result = Player.ControlRealPlayer('pause');
						break;
					
					case 'quicktime':
						result = Player.ControlQuicktimePlayer('pause');
						break;
					
					case 'flash':
						result = Player.ControlFlashPlayer('pause');
						break;
					
					case 'html5':
						result = Player.ControlHTML5Player('pause');
						break;
				}
			}
			catch(ex)
			{
				Player.Exception(ex, "Pause");
			}
		}
		
		return result;
	}
	
	Player.Next = function()
	{
		Player.changing_track = false;
		
		if(Player.state == 7 || Player.object == null || Player._files.length == 0) return false;
		
		var new_track = 1;
		
		// Check if there are more songs in playlist
		if(Player._files.length > Player.current_track)
		{
			new_track = Player.current_track + 1; // Next Track
		}
		else
		{
			new_track = 1; // First Track
		}
		
		var result = true;
		
		// Stop Player if not stopped
		if(Player.state > 0)
		{
			result = Player.Stop();
		}
		// Play next track if everything is still OK
		if(result)
		{
			Player.Play(new_track);
		}
		
		return result;
	}
	
	Player.Previous = function()
	{
		Player.changing_track = false;
		
		if(Player.state == 7 || Player.object == null) return false;
		
		if(Player._files.length == 0) return false;
		
		// Check if there are more songs in playlist
		if(Player.current_track > 1)
		{
			Player.current_track -= 1; // Previous  Track
		}
		else
		{
			Player.current_track = Player._files.length; // Last Track
		}
		
		var result = true;
		
		// Stop Player if not stopped

		if(Player.state > 0 && Player.state < 7)
		{
			result = Player.Stop();
		}
		
		// Play previous track if everything is still OK
		if(result)
		{
			Player.Play();
		}
		
		return result;
	}
	
	Player.SetVolume = function(percentage)
	{
		Player.volume = (percentage > 100 || percentage < 0) ? 100 : percentage;
		
		var result = false;
		
		try
		{
			switch(Player.type)
			{
				case 'windows_media':
					result = Player.ControlWindowsMediaPlayer('volume', Player.volume);
					break;
				
				case 'real':
					result = Player.ControlRealPlayer('volume', Player.volume);
					break;
				
				case 'quicktime':
					result = Player.ControlQuicktimePlayer('volume', Player.volume);
					break;
				
				case 'flash':
					result = Player.ControlFlashPlayer('volume', Player.volume);
					break;
				
				case 'html5':
					result = Player.ControlHTML5Player('volume', Player.volume);
					break;
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "Volume");
		}
		
		return result;
	}
	
	Player.Mute = function(really)
	{
		Player.mute = really;
		
		var result = false;
		
		try
		{
			switch(Player.type)
			{
				case 'windows_media':
					result = Player.ControlWindowsMediaPlayer('mute', Player.mute);
					break;
				
				case 'real':
					result = Player.ControlRealPlayer('mute', Player.mute);
					break;
				
				case 'quicktime':
					result = Player.ControlQuicktimePlayer('mute', Player.mute);
					break;
				
				case 'flash':
					result = Player.ControlFlashPlayer('mute', Player.mute);
					break;
				
				case 'html5':
					result = Player.ControlHTML5Player('mute', Player.mute);
					break;
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "Mute");
		}
		
		return result;
	}
	
	Player.SetPosition = function(percentage)
	{
		if(parseInt(percentage) < 0 || parseInt(percentage) > 100 || Player.length == 0) return false;
		
		var position = Math.floor((Player.length / 100) * parseInt(percentage));
		
		var result = false;
		
		try
		{
			switch(Player.type)
			{
				case 'windows_media':
					result = Player.ControlWindowsMediaPlayer('position', position);
					break;
						
				case 'real':
					
					result = Player.ControlRealPlayer('position', position);
					break;
				
				case 'quicktime':
					result = Player.ControlQuicktimePlayer('position', position);
					break;
				
				case 'flash':
					result = Player.ControlFlashPlayer('position', position);
					break;
				
				case 'html5':
					result = Player.ControlHTML5Player('position', position);
					break;
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "SetPosition");
		}
		
		if(result) Player.PositionChanged(position);
		
		return result;
	}
	
	Player.CheckState = function()
	{
		try
		{
			switch(Player.type)
			{
				case 'windows_media':
					result = Player.ControlWindowsMediaPlayer('state');
					break;
				
				case 'real':
					result = Player.ControlRealPlayer('state');
					break;
				
				case 'quicktime':
					result = Player.ControlQuicktimePlayer('state');
					break;
				
				case 'flash':
					result = Player.ControlFlashPlayer('state');
					break;
				
				case 'html5':
					result = Player.ControlHTML5Player('state');
					break;
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "CheckState");
		}
		// DEBUGER
		//window.status = result;
		//window.status = Player._states[Player.state] + ': ' + Player.state + ", Position: " + Player.position + ", Date: " + new Date();
	}
	
	if(Player.object != null) Player.timer_state_check = setInterval(Player.CheckState, 1000);
	
	Player.LoadPlaylist = function(url)
	{
		
	}
	
	Player.StateChanged = function(state, function_name)
	{
		Player.state = state;
		
		// handle the on state change event
		try
		{
			if(Player.onstatechange != null)
			{
				eval(Player.onstatechange);
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "StateChanged");
		}
		
		//window.status = function_name + ' Reported: ' + Player._states[Player.state] + ': ' + Player.state + ", Position: " + Player.position;
	}
	
	Player.PositionChanged = function(position)
	{
		Player.position = (isNaN(position)) ? 0 : position;
		
		// handle the on position change event
		try
		{
			if(Player.onstatechange != null)
			{
				eval(Player.onpositionchange);
			}
		}
		catch(ex)
		{
			Player.Exception(ex, "PositionChanged");
		}
	}
	
	Player.Exception = function(exeption, function_name)
	{
		var message = "ERROR: [" + exeption + "] in function: " + function_name + "()";
		
		alert(message);
		window.status = message;
	}
	
	return Player;
};


// JavaScript Document
VitaminXP.Namespace("VitaminXP.Array");

// This class extends Array class adding following functions to it

// Adds an element to array
// Optional Parameter [key] (ex: array[key] = value (if omited array.push(value) id used)
Array.prototype.Add = function(value)
{
	var _args = Array.prototype.Add.arguments
	var key = (_args.length > 1) ? _args[1] : null;
	
	if(key == null)
	{
		this.push(value);
	}
	else
	{
		this["'" + key + "'"] = value;
	}
}

// Removes all elements which values are same as passed as Value
// Optional Parameter [Limit] decides how many elements will be deleted. 0 = No limit
Array.prototype.Remove = function(value)
{
	var _args = Array.prototype.Remove.arguments
	var limit = (_args.length > 1) ? _args[1] : 0;
	var count = 0;
	
	for(i = 0; i < this.length; i++)
	{
		if(this[i] == value)
		{
			this.splice(i, 1)
			i--;
			count++;
			
			if(count >= limit && limit != 0)
			{
				i = this.length;
			}
		}
	}
}

Array.prototype.Max = function()
{
	var max = undefined;
	
	for(i = 0; i < this.length; i++)
	{
		if(this[i] > max || max == undefined) max = this[i];
	}
	return max;
}

Array.prototype.Min = function()
{
	var min = undefined;
	
	for(i = 0; i < this.length; i++)
	{
		if(this[i] < min || min == undefined) min = this[i];
	}
	
	return min;
}

Array.prototype.HasElement = function(el)
{
	for(i = 0; i < this.length; i++) if(this[i] == el) return true;
	return false;
}

// JavaScript Document
VitaminXP.Namespace("VitaminXP.Cookie");

VitaminXP.Cookie.Get = function(name)
{
	var _cookies = document.cookie.split(";");
    
    for(var i = 0; i < _cookies.length; i++)
    {
        if(_cookies[i].substring(0, 1) == " ") _cookies[i] = _cookies[i].substring(1);
        if(_cookies[i].substring(0, name.length + 1) == name + "=") return unescape(_cookies[i].substring(name.length + 1));
    }
    
    return undefined;
}

VitaminXP.Cookie.Set = function(name, value)
{
    try
    {
		var _args = VitaminXP.Cookie.Set.arguments;
		var daysToExpire = (_args.length > 2) ? _args[2] : 365;
		var path = (_args.length > 3) ? _args[3] : "/";
		var domain = (_args.length > 4) ? _args[4] : null;
		var secure = (_args.length > 5) ? _args[5] : false;
		
		var date = new Date();
		date.setTime(date.getTime() + (daysToExpire * 24 * 60 * 60 * 1000));
		
		var cookie = name + "=" + escape(value) + ";expires=" + date.toString() + "; path=" + path + ";";
		
		if(domain != null) cookie += " domain=" + domain + ";";
		if(secure) cookie += " secure=" + secure + ";";
		
        document.cookie = cookie;
    }
    catch(err){ return false;}
    
    return true;
}

// Create NameSpaces
VitaminXP.Namespace("VitaminXP.DataSet");

VitaminXP.DataSet = function()
{
	this.tables = {};
	this.tables.count = 0;
	
	this.AddTable = function(name)
	{
		
	}
}

// JavaScript Document
VitaminXP.Namespace("VitaminXP.DateTime");

VitaminXP.DateTime.GetTimezoneOffset = function()
{
	var tz = getStandardTimezoneOffset() / 60;
	var sign = (tz < 0) ? '-' : '+';
	var tz = Math.abs(tz);
	var hours = parseInt(tz);
	var minutes = tz - hours;
	if(hours < 10) hours = '0' + hours;
	if(minutes < 10) minutes = '0' + minutes;
	
	return sign + hours + ':' + minutes;
}

// converts integer seconds to string time (0:0:12:59) - days, hours, minutes,seconds
VitaminXP.DateTime.SecondsToTime = function(seconds)
{
	var sign = (seconds >= 0) ? '' : '-';
	seconds = Math.abs(seconds);
	
	var minutes = Math.floor(seconds / 60);
	seconds = seconds % 60;
	
	var hours = Math.floor(minutes / 60);
	minutes = minutes % 60;
	
	var days = Math.floor(hours / 24);
	hours = hours % 24;
	
	// generate time string
	if(seconds < 10) seconds = "0" + seconds;
	minutes = (hours > 0 && minutes < 10) ? "0" + minutes + ":" : minutes + ":";
	hours = (hours > 0) ? ((days > 0 && hours < 10) ? "0" + hours + ":" : hours + ":") : "";
	days = (days > 0) ? days + ":" : "";
	
	return days + hours + minutes + seconds;
}

// JavaScript Document
VitaminXP.Namespace("VitaminXP.Directory");

VitaminXP.Directory.Domain = function(){return document.domain;}



// Create NameSpaces
VitaminXP.Namespace("VitaminXP.Effect");


VitaminXP.Effect.Fade = function(obj, from, to, seconds){
	this.element = obj
	this.from = from
	this.to = to
	this.current = from
	this.seconds = seconds
	this.step = Math.abs(from - to) / (seconds / (1 / VitaminXP.Timeline.FramesPerSecond))
	
	// Methods
	VitaminXP.Timeline.AddScene(this);
	
	VitaminXP.Effect.SetOpacity(this.element, this.current);
	if(document.getElementById(this.element).style.display == 'none') document.getElementById(this.element).style.display = '';
	
	this.ExecuteFrame = function(){
		if(this.current != to && document.getElementById(this.element).style.display != 'none'){
			this.current += (to > from)? this.step : this.step * -1;
			if(this.current > 100) this.current = 100;
			if(this.current < 0) this.current = 0;
			
			VitaminXP.Effect.SetOpacity(this.element, this.current);
			
		}else{
			this.Stop();
		}
	}
	
	this.Stop = function(){
		VitaminXP.Timeline.RemoveScene(this);
	}
};

VitaminXP.Effect.FadeIn = function(obj, seconds){
	return new VitaminXP.Effect.Fade(obj, 0, 100, seconds);
};

VitaminXP.Effect.FadeOut = function(obj, seconds){
	return new VitaminXP.Effect.Fade(obj, 100, 0, seconds);
};

VitaminXP.Effect.Show = function(id){
	if(document.getElementById(id).style.visibility.toLowerCase() == 'hidden') document.getElementById(id).style.visibility = 'visible';
	document.getElementById(id).style.display = '';
};

VitaminXP.Effect.Hide = function(id){
	document.getElementById(id).style.display = 'none';
};

VitaminXP.Effect.SetOpacity = function(obj, val){
	this.element = document.getElementById(obj)
	
	if (Browser == "Internet Explorer" && typeof this.element.style.filter == 'string') {
		this.element.style.filter = 'alpha(opacity='+val+')'
		if (!this.element.currentStyle || !this.element.currentStyle.hasLayout) {
			obj.style.zoom = 1; // when no layout or cant tell
		}
	}else{
		this.element.style.opacity = val/100;
		this.element.style['-moz-opacity'] = val/100;
		this.element.style['-khtml-opacity'] = val/100;
	}
};

VitaminXP.Effect.GetOpacity = function(obj){
	this.element = document.getElementById(obj);
	
	if(Browser == "Internet Explorer" && typeof this.element.style.filter == 'string'){
		filter = this.element.style.filter
		filter = filter.replace("alpha(","")
		filter = filter.replace(")","")
		
		filters = str2arr(filter,",")
		
		opacity = filters['opacity']
		opacity = (opacity == undefined)? 100 : opacity
	}else{
		try{
			opacity = this.element.style.MozOpacity * 100;
		}catch(ex){
			try{
				opacity = this.element.style.KhtmlOpacity * 100;
			}catch(ex){
				try{
					opacity = this.element.style.opacity * 100;
				}catch(ex){
					opacity = 100
				}
			}
		}
	}
	
	return Math.round(parseFloat(opacity))
};

// Change of property value from Slow to Fast (Slow->Fast)
VitaminXP.Effect.EasyOut = function(obj, property, from, to, seconds)
{
	this.element = document.getElementById(obj);
	this.property = property;
	this._value = new Array(); // Value for each frame this.value[i] = int
	this.percentage_completed = 0;
	this.seconds = seconds;
	this.frames = this.seconds / (1 / VitaminXP.Timeline.FramesPerSecond);
	this.frame = 0;
	this.from = from;
	this.to = to;
	this.average_acceleration = ((this.to - this.from) * 2) / Math.pow(this.frames, 2);;
	this.initial_acceleration = this.average_acceleration * 1;
	this.final_acceleration = 0;
	this.current_acceleration = 0;
	
	// Methods
	VitaminXP.Timeline.AddScene(this);
	
	// Calculate values for each frame
	for(i = 1; i <= this.frames; i++)
	{
		this.percentage_completed = (i / this.frames) * 100;
		this.current_acceleration = ((this.initial_acceleration - this.final_acceleration) / 100) * this.percentage_completed;
		this._value[i] = ((0.5 * this.current_acceleration) * Math.pow(i, 2)); // Displacement
	}
	
	// Execute Frame
	this.ExecuteFrame = function()
	{
		this.frame++;
		
		document.getElementById('cube2').style.left = this._value[this.frame] + 'px';
		
		if(this.frame >= this.frames)
		{
			this.Stop();
		}
	}
	
	this.Stop = function(){
		VitaminXP.Timeline.RemoveScene(this);
	}
}

// Change of property value from Fast to Slow (Fast->Slow)
VitaminXP.Effect.EasyIn = function(obj, property, from, to, seconds)
{
	this.element = document.getElementById(obj);
	this.property = property;
	this._value = new Array(); // Value for each frame this.value[i] = int
	this.percentage_completed = 0;
	this.seconds = seconds;
	this.frames = this.seconds / (1 / VitaminXP.Timeline.FramesPerSecond);
	this.frame = 0;
	this.from = from;
	this.to = to;
	//this.average_acceleration = ((this.to - this.from) * 2) / Math.pow(this.frames, 2);
	//this.initial_acceleration = 0;
	//this.final_acceleration = this.average_acceleration * 1;
	this.current_acceleration = ((this.to - this.from) * 2) / Math.pow(this.frames, 2);
	
	// Methods
	VitaminXP.Timeline.AddScene(this);
	
	// Calculate values for each frame
	for(i = 1; i <= this.frames; i++)
	{
		//this.percentage_completed = (i / this.frames) * 100;
		//this.current_acceleration = ((this.initial_acceleration - this.final_acceleration) / 100) * this.percentage_completed;
		this._value[this.frames - i] =  (this.to - this.from) - ((0.5 * this.current_acceleration) * Math.pow(i, 2)); // Displacement
	}
	
	// Execute Frame
	this.ExecuteFrame = function()
	{
		this.frame++;
		
		document.getElementById('cube2').style.left = this._value[this.frame] + 'px';
		
		if(this.frame >= this.frames)
		{
			this.Stop();
		}
	}
	
	this.Stop = function(){
		VitaminXP.Timeline.RemoveScene(this);
	}
}

// JavaScript Document
VitaminXP.Import("VitaminXP.Event");

VitaminXP.Namespace("VitaminXP.Element");
VitaminXP.Namespace("Element.Style");
VitaminXP.Namespace("VitaminXP.Select"); // This namespace is not to be used. Only to copy it's methods to every Select element on page load
VitaminXP.Namespace("VitaminXP.TextArea");
VitaminXP.Namespace("VitaminXP.Form");

VitaminXP.Element.property_cache = {}; // to cache case conversion for set/getStyle

VitaminXP.Element.patterns = { // cached for performance
	noNegatives:      /width|height|opacity|padding/i, // keep at zero or above
	offsetAttribute:  /^((width|height)|(top|left))$/, // use offsetValue as default
	defaultUnit:      /width|height|top$|bottom$|left$|right$/i, // use 'px' by default
	offsetUnit:       /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i, // IE may return these, so convert these to offset
	simpleAttribute:      /scrollTop|scrollLeft|/i // simple attribute (ex: element.scrollTop)
};

// improve performance by only looking up once
VitaminXP.Element.cacheConvertedProperties = function(property)
{
	VitaminXP.Element.property_cache[property] = {
		camel: VitaminXP.Element.toCamel(property),
		hyphen: VitaminXP.Element.toHyphen(property)
	};
};

// Converts style attribute from padding-left to paddingLeft
VitaminXP.Element.toCamel = function(property)
{
	if(VitaminXP.Element.property_cache[property])
	{
		return VitaminXP.Element.property_cache[property]['camel'];
	}
	
	var convert = function(prop) {
		var test = /(-[a-z])/i.exec(prop);
		return prop.replace(RegExp.$1, RegExp.$1.substr(1).toUpperCase());
	};
	
	while(property.indexOf('-') > -1) {
		property = convert(property);
	}
	
	// cache converted property names
	VitaminXP.Element.property_cache[property] = {
		camel: property,
		hyphen: VitaminXP.Element.toHyphen(property)
	};
	
	return property;
	//return property.replace(/-([a-z])/gi, function(m0, m1) {return m1.toUpperCase()}) // cant use function as 2nd arg yet due to safari bug
};

// Converts style attribute from paddingLeft to padding-left
VitaminXP.Element.toHyphen = function(property)
{
	if (property.indexOf('-') > -1) // assume hyphen
	{
		return property;
	}
	
	var converted = '';
	for (var i = 0, len = property.length;i < len; ++i)
	{
		if (property.charAt(i) == property.charAt(i).toUpperCase())
		{
			converted = converted + '-' + property.charAt(i).toLowerCase();
		}
		else
		{
			converted = converted + property.charAt(i);
		}
	}
	
	return converted;
	//return property.replace(/([a-z])([A-Z]+)/g, function(m0, m1, m2) {return (m1 + '-' + m2.toLowerCase())});
};

if (document.defaultView && document.defaultView.getComputedStyle) // W3C DOM method
{
	VitaminXP.Element.GetStyle = function(el, property)
	{
		el = VitaminXP.Element.Get(el);
		var value = null;
		
		if (property == 'float') // fix reserved word
		{
			property = 'cssFloat';
		}

		var computed = document.defaultView.getComputedStyle(el, '');
		
		if (computed) // test computed before touching for safari
		{
			value = computed[VitaminXP.Element.toCamel(property)];
		}
		
		value = el.style[property] || value;
		
		if(property == 'opacity') value = value * 100;
		
		return value;
	};
}
else if (document.documentElement.currentStyle && Browser == "Internet Explorer") // IE method
{
	VitaminXP.Element.GetStyle = function(el, property)
	{
		el = VitaminXP.Element.Get(el);
		
		switch( VitaminXP.Element.toCamel(property))
		{
			case 'opacity' :// IE opacity uses filter
				var val = 100;
				try
				{ // will error if no DXImageTransform
					val = el.filters['DXImageTransform.Microsoft.Alpha'].opacity;

				}
				catch(e)
				{
					try
					{ // make sure its in the document
						val = el.filters('alpha').opacity;
					}
					catch(e)
					{}
				}
				return parseInt(val);
			case 'float': // fix reserved word
				property = 'styleFloat'; // fall through
			default: 
				// test currentStyle before touching
				var value = el.currentStyle ? el.currentStyle[property] : null;
				value = ( el.style[property] || value );
				
				return value;
		};
	};
}
else // default to inline only
{
	VitaminXP.Element.GetStyle = function(el, property)
	{
		el = VitaminXP.Element.Get(el);
		
		var value = el.style[property];
		
		if(property == 'opacity') value = value * 100;
		
		return value;
	};
}

VitaminXP.Element.GetAttribute = function(el, attr)
{
	el = VitaminXP.Element.Get(el);
	
	if(VitaminXP.Element.patterns.simpleAttribute.exec(attr) != '')
	{
		val = parseFloat(el[attr]);
		if(val == NaN) val = 0;
		
		return val;
	}
	
	var val = VitaminXP.Element.GetStyle(el, attr);
	
	if(val !== 'auto' && !VitaminXP.Element.patterns.offsetUnit.test(val))
	{
		return parseFloat(val);
	}
	
	var a = VitaminXP.Element.patterns.offsetAttribute.exec(attr) || [];
	var pos = !!( a[3] ); // top or left
	var box = !!( a[2] ); // width or height
	
	// use offsets for width/height and abs pos top/left
	if( box || (VitaminXP.Element.GetStyle(el, 'position') == 'absolute' && pos))
	{
		val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
	}
	else
	{ // default to zero for other 'auto'
		val = 0;
	}
	
	return val;
}

// Sets any style to any element
VitaminXP.Element.SetStyle = function(el, property, val)
{
	el = VitaminXP.Element.Get(el);
	
	if(VitaminXP.Element.patterns.simpleAttribute.exec(property) != '')
	{
		el[property] = val;
	}
	
	var camel = VitaminXP.Element.toCamel(property);
	
	try
	{
		switch(property)
		{
			case 'opacity' :
				if (Browser == "Internet Explorer" && typeof el.style.filter == 'string') { // in case not appended
					el.style.filter = 'alpha(opacity=' + val + ')';
					
					if (!el.currentStyle || !el.currentStyle.hasLayout) {
						el.style.zoom = 1; // when no layout or cant tell
					}
				} else {
						el.style.opacity = val/100;
						el.style['-moz-opacity'] = val/100;
						el.style['-khtml-opacity'] = val/100;
				}
				break;
			default :
				if(VitaminXP.Element.patterns.defaultUnit.exec(camel) != null)
				{
					el.style[camel] = (typeof val == 'number') ? val+'px' : (val.indexOf('px') == -1 ? val+'px' : val);
				}
				else
				{
					el.style[camel] = val;
				}
				break;
		}
	}
	catch(ex)
	{
		VitaminXP.Exception(ex, 'VitaminXP.Element.SetStyle');
	}
}

VitaminXP.Element.Style.HasStyle = function(style_name)
{
	style_name = VitaminXP.Element.toCamel(style_name);
	
	for(style in this.style)
	{
		if(style.toString() == style_name) has = true;
		return true;
	}
	
	return false;
}

// Returns a reference to an ellement passed. Either ID of element or reference to element can be passed
VitaminXP.Element.Get = function(el)
{
	if (!el || el.tagName || el.item || (typeof el == 'object')) // null, HTMLElement, or HTMLCollection
	{
		return el;
	}
	
	if (typeof el == 'string') // HTMLElement or null
	{
		return document.getElementById(el);
	}
	
	if (el.splice) // Array of HTMLElements/IDs
	{
		var c = [];
		for (var i = 0, len = el.length; i < len; ++i)
		{
			c[c.length] = VitaminXP.Element.Get(el[i]);
		}
		
		return c;
	}
	
	return el; // some other object, just pass it back
}

VitaminXP.Element.GetParent = function(el)
{
	try
	{
	if(typeof el.parentElement == 'object')
	{
		return el.parentElement;
	}
	else
	{
		return el.parentNode;
	}
	}
	catch(ex)
	{
		VitaminXP.Exception(ex, "VitaminXP.Element.GetParent");
	}
	
	return false;
}

VitaminXP.Element.GetChildren = function(el)
{
	var children = new Array();
	var _children = new Array();
	
	if(el.childNodes)
	{
		children = el.childNodes
	}
	else if(el.children)
	{
		children = el.children;
	}
	
	if(typeof children.length == 'number')
	{
		for(child in children)
		{
			_children.Add(child);
		}
	}
	else
	{
		_children = new Array(children);
	}
	
	return _children;
}

// Retruns Left position of the element on the page
VitaminXP.Element.offsetX = function(elm)
{
	var mOffsetLeft = elm.offsetLeft;
	var mOffsetParent = elm.offsetParent;

	while(mOffsetParent){
		mOffsetLeft += mOffsetParent.offsetLeft;
		mOffsetParent = mOffsetParent.offsetParent;
	}

	return mOffsetLeft;
}

// Returns Top position of element on the page
VitaminXP.Element.offsetY = function(elm)
{
	var mOffsetTop = elm.offsetTop;
	var mOffsetParent = elm.offsetParent;

	while (mOffsetParent)
	{
		mOffsetTop += mOffsetParent.offsetTop;
		mOffsetParent = mOffsetParent.offsetParent;
	}
	return mOffsetTop;
}

VitaminXP.Element.AddEvent = function(obj, eventType, func, useEventCapture)
{
	VitaminXP.Event.AddHandler(obj, eventType, func, useEventCapture);
}

VitaminXP.Element.RemoveEvent = function(obj, eventType, func, useEventCapture)
{
	VitaminXP.Event.RemoveHandler(obj, eventType, func, useEventCapture);
}

VitaminXP.Element.GetScreenX = function(e)
{
    return VitaminXP.Event.ScreenX(e);
}

VitaminXP.Element.GetScreenY = function(e)
{
    return VitaminXP.Event.ScreenY(e);
}

VitaminXP.Element.GetScrollDeltaFromEvent = function(e)
{
    return VitaminXP.Event.ScrollDelta(e);
}

VitaminXP.Element.BlockEvent = function(e)
{
    VitaminXP.Event.Block(e);
}

// Returns a random string valid to be an ID of element
VitaminXP.Element.RandomID = function()
{
	var ID = Math.random();
	ID = "ID" + ID;
	ID.replace(".", "");
	
	return ID;
}

// Returns a length of properties of object. (does not count methods, only properties)
Object.prototype.properties = function()
{
	var count = 0;
	
	for(attr in this)
	{
		if(typeof(this[attr]) != "function")
		{
			count++;
		}
	}
	
	return count;
}

// Adds an Ooption to the end of Select element
VitaminXP.Select.AddElement = function(text, value)
{
	var _args = this.AddElement.arguments;
	var opt = new Option(text, value);
	
	(Browser == "Internet Explorer")? this.add(opt) : this.add(opt, null);
	
	// only IE version works everywhere, but I think it would be faster in big loops
	if(_args.length > 2) (Browser == "Internet Explorer")? this.options[this.options.length - 1].selected = _args[2] : opt.selected = _args[2];
}

// Removes all Option elements from Select element
VitaminXP.Select.ClearElements = function(el)
{
	while(el.length > 0)
	{
		el.remove(0);
	}
}

// Returns an array of elements found by [element_name] in a form (frm)
VitaminXP.Form.GetElements = function(frm, element_name)
{
	var _els = frm.elements[element_name];
	
	// Fix Browsers problem
	if(typeof(_els) == undefined) // if no elements
	{
		return new Array();
	}
	else if(_els.length == undefined) // if one element
	{
		return new Array(_els);
	}
	else
	{
		var _arr = new Array();
		
		for(i = 0; i < _els.length; i++)
		{
			_arr.push(_els[i]);
		}
		
		return _arr;
	}
}

//Returns an array of only checked elements found by [element_name] in [form]
VitaminXP.Form.GetCheckedElements = function(frm, element_name)
{
	var _els = VitaminXP.Form.GetElements(frm, element_name);
	
	for(i = 0; i < _els.length; i++)
	{
		if(!_els[i].checked)
		{
			_els.splice(i, 1);
			i--;
		}
	}

	return _els;
}

// Returns a string array of IDs of check boxes or radio boxes that have name [element_name]
VitaminXP.Form.GetCheckedElementIDs = function(element_name)
{
	var _ids = new Array();
	var _els = this.GetCheckedElements(element_name);
	
	for(i = 0; i < _els.length; i++)
	{
		_ids.push(_els[i].id);
	}

	return _ids;
}

// Finds and checks all checkboxes that have same name as passed
VitaminXP.Form.SelectAll = function(element_name, bool)
{
	var _els = this.GetElements(element_name);
	
	for(i = 0; i < _els.length; i++)
	{
		_els[i].checked = bool;
	}

	return _els;
}

// Finds radio boxed that have same name as passe, and returns a value of the one that is checked.
// If no boxes are checked, [undefined] is returned.
VitaminXP.Form.GetRadioValue = function(frm, element_name)
{
    for(var i = 0; i < frm.elements[element_name].length; i++)
	{
		if(frm.elements[element_name][i].checked)
		{
			return frm.elements[element_name][i].value;
		}
	}
	
	return undefined;
}

// Finds all radio input boxes that have passed name, and checks the one that has same value as passed
VitaminXP.Form.SetRadioValue = function(frm, element_name, value)
 {
    var _els = VitaminXP.Form.GetElements(frm, element_name);
    
    for(i = 0; i < _els.length; i++)
    {
        if(_els[i].value == value)
        {
            _els[i].checked = true;
            return true
        }
    }
   
   return false
}

// If vertical scroll is more than 0 zero, it will make the textarea taller untill vertical scroll is 0 zero
VitaminXP.TextArea.ExpendHeight = function(el)
{
	var _args = VitaminXP.TextArea.ExpendHeight.arguments
	var max_height = (_args.length > 1)? parseFloat(_args[1]) : 0
	
	if(el.scrollHeight > el.offsetHeight)
	{
		if(max_height == 0 || el.offsetHeight < max_height)
		{
			el.rows = parseInt(el.rows) + 1;
			
			VitaminXP.TextArea.ExpendHeight(el, max_height);
		}
	}
}

// If horisontal scroll is more than 0 zero, it will make the textarea wider untill horisontal scroll is 0 zero
VitaminXP.TextArea.ExpendWidth = function(el)
{
	var _args = VitaminXP.TextArea.ExpendHeight.arguments
	var max_width = (_args.length > 1)? parseFloat(_args[1]) : 0
	
	if(el.scrollWidth > el.offsetWidth)
	{
		if(max_width == 0 || el.offsetWidth < max_width)
		{
			el.cols = parseInt(el.cols) + 1;
			
			VitaminXP.TextArea.ExpendWidth(el, max_width);
		}
	}
}

VitaminXP.Element.SizeTo = function(el, width, height)
{
	el.style.width = width + 'px';
	el.style.height = height + 'px';
}

VitaminXP.Element.MoveTo = function(el, x, y)
{
	el.style.left = x + 'px';
	el.style.top = y + 'px';
	
	el.style.position = 'absolute';
}

VitaminXP.Element.Hide = function(el)
{
	el.style.display = 'none';
}

VitaminXP.Element.Show = function(el)
{
	el.style.display = '';
}

VitaminXP.Element.All = function()
{
	return (Browser == "Internet Explorer") ? document.all : document.getElementsByTagName('*');
}


//===================================================
//===== Do not put any code below this line =========
//===================================================

// Loops through passed namespace and copies methods and properties to every passed element type found on page
VitaminXP.Element.ApplyPrototypesToElements = function(Namespace, TagName)
{
	var _els = document.getElementsByTagName(TagName)
	
	for(i = 0; i < _els.length; i++)
	{
		for(method in Namespace)
		{
			if(!_els[i][method])
			{
				_els[i][method] = Namespace[method];
			}
		}
	}
}


// Create NameSpaces
VitaminXP.Namespace("VitaminXP.Flash");


// returns installed flash player's version
// return values (-1 = when no flash player detected, 0 = when can't detect version, but detected player, >0 = version number)
VitaminXP.Flash.DetectInstalledVersion = function()
{
	var flash_try_up_to_version = 20;
	var flash_version = -1; // -1=Not Installed, 0=Installed but can't get version number, >0 is version number

	if (navigator.plugins && navigator.plugins.length)
	{
		x = navigator.plugins["Shockwave Flash"];
		
		if (x)
		{
			flash_version = 0;

			if (x.description)
			{
				y = x.description;
				flash_version = y.charAt(y.indexOf('.')-1);
			}
		}

		if (navigator.plugins["Shockwave Flash 2.0"])
		{
			flash_version = 2;
		}
	}
	else if (navigator.mimeTypes && navigator.mimeTypes.length)
	{
		x = navigator.mimeTypes['application/x-shockwave-flash'];

		if (x && x.enabledPlugin)
		{
			flash_version = 0;
		}
	}
	else
	{
		var TempObject;
		
		for(i = 1; i <= flash_try_up_to_version; i++)
		{
			try
			{
				TempObject = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + i);
				
				flash_version = i
			}
			catch(ex)
			{
				//status = ex;
			}
		}
	}
	
	return flash_version;
}

// Returns a Flash Object by object's ID/Name
// Note: <object> should have id="" and <embed> should have name"" attribute
VitaminXP.Flash.GetElement = function(movieName)
{
	if (Browser == "Microsoft Internet")
	{
		if (document.embeds && document.embeds[movieName]) return document.embeds[movieName]; 
	}
	else if (window.document[movieName]) 
	{
		return window.document[movieName];
	}
	else if(window[movieName])
	{
		return window[movieName];
	}
	else // if Internet Explorer
	{
		return document.getElementById(movieName);
	}
}

VitaminXP.Flash.SetVariable = function(movieName, variableName, value)
{
	VitaminXP.Flash.GetElement(movieName).SetVariable(variableName, value);
}

VitaminXP.Flash.PercentLoaded = function(movieName)
{
	return VitaminXP.Flash.GetElement(movieName).PercentLoaded();
}

VitaminXP.Flash.Object = function()
{
	var _arguments = VitaminXP.Flash.Object.arguments;
	
	this._args = new Array();
	this._params = new Array();
	this._vars = new Array();
	this.seperator = "xX=Xx";
	
	this.addArgument = function(name, value)
	{
		this._args.push(name + this.seperator + value);
	}
	
	this.addParameter = function(name, value)
	{
		this._params.push(name + this.seperator + value);
	}
	
	this.addVariable = function(name, value)
	{
		this._vars.push(name + this.seperator + value);
	}
	
	this.write = function(id)
	{
		$(id).innerHTML = $(id).innerHTML + this.toString();
	}
	
	this.toString = function()
	{
		var args = "";
		var object_params = "";
		var embed_params = "";
		var flashvars = "";
		var _temp;
		var temp;
		
		var html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" %%ARGS%%>%%OBJECT_PARAMS%%'
			+ '<param name="flashvars" value="%%VARS%%" />'
			+ '<embed type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" %%ARGS%% %%EMBED_PARAMS%% flashvars="%%VARS%%"></embed>'
			+ '</object>';
		
		// generate arguments
		for(var i = 0; i < this._args.length; i++)
		{
			_temp = this._args[i].split(this.seperator, 2);
			args += " " + _temp[0] + '="' + _temp[1] + '"';
		}
		
		// generate rapameters
		for(var i = 0; i < this._params.length; i++)
		{
			_temp = this._params[i].split(this.seperator, 2);
			if(_temp[0] != 'src') object_params += '<param name="' + _temp[0] + '" value="' + _temp[1] + '" />'
			if(_temp[0] != 'movie') embed_params += ' ' + _temp[0] + '="' + _temp[1] + '"';
		}
		
		for(var i = 0; i < this._vars.length; i++)
		{
			if(i > 0) flashvars += "&";
			_temp = this._vars[i].split(this.seperator, 2);
			temp = _temp[1].toString();
			flashvars += _temp[0] + "=" + temp.replaceString("=", "%3D").replaceString("&", "%26");
		}
		
		html = html.replaceString('%%ARGS%%', args);
		html = html.replaceString('%%OBJECT_PARAMS%%', object_params);
		html = html.replaceString('%%EMBED_PARAMS%%', embed_params);
		html = html.replaceString('%%VARS%%', flashvars);
		
		return html;
	}
	
	if(_arguments.length > 0) this.addParameter('src', _arguments[0]);
	if(_arguments.length > 0) this.addParameter('movie', _arguments[0]);
	if(_arguments.length > 1) this.addArgument('id', _arguments[1]);
	if(_arguments.length > 1) this.addArgument('name', _arguments[1]);
	if(_arguments.length > 2) this.addArgument('width', _arguments[2]);
	if(_arguments.length > 3) this.addArgument('height', _arguments[3]);
}


// This code requires file "vitaminxp.forms.css" to be included too

// Create NameSpaces
VitaminXP.Namespace("VitaminXP.Forms.Control");

VitaminXP.Forms.Control.CreateNew = function(tag_name)
{
	var _args = VitaminXP.Forms.Control.CreateNew.arguments;
	
	var Control = document.createElement(tag_name);
	
	Control.tag_name = tag_name;
	Control.parent = (_args.length > 1) ? _args[1] : null;
	Control.ZOrder = 0; // for this control (just to keep track)
	Control.ElementsZOrder = 1; // for child elements of this control (if any)
	Control._elements = new Array();
	Control.dragable = false;
	Control.dragging = null;
	Control.location = {x:0, y:0};
	Control._size = {width:0, height:0};
	Control.anchor = {
		top:true,
		bottom:false,
		left:true,
		right:false
	}
	Control.stay_inside = false; // don't make default to true because it effects badly on form
	Control.snap = {
		on_drag:false,
		on_drop:false,
		paralel:10,
		perpendicular:10,
		animate:false
	}
	Control.throwing = {
		enabled:false,
		friction:50,
		timer:null
	}
	
	Control.ondrag = function(){};
	Control.onresize = function(){};
	Control.onmove = function(){};
	
	Control.SizeTo = function(width, height)
    {
		
		try
		{
			// Get difference of size
			var size_dif = {
				width: width - Control._size.width,
				height: height - Control._size.height
			}
			
			if(Control.stay_inside)
			{
				Control.MoveTo(Control.location.x - size_dif.width, Control.location.y - size_dif.height);
			}
			
			Control._size.width = width;
			Control._size.height = height;
			
			var moveX;
			var moveY;
			
			var cancelResize = false;
			
			// Resize child nodes if their anchors are set
			for(var i = 0; i < Control._elements.length; i++)
			{
				moveX = null;
				moveY = null;
				
				// check if element is compatible
				if(typeof Control._elements[i].anchor == 'object')
				{
					if(Control._elements[i].anchor.left && Control._elements[i].anchor.right && size_dif.width != 0)
					{
						Control._elements[i].SizeTo(Control._elements[i]._size.width + size_dif.width, Control._elements[i]._size.height);
					}
					else if(Control._elements[i].anchor.right && size_dif.width != 0)
					{
						Control._elements[i].MoveTo(Control._elements[i].location.x + size_dif.width, Control._elements[i].location.y);
					}
					
					if(Control._elements[i].anchor.top && Control._elements[i].anchor.bottom && size_dif.height != 0)
					{
						Control._elements[i].SizeTo(Control._elements[i]._size.width, Control._elements[i]._size.height + size_dif.height);
					}
					else if(Control._elements[i].anchor.bottom && size_dif.height != 0)
					{
						Control._elements[i].MoveTo(Control._elements[i].location.x, Control._elements[i].location.y + size_dif.height);
					}
				}
				
				if(typeof Control._elements[i].stay_inside == 'boolean' && typeof Control._elements[i]._size == 'object' && typeof Control._elements[i].location == 'object' && typeof Control._elements[i].MoveTo == 'function')
				{
					if(Control._elements[i].stay_inside)
					{
						// Sheck horisontal
						if(width >= Control._elements[i]._size.width)
						{
							if(width < Control._elements[i].location.x + Control._elements[i]._size.width)
							{
								moveX = width - Control._elements[i]._size.width;
							}
						}
						else
						{
							cancelResize = true;
						}
						
						// Sheck vertical
						if(height >= Control._elements[i]._size.height)
						{
							if(height < Control._elements[i].location.y + Control._elements[i]._size.height)
							{
								moveY = height - Control._elements[i]._size.height;
							}
						}
						else
						{
							cancelResize = true;
						}
						
						if(moveX != null && moveY == null) moveY = Control._elements[i].location.y;
						if(moveY != null && moveX == null) moveX = Control._elements[i].location.x;
						
						if(moveX != null && moveY != null) Control._elements[i].MoveTo(moveX, moveY);
					}
				}
			}
			
			if(width < 0) width = 0;
			if(height < 0) height = 0;
			
			// Apply size
			if(!cancelResize)
			{
				VitaminXP.Element.SetStyle(Control, 'width', width);
				VitaminXP.Element.SetStyle(Control, 'height', height);
			}
			else
			{
				return false;
			}
			
			// handle on resize event
			Control.onresize();
		}
		catch(ex)
		{
			Control.HandleExeption(ex, "Control.SizeTo()");
		}
		
		return true;
    }
    
    Control.MoveTo = function(left, top)
    {
		try
		{
			// Check if control should stay inside of parent's rectangle
			if(typeof Control.parent._size == 'object' && Control.stay_inside)
			{
				// Check horisontal
				if(left < 0)
				{
					left = 0;
				}
				else if(left + Control._size.width > Control.parent._size.width)
				{
					left = Control.parent._size.width - Control._size.width;
				}
				
				// Check vertical
				if(top < 0)
				{
					top = 0;
				}
				else if(top + Control._size.height > Control.parent._size.height)
				{
					top = Control.parent._size.height - Control._size.height;
				}
			}
			
			Control.location.x = parseInt(left);
			Control.location.y = parseInt(top);
			
			VitaminXP.Element.SetStyle(Control, 'left', Control.location.x);
			VitaminXP.Element.SetStyle(Control, 'top', Control.location.y);
			
			Control.onmove();
		}
		catch(ex)
		{
			Control.HandleExeption(ex, "Control.MoveTo()");
		}
    }
	
	Control.StartDragging = function(e)
	{
		Control.dragging = {
			locationX:Control.location.x,
			locationY:Control.location.y,
			sizeWidth:Control._size.width,
			sizeHeight:Control._size.height,
			parentLocationX:(typeof Control.parent.location == 'object') ? Control.parent.location.x : 0,
			parentLocationY:(typeof Control.parent.location == 'object') ? Control.parent.location.y : 0,
			parentSizeWidth:(typeof Control.parent._size == 'object') ? Control.parent._size.width : 0,
			parentSizeHeight:(typeof Control.parent._size == 'object') ? Control.parent._size.height : 0,
			mouseX:(Browser == "Internet Explorer") ? event.screenX : e.screenX,
			mouseY:(Browser == "Internet Explorer") ? event.screenY : e.screenY,
			time:new Date()
		}
		
		VitaminXP.Element.AddEvent(document.body, 'mouseup', Control.StopDragging);
		VitaminXP.Element.AddEvent(document.body, 'mousemove', Control.Drag);
		
		if(Control.throwing.enabled)
		{
			Control.throwing.timer = setInterval(Control.LogThrowingData, 10);
			Control.throwing.toTime = new Date();
			Control.throwing.toX = Control.location.x;
			Control.throwing.toY = Control.location.y;
			Control.throwing.fromTime = new Date();
			Control.throwing.fromX = Control.location.x;
			Control.throwing.fromY = Control.location.y;
		}
	}
	
	Control.LogThrowingData = function()
	{
		
		Control.throwing.fromTime = Control.throwing.toTime;
		Control.throwing.toTime = new Date();
		
		Control.throwing.fromX = Control.throwing.toX;
		Control.throwing.toX = Control.location.x;
		
		Control.throwing.fromY = Control.throwing.toY;
		Control.throwing.toY = Control.location.y;
	}
	
	Control.Drag = function(e)
	{
		try
		{
			if(Control.dragging != null)
			{
				Control.dragging.time = new Date();
				Control.dragging.slopeX = e.screenX - Control.dragging.mouseX;
				Control.dragging.slopeY = e.screenY - Control.dragging.mouseY;
				
				Control.MoveTo(Control.dragging.locationX + Control.dragging.slopeX, Control.dragging.locationY + Control.dragging.slopeY);
				
				Control.ondrag();
				
				if(Control.snap.on_drag) Control.Snap();
			}
		}
		catch(ex)
		{
			Control.HandleExeption(ex, "Control.Drag()");
		}
	}
	
	Control.StopDragging = function(e)
	{
		// Before destroying drag information do throwing
		if(Control.throwing.enabled)
		{
			clearInterval(Control.throwing.timer);
			Control.Throw();
		}
		
		Control.dragging = null;
		VitaminXP.Element.RemoveEvent(document.body, 'mouseup', Control.StopDragging);
		VitaminXP.Element.RemoveEvent(document.body, 'mousemove', Control.Drag);
		
		if(Control.snap.on_drop) Control.Snap();
	}
	
	Control.Draggable = function()
	{
		var _args = Control.Draggable.arguments;
		
		if(_args.length == 0)
		{
			return Control.dragable;
		}
		else
		{
			if(_args[0] === true)
			{
				VitaminXP.Element.AddEvent(Control, 'mousedown', Control.StartDragging);
			}
			else if(_args[0] === false)
			{
				VitaminXP.Element.RemoveEvent(Control, 'mousedown', Control.StartDragging);
			}
			
			Control.dragable = _args[0];
		}
	}
	
	// Throws the control
	// parameter: slope (object with properties x and y. Ex: slope.x = 10);
	Control.Throw = function()
	{
		var miliseconds = Control.throwing.toTime - Control.throwing.fromTime;
		
		if(miliseconds > 0)
		{
			var xDisplacement = Control.throwing.toX - Control.throwing.fromX;
			var yDisplacement = Control.throwing.toY - Control.throwing.fromY;
			
			var x_per_second = xDisplacement / (miliseconds * 2) * 1000;
			var y_per_second = yDisplacement / (miliseconds * 2) * 1000;
			
			var toX = Control.location.x + x_per_second;
			var toY = Control.location.y + y_per_second;
			
			VitaminXP.Animation.Animate(Control, {left:{from:Control.location.x, to:toX}, top:{from:Control.location.y, to:toY}}, 1, "EaseOut");
		}
	}
	
	Control.Snap = function()
	{
		var snaped_control = {
			x:null,
			y:null
		}
		
		var left;
		var right;
		var top;
		var bottom;
		
		var snapedX = false;
		var snapedY = false;
		var allowSnapX = false;
		var allowSnapY = false;
		
		var newX = null;
		var newY = null;
		
		// Scan for elements that belong to same parent and find ones that control might snap to
		for(var i = 0; i < Control.parent._elements.length; i++)
		{
			if(Control.parent._elements[i] != Control)
			{
				allowSnapX = false;
				allowSnapY = false;
				
				left = Control.parent._elements[i].location.x.toInteger();
				right = (left + Control.parent._elements[i]._size.width).toInteger();
				top = Control.parent._elements[i].location.y.toInteger();
				bottom = (top + Control.parent._elements[i]._size.height).toInteger();
				
				if(!snapedY && ((Control.location.x >= left && Control.location.x <= right) || (Control.location.x + Control._size.width >= left && Control.location.x + Control._size.width <= right) || (Control.location.x < left && Control.location.x + Control._size.width > right)))
				{
					allowSnapY = true;
				}
				
				if(!snapedX && ((Control.location.y >= top && Control.location.y <= bottom) || (Control.location.y + Control._size.height >= top && Control.location.y + Control._size.height <= bottom) || (Control.location.y < top && Control.location.y + Control._size.height > bottom)))
				{
					allowSnapX = true;
				}
				
				if(allowSnapX && !snapedX)
				{
					// [c]>[
					if((Control.location.x + Control._size.width).similarTo(left, Control.snap.paralel))
					{
						newX = left - Control._size.width;
						snaped_control.x = {top:top, bottom:bottom};
						snapedX = true;
					}
					
					//  ]<[c]
					if(Control.location.x.similarTo(right, Control.snap.paralel))
					{
						newX = right;
						snaped_control.x = {top:top, bottom:bottom};
						snapedX = true;
					}
				}
				
				if(allowSnapY && !snapedY)
				{
					// \/
					//|--|
					if((Control.location.y + Control._size.height).similarTo(top, Control.snap.paralel))
					{
						newY = top - Control._size.height;
						snaped_control.y = {left:left, right:right};
						snapedY = true;
					}
					
					// |__|
					//  /\
					if(Control.location.y.similarTo(bottom, Control.snap.paralel) && !snapedY)
					{
						newY = bottom;
						snaped_control.y = {left:left, right:right};
						snapedY = true;
					}
				}
			}
		}
		
		// Check for perpendicular snaping with same object that it snaped to (only if it snaped to one object)
		if(snapedX && !snapedY)
		{
			if(snaped_control.x.top.similarTo(Control.location.y, Control.snap.perpendicular) || snaped_control.x.top.similarTo(Control.location.y + Control._size.height, Control.snap.perpendicular))
			{
				newY = snaped_control.x.top;
				snapedY = true;
			}
			else if(snaped_control.x.bottom.similarTo(Control.location.y + Control._size.height, Control.snap.perpendicular) || snaped_control.x.bottom.similarTo(Control.location.y, Control.snap.perpendicular))
			{
				newY = snaped_control.x.bottom;
				snapedY = true;
			}
		}
		
		if(snapedY && !snapedX)
		{
			if(snaped_control.y.left.similarTo(Control.location.x, Control.snap.perpendicular) || snaped_control.y.left.similarTo(Control.location.x + Control._size.width, Control.snap.perpendicular))
			{
				newX = snaped_control.y.left;
				snapedX = true;
			}
			else if(snaped_control.y.right.similarTo(Control.location.x + Control._size.width, Control.snap.perpendicular) || snaped_control.y.right.similarTo(Control.location.x, Control.snap.perpendicular))
			{
				newX = snaped_control.y.right;
				snapedX = true;
			}
		}
		// End of perpendicular snaping
		
		if(newX == null) newX = Control.location.x;
		if(newY == null) newY = Control.location.y;
		
		if(newX != Control.location.x || newY != Control.location.y)
		{
			if(Control.snap.animate)
			{
				VitaminXP.Animation.Animate(Control, {left:{to:newX, from:Control.location.x}, top:{to:newY, from:Control.location.y}}, 0.2, "EaseOut");
			}
			else
			{
				Control.MoveTo(newX, newY);
			}
		}
		
		if(snapedX && snapedY) i = Control.parent._elements.length;
	}
    
    Control.BringToFront = function()
    {
		// Make sure that this.parent has a valid value
		if(typeof Control.parent != 'object') return false;
		
		if(Control.parent.ElementsZOrder == undefined) Control.parent.ElementsZOrder = 1;
		
		VitaminXP.Element.SetStyle(Control, 'z-index', Control.parent.ElementsZOrder++);
		Control.ZOrder = Control.parent.ElementsZOrder;
		
		return true;
    }
    
    Control.SendToBack = function()
    {
		VitaminXP.Element.SetStyle(Control, 'z-index', 0);
		Control.ZOrder = 0;
    }
    
    Control.AddControl = function(element)
    {
		element.parent = Control;
		
		Control.appendChild(element);
		
		Control._elements.Add(element);
    }
    
    Control.RemoveControl = function(element)
    {
		Control.removeChild(element);
		
		Control._elements.Remove(element);
    }
    
    Control.HandleExeption = function(exeption, function_name)
    {
		alert("JAVASCRIPT ERROR: " + exeption.message + " by function " + function_name);
    }
	
	return Control;
}



// This code requires file "vitaminxp.forms.css" to be included too

// Create NameSpaces
VitaminXP.Namespace("VitaminXP.Forms");

// TextBox
VitaminXP.Forms.TextBox = function(name)
{
    var NewObject = VitaminXP.Forms.Control.CreateNew('input', document.body);
    NewObject.type = 'text';
    NewObject.name = name;
    NewObject.id = name;
    NewObject.style.position = 'absolute';
    
    NewObject.Text = function(txt)
    {
		this.value = txt;
    }
    
    NewObject.GetText = function()
    {
		return this.value;
    }
    
    return NewObject;
}

// TextArea
VitaminXP.Forms.TextArea = function(name)
{
    var NewObject = VitaminXP.Forms.Control.CreateNew('textarea', document.body);
    NewObject.name = name;
    NewObject.id = name;
    NewObject.style.position = 'absolute';
    
    NewObject.Text = function(txt)
    {
		this.value = txt;
    }
    
    NewObject.GetText = function()
    {
		return this.value;
    }
    
    return NewObject;
}

// Button
VitaminXP.Forms.Button = function(name)
{
    var NewObject = VitaminXP.Forms.Control.CreateNew('input', document.body);
    NewObject.type = 'button';
    NewObject.name = name;
    NewObject.id = name;
    NewObject.value = name;
    NewObject.style.position = 'absolute';
    
    NewObject.Text = function(txt)
    {
		this.value = txt;
    }
    
    NewObject.GetText = function()
    {
		return this.value;
    }
    
    return NewObject;
}

// Label
VitaminXP.Forms.Label = function(name)
{
    var NewObject = VitaminXP.Forms.Control.CreateNew('label', document.body);
    NewObject.name = name;
    NewObject.id = name;
    NewObject.innerHTML = 'name';
    NewObject.style.position = 'absolute';
    VitaminXP.Element.SetStyle(NewObject, 'font-family', 'Arial');
    VitaminXP.Element.SetStyle(NewObject, 'font-size', '9pt');
    
    NewObject.Text = function(txt)
    {
		this.innerText = txt;
    }
    
    NewObject.GetText = function()
    {
		return this.innerHTML;
    }
    
    return NewObject;
}

// Panel
VitaminXP.Forms.Panel = function(name)
{
	var NewObject = null;
    NewObject = VitaminXP.Forms.Control.CreateNew('div', document.body);
    NewObject.name = name;
    NewObject.id = name;
    NewObject.style.position = 'absolute';
    NewObject.style.overflow = 'auto';
    NewObject.style.display = 'block';
    NewObject.style.background = '#e0dfe3';
    
    return NewObject;
}

// Form
VitaminXP.Forms.Form = function(name)
{
	var border_size = 5;
	var title_bar_size = 20;
	var window_color = '#4444EE';
	
	var NewForm = VitaminXP.Forms.Control.CreateNew('div', document.body);
	
	NewForm.name = name;
	NewForm.id = name;
	NewForm.resizable = true;
	NewForm.draggable = true;
	NewForm._min_size = {width:150, height:100};
	NewForm._max_size = {width:0, height:0};
	VitaminXP.Element.SetStyle(NewForm, 'position', 'absolute');
	VitaminXP.Element.SetStyle(NewForm, 'background', '#e0dfe3');
	VitaminXP.Element.SetStyle(NewForm, '-moz-user-select', 'none');
	VitaminXP.Element.AddEvent(NewForm, 'selectstart', function(){return false;});
	NewForm.SizeTo(300, 200);
	
	VitaminXP.Element.AddEvent(NewForm, 'mousedown', NewForm.BringToFront);
	
	NewForm.BorderDrag = function(e, Control)
	{
		try
		{
			if(Control.dragging == null) return;
			
			if(!NewForm.resizable)
			{
				if(Control.drag == 'drag' && NewForm.draggable)
				{
					
				}
				else
				{
					return;
				}
			}
			
			var difX = VitaminXP.Element.GetScreenX(e) - Control.dragging.mouseX;
			var difY = VitaminXP.Element.GetScreenY(e) - Control.dragging.mouseY;
			
			// Create newX, newY, newWidth and newHeight based on control direction (up down right left);
			var move = false;
			
			var newX;
			var newY;
			var newWidth;
			var newHeight;
			
			switch(Control.drag)
			{
				case 'top':
					
					newX = Control.parent.location.x;
					newY = Control.dragging.parentLocationY + difY;
					newWidth = Control.parent._size.width;
					newHeight = Control.dragging.parentSizeHeight - difY;
					
					break;
				
				case 'top-right':
					
					newX = Control.dragging.parentLocationX;
					newY = Control.dragging.parentLocationY + difY;
					newWidth = Control.dragging.parentSizeWidth + difX;
					newHeight = Control.dragging.parentSizeHeight - difY;
					
					break;
				
				case 'right':
					
					newWidth = Control.dragging.parentSizeWidth + difX;
					newHeight = Control.parent._size.height;
					
					break;
				
				case 'bottom-right':
					
					newWidth = Control.dragging.parentSizeWidth + difX;
					newHeight = Control.dragging.parentSizeHeight + difY;
					
					break;
				
				case 'bottom':
					
					newWidth = Control.parent._size.width;
					newHeight = Control.dragging.parentSizeHeight + difY;
					
					break;
				
				case 'bottom-left':
					
					newX = Control.dragging.parentLocationX + difX;
					newY = Control.parent.location.y;
					newWidth = Control.dragging.parentSizeWidth - difX;
					newHeight = Control.dragging.parentSizeHeight + difY;
					
					break;
				
				case 'left':
					
					newX = Control.dragging.parentLocationX + difX;
					newY = Control.parent.location.y;
					newWidth = Control.dragging.parentSizeWidth - difX;
					newHeight = Control.parent._size.height;
					
					break;
				
				case 'top-left':
					
					newX = Control.dragging.parentLocationX + difX;
					newY = Control.dragging.parentLocationY + difY;
					newWidth = Control.dragging.parentSizeWidth - difX;
					newHeight = Control.dragging.parentSizeHeight - difY;
					
					break;
				
				case 'drag':
					
					newX = Control.dragging.parentLocationX + difX;
					newY = Control.dragging.parentLocationY + difY;
					
					break;
			}
			
			if(newWidth != null && newHeight != null)
			{
				if(newWidth < Control.parent._min_size.width)
				{
					newWidth = Control.parent._min_size.width;
					newX = null;
				}
				else if(newWidth > Control.parent._max_size.width && Control.parent._max_size.width > Control.parent._min_size.width)
				{
					newWidth = Control.parent._max_size.width;
					newX = null;
				}
				
				if(newHeight < Control.parent._min_size.height)
				{
					newHeight = Control.parent._min_size.height;
					newY = null;
				}
				else if(newHeight > Control.parent._max_size.height && Control.parent._max_size.height > Control.parent._min_size.height)
				{
					newHeight = Control.parent._max_size.height;
					newY = null;
				}
				
				Control.parent.SizeTo(newWidth, newHeight);
			}
			
			if(newX != null || newY != null)
			{
				if(newX == null) newX = Control.parent.location.x;
				if(newY == null) newY = Control.parent.location.y;
				
				Control.parent.MoveTo(newX, newY);
			}
			
			Control.ondrag();
		}
		catch(ex)
		{
			Control.HandleExeption(ex, "NewForm.BorderDrag()");
		}
	}
	
	// Title Bar
	var TitleBar = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(TitleBar, 'background', window_color);
	VitaminXP.Element.SetStyle(TitleBar, 'font-family', 'Arial');
	VitaminXP.Element.SetStyle(TitleBar, 'font-weight', 'bold');
	VitaminXP.Element.SetStyle(TitleBar, 'font-size', '10pt');
	VitaminXP.Element.SetStyle(TitleBar, 'color', '#FFFFFF');
	VitaminXP.Element.SetStyle(TitleBar, 'cursor', 'default');
	VitaminXP.Element.SetStyle(TitleBar, 'position', 'absolute');
	VitaminXP.Element.SetStyle(TitleBar, 'overflow', 'hidden');
	TitleBar.innerHTML = name;
	TitleBar.SizeTo(NewForm._size.width, title_bar_size);
	TitleBar.MoveTo(NewForm.location.x, NewForm.location.y - title_bar_size);
	TitleBar.anchor.right = true;
	TitleBar.drag = 'drag';
	
	TitleBar.Drag = function(e)
	{
		NewForm.BorderDrag(e, TitleBar);
	}
	
	TitleBar.Draggable(true);
	NewForm.AddControl(TitleBar);
	
	NewForm.Text = function()
	{
		var _args = NewForm.Text.arguments;
		
		if(_args.length == 0)
		{
			return TitleBar.innerHTML;
		}
		else
		{
			TitleBar.innerHTML = _args[0];
		}
	}
	
	// Top Border
	var TopBorder = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(TopBorder, 'background', window_color);
	VitaminXP.Element.SetStyle(TopBorder, 'cursor', 'n-resize');
	VitaminXP.Element.SetStyle(TopBorder, 'position', 'absolute');
	VitaminXP.Element.SetStyle(TopBorder, 'overflow', 'hidden');
	TopBorder.SizeTo(NewForm._size.width, border_size);
	TopBorder.MoveTo(NewForm.location.x, NewForm.location.y - title_bar_size - border_size);
	TopBorder.anchor.right = true;
	TopBorder.drag = 'top';
	
	TopBorder.Drag = function(e)
	{
		NewForm.BorderDrag(e, TopBorder);
	}
	
	TopBorder.Draggable(true);
	NewForm.AddControl(TopBorder);
	
	// Left Border
	var LeftBorder = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(LeftBorder, 'background', window_color);
	VitaminXP.Element.SetStyle(LeftBorder, 'cursor', 'w-resize');
	VitaminXP.Element.SetStyle(LeftBorder, 'position', 'absolute');
	LeftBorder.SizeTo(border_size, NewForm._size.height + title_bar_size);
	LeftBorder.MoveTo(NewForm.location.x - border_size, NewForm.location.y - title_bar_size);
	LeftBorder.anchor.bottom = true;
	LeftBorder.drag = 'left';
	
	LeftBorder.Drag = function(e)
	{
		NewForm.BorderDrag(e, LeftBorder);
	}
	
	LeftBorder.Draggable(true);
	NewForm.AddControl(LeftBorder);
	
	// Right Border
	var RightBorder = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(RightBorder, 'background', window_color);
	VitaminXP.Element.SetStyle(RightBorder, 'cursor', 'e-resize');
	VitaminXP.Element.SetStyle(RightBorder, 'position', 'absolute');
	RightBorder.SizeTo(border_size, NewForm._size.height + title_bar_size);
	RightBorder.MoveTo(NewForm._size.width, NewForm.location.y - title_bar_size);
	RightBorder.anchor.right = true;
	RightBorder.anchor.left = false;
	RightBorder.anchor.bottom = true;
	RightBorder.drag = 'right';
	
	RightBorder.Drag = function(e)
	{
		NewForm.BorderDrag(e, RightBorder);
	}
	
	RightBorder.Draggable(true);
	NewForm.AddControl(RightBorder);
	
	// bottom Border
	var BottomBorder = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(BottomBorder, 'background', window_color);
	VitaminXP.Element.SetStyle(BottomBorder, 'cursor', 's-resize');
	VitaminXP.Element.SetStyle(BottomBorder, 'position', 'absolute');
	VitaminXP.Element.SetStyle(BottomBorder, 'overflow', 'hidden');
	BottomBorder.SizeTo(NewForm._size.width, border_size);
	BottomBorder.MoveTo(NewForm.location.x, NewForm._size.height);
	BottomBorder.anchor.right = true;
	BottomBorder.anchor.top = false;
	BottomBorder.anchor.bottom = true;
	BottomBorder.drag = 'bottom';
	
	BottomBorder.Drag = function(e)
	{
		NewForm.BorderDrag(e, BottomBorder);
	}
	
	BottomBorder.Draggable(true);
	NewForm.AddControl(BottomBorder);
	
	// Top Left Corner
	var TopLeftCorner = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(TopLeftCorner, 'background', window_color);
	VitaminXP.Element.SetStyle(TopLeftCorner, 'cursor', 'nw-resize');
	VitaminXP.Element.SetStyle(TopLeftCorner, 'position', 'absolute');
	VitaminXP.Element.SetStyle(TopLeftCorner, 'overflow', 'hidden');
	TopLeftCorner.SizeTo(border_size, border_size);
	TopLeftCorner.MoveTo(NewForm.location.x - border_size, NewForm.location.y - title_bar_size - border_size);
	TopLeftCorner.drag = 'top-left';
	
	TopLeftCorner.Drag = function(e)
	{
		NewForm.BorderDrag(e, TopLeftCorner);
	}
	
	TopLeftCorner.Draggable(true);
	NewForm.AddControl(TopLeftCorner);
	
	// Top Right Corner
	var TopRightCorner = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(TopRightCorner, 'background', window_color);
	VitaminXP.Element.SetStyle(TopRightCorner, 'cursor', 'ne-resize');
	VitaminXP.Element.SetStyle(TopRightCorner, 'position', 'absolute');
	VitaminXP.Element.SetStyle(TopRightCorner, 'overflow', 'hidden');
	TopRightCorner.SizeTo(border_size, border_size);
	TopRightCorner.MoveTo(NewForm._size.width, NewForm.location.y - title_bar_size - border_size);
	TopRightCorner.anchor.right = true;
	TopRightCorner.anchor.left = false;
	TopRightCorner.drag = 'top-right';
	
	TopRightCorner.Drag = function(e)
	{
		NewForm.BorderDrag(e, TopRightCorner);
	}
	
	TopRightCorner.Draggable(true);
	NewForm.AddControl(TopRightCorner);
	
	// Bottom Left Corner
	var BottomLeftCorner = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(BottomLeftCorner, 'background', window_color);
	VitaminXP.Element.SetStyle(BottomLeftCorner, 'cursor', 'sw-resize');
	VitaminXP.Element.SetStyle(BottomLeftCorner, 'position', 'absolute');
	VitaminXP.Element.SetStyle(BottomLeftCorner, 'overflow', 'hidden');
	BottomLeftCorner.SizeTo(border_size, border_size);
	BottomLeftCorner.MoveTo(NewForm.location.x - border_size, NewForm._size.height);
	BottomLeftCorner.anchor.top = false;
	BottomLeftCorner.anchor.bottom = true;
	BottomLeftCorner.drag = 'bottom-left';
	
	BottomLeftCorner.Drag = function(e)
	{
		NewForm.BorderDrag(e, BottomLeftCorner);
	}
	
	BottomLeftCorner.Draggable(true);
	NewForm.AddControl(BottomLeftCorner);
	
	// Bottom Right Corner
	var BottomRightCorner = VitaminXP.Forms.Control.CreateNew('div', NewForm);
	VitaminXP.Element.SetStyle(BottomRightCorner, 'background', window_color);
	VitaminXP.Element.SetStyle(BottomRightCorner, 'cursor', 'se-resize');
	VitaminXP.Element.SetStyle(BottomRightCorner, 'position', 'absolute');
	VitaminXP.Element.SetStyle(BottomRightCorner, 'overflow', 'hidden');
	BottomRightCorner.SizeTo(border_size, border_size);
	BottomRightCorner.MoveTo(NewForm._size.width, NewForm._size.height);
	BottomRightCorner.anchor.left = false;
	BottomRightCorner.anchor.right = true;
	BottomRightCorner.anchor.top = false;
	BottomRightCorner.anchor.bottom = true;
	BottomRightCorner.drag = 'bottom-right';
	
	BottomRightCorner.Drag = function(e)
	{
		NewForm.BorderDrag(e, BottomRightCorner);
	}
	
	BottomRightCorner.Draggable(true);
	NewForm.AddControl(BottomRightCorner);
    
	return NewForm;
}

// Slider Control (name, min_value, max_value, init_value, width)
VitaminXP.Forms.Slider = function(name, min_value, max_value, init_value, width)
{
	// Initialize Main Object
	var NewObject = new VitaminXP.Forms.Panel(name);
    VitaminXP.Element.SetStyle(NewObject, 'overflow', '');
    VitaminXP.Element.SetStyle(NewObject, 'background', 'transparent url(' + framework_location + 'images/slider_track.gif) repeat-x 0px 8px');
    NewObject.className = 'vxp_slider_horisontal';
    //return NewObject;
    NewObject.value = init_value;
    NewObject.min = (min_value > 0) ? min_value : 0;
    NewObject.max = (min_value < max_value) ? max_value : min_value + 1;
    
    if(NewObject.value > NewObject.max) NewObject.value = NewObject.max;
    if(NewObject.value < NewObject.min) NewObject.value = NewObject.min;
    
    NewObject.width = (width > 30) ? width : 30;
    NewObject.show_markers = true;
    
    NewObject.SizeTo(NewObject.width, 26);
    
    NewObject.padding = 7;
    NewObject.boundry = {
		left: NewObject.padding,
		right: NewObject.width - NewObject.padding
	};
	NewObject.markers = max_value - min_value;
	NewObject._markers = new Array();
	NewObject.marker_size = (NewObject.width - (NewObject.padding * 2)) / NewObject.markers;
    
    NewObject.eventHandler = null; // event
    
    // Creating and Positioning Markers
    NewObject.RearangeMarkers = function()
    {
		NewObject.marker_size = (NewObject.width - (NewObject.padding * 2)) / NewObject.markers;
		var marker_size = parseInt(NewObject.marker_size);
		var marker_size_decimals = NewObject.marker_size - marker_size;
		var xPosition = 0;
		var last_visible_marker_x_position = 0;
		
		for(var i = 0; i <= NewObject.markers; i++)
		{
			if(NewObject._markers[i] == undefined)
			{
				NewObject._markers[i] = new VitaminXP.Forms.Panel(name + '_marker' + i);
				VitaminXP.Element.SetStyle(NewObject._markers[i], 'border-left', '1px solid #a1a192');
				NewObject._markers[i].SizeTo(1, 3);
				NewObject.appendChild(NewObject._markers[i]);
			}
			
			NewObject._markers[i].style.display = NewObject.show_markers ? '' : 'none';
			
			if(last_visible_marker_x_position < 5 && last_visible_marker_x_position > 0)
			{
				NewObject._markers[i].style.display = 'none';
				since_last_marker
			}
			else
			{
				since_last_marker = 0;
			}
			
			xPosition = NewObject.padding + (marker_size * i) + (marker_size_decimals * i);
			NewObject._markers[i].MoveTo(xPosition, 23);
			
			if((xPosition - last_visible_marker_x_position) < 5 && last_visible_marker_x_position > 0 && i != NewObject.markers)
			{
				NewObject._markers[i].style.display = 'none';
			}
			else
			{
				last_visible_marker_x_position = xPosition;
			}
		}
    }
    
    NewObject.RearangeMarkers();
    
    // Initialize Slider thing
    NewObject.Slider = new VitaminXP.Forms.Panel(name + '_slider');
    VitaminXP.Element.SetStyle(NewObject.Slider, 'background', '');
    NewObject.Slider.className = "vxp_slider_horisontal_knob";
    NewObject.Slider.style.background = 'transparent url(' + framework_location + 'images/slider_mover.gif)';
    VitaminXP.Element.AddEvent(NewObject.Slider, 'mouseover', function(){NewObject.Slider.style.background = 'transparent url(' + framework_location + 'images/slider_mover_over.gif)';}, true);
    VitaminXP.Element.AddEvent(NewObject.Slider, 'mouseout', function(){if(!NewObject.Slider.mousedown){NewObject.Slider.style.background = 'transparent url(' + framework_location + 'images/slider_mover.gif)';};}, true);
    NewObject.Slider.width = 11;
    VitaminXP.Element.SetStyle(NewObject.Slider, 'width', NewObject.Slider.width);
    VitaminXP.Element.SetStyle(NewObject.Slider, 'left', parseInt(NewObject.width / 2) - parseInt(NewObject.Slider.width / 2));
    VitaminXP.Element.SetStyle(NewObject.Slider, 'height', 21);
    VitaminXP.Element.SetStyle(NewObject.Slider, 'cursor', 'e-resize');
    NewObject.AddControl(NewObject.Slider);
    
    NewObject.Slider.onmousedown = function(e)
    {
		this.mousedown = true;
		NewObject.style.cursor = 'e-resize';
		
		if(typeof e == 'undefined') e = event;
		
		this.startX = VitaminXP.Element.GetScreenX(e);
		this.sliderX = parseInt(VitaminXP.Element.GetStyle(this,'left')) + parseInt(NewObject.Slider.width / 2);
		
		VitaminXP.Element.AddEvent(document.body, 'mousemove', $(this).Drag, true);
		VitaminXP.Element.AddEvent(document.body, 'mouseup', $(this).StopDraging, true);
    }
    
    NewObject.Slider.StopDraging = function(e)
    {
		NewObject.Slider.mousedown = false;
		NewObject.style.cursor = 'default';
		NewObject.Slider.style.background = 'transparent url(' + framework_location + 'images/slider_mover.gif)';
		
		VitaminXP.Element.RemoveEvent(document.body, 'mousemove', $(NewObject.Slider).Drag, true);
		VitaminXP.Element.RemoveEvent(document.body, 'mouseup', $(NewObject.Slider).StopDraging, true);
    }
    
    NewObject.Slider.Drag = function(e)
    {
        if(typeof e == 'undefined') e = event;
        
		// Calculate slider position without snaping
		var difX = VitaminXP.Element.GetScreenX(e) - NewObject.Slider.startX;
		var newX = NewObject.Slider.sliderX + difX;
		
		// Make sure slider doesn't go out of boundries
		if(newX < NewObject.boundry.left)
		{
			newX = NewObject.boundry.left;
		}
		else if(newX > NewObject.boundry.right)
		{
			newX = NewObject.boundry.right;
		}
		
		// Calculate current marker and value
		var current_marker = Math.round((newX - NewObject.padding) / NewObject.marker_size);
		
		// Set new value
		NewObject.ValueChanged(current_marker + NewObject.min);
    }
    
    NewObject.Value = function(value)
    {
		NewObject.value = value;
		
		// Snap slider to current marker
		var left = NewObject.padding + ((NewObject.value - NewObject.min) * NewObject.marker_size) - parseInt(NewObject.Slider.width / 2);
		
		if(!isNaN(left)) VitaminXP.Element.SetStyle(NewObject.Slider, 'left', left);
    }
    
    NewObject.Value(NewObject.value);
    
    NewObject.ValueChanged = function(value)
    {
		NewObject.Value(value);
		
		// Handle onchange event
		if(NewObject.eventHandler != null)
		{
			try
			{
				eval(NewObject.eventHandler);
			}
			catch(ex)
			{
				VitaminXP.Exception(ex);
				window.status = ex.message;
			}
		}
    }
    
    NewObject.ShowMarkers = function()
    {
		this.show_markers = true;
		
		this.RearangeMarkers();
    }
    
    NewObject.HideMarkers = function()
    {
		NewObject.show_markers = false;
		
		NewObject.RearangeMarkers();
    }
    
    NewObject.SizeTo = function(width)
    {
		this.width = width;
		this.boundry = {
			left: this.padding,
			right: this.width - this.padding
		};
		this.marker_size = (NewObject.width - (NewObject.padding * 2)) / NewObject.markers;
		
		VitaminXP.Element.SetStyle(this, 'width', this.width);
		
		this.RearangeMarkers();
    }
    
    NewObject.MoveTo = function(left, top)
    {
		VitaminXP.Element.SetStyle(this, 'left', left);
		VitaminXP.Element.SetStyle(this, 'top', top);
    }
    
    return NewObject;
}

// JavaScript Document
VitaminXP.Namespace("VitaminXP.Image");


// PNG FIXES
var blankSrc = 'images/pixel.gif';

// Finds PNG images and pixes them using Image.FixPNG()
VitaminXP.Image.FixPNGImages = function ()
{
	var supported = /MSIE/.test(navigator.userAgent) && !/opera/.test(navigator.userAgent) && navigator.platform == "Win32";
	if ( supported )
	{
		var _imgs = document.getElementsByTagName('img');
		
		for (var i = 0; i < _imgs.length; i++)
		{
			if ( /\.png$/.test( _imgs[i].src.toLowerCase()) ) VitaminXP.Image.Source(_imgs[i], VitaminXP.Image.Source(_imgs[i]));
		}
		
		var _inputs = document.getElementsByTagName('input');
		
		for (var i = 0; i < _inputs.length; i++)
		{
			if(_inputs[i].type == 'image')
			{
				if ( /\.png$/.test( _inputs[i].src.toLowerCase()) ) VitaminXP.Image.Source(_inputs[i], VitaminXP.Image.Source(_inputs[i]));
			}
		}
	}
}

VitaminXP.StartUp("VitaminXP.Image.FixPNGImages()");
// END OF PNG FIXES

// Preloads images passed in array
VitaminXP.Image.Preload = function()
{
	var _urls = VitaminXP.Image.Preload.arguments;
	document.imageArray = new Array(_urls.length);
	
	for(var i=0; i<_urls.length; i++)
	{
		document.imageArray[i] = new Image;
		document.imageArray[i].src = _urls[i];
	}
}

// Sets/Gets source of an image handling PNG images well in Internet Explorer
VitaminXP.Image.Source = function(img)
{
	var _args = VitaminXP.Image.Source.arguments;
	
	img = $(img);
	
	if(_args.length > 1) // Set Source
	{
		var url = _args[1];
		
		if(url.substring(url.length - 4, url.length).toLowerCase() == '.png' && Browser == 'Internet Explorer')
		{
			img.style.width = img.offsetWidth + 'px';
			img.style.height = img.offsetHeight + 'px';
			
			img.src = blankSrc;
			
			img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + url + "',sizingMethod='scale')";
		}
		else
		{
			img.src = url;
		}
		
		return VitaminXP.Image.Source(img);
	}
	else // Return Source
	{
		if(Browser == 'Internet Explorer' && typeof img.style.filter == 'string' && img.src == blankSrc && img.style.filter.indexOf("progid:DXImageTransform.Microsoft.AlphaImageLoader(src='") > -1)
		{
			var start = img.style.filter.indexOf("src='") + 5;
			var end = img.style.filter.indexOf("'", start);
			
			return img.style.filter.substring(start, end);
		}
		else
		{
			return img.src;
		}
	}
}

// Create NameSpaces
VitaminXP.Namespace("VitaminXP.Line");
VitaminXP.Namespace("VitaminXP.LineService");

VitaminXP.Location = function(x, y)
{
	this.x = x;
	this.y = y;
};

_Points = new Array();

VitaminXP.LineService.Timer = setInterval('VitaminXP.LineService.AppendPoint()', 1000);

// Adds points of the line to the parent element, so the points will be displayed
VitaminXP.LineService.AppendPoint = function()
{
	if(_Points.length > 0)
	{
		clearInterval(VitaminXP.LineService.Timer);
		
		_Points[0].parent.appendChild(_Points[0].point);
		_Points.splice(0, 1);
		
		if(_Points.length == 0)
		{
			VitaminXP.LineService.Timer = setInterval('VitaminXP.LineService.AppendPoint()', 10);
		}
	}
	
	if(_Points.length > 0)
	{
		//setTimeout('VitaminXP.LineService.AppendPoint()', 1);
		VitaminXP.LineService.AppendPoint();
	}
}

VitaminXP.Line = function() // (Start, End, Parent, Color, Width)
{
	var _args = VitaminXP.Line.arguments;
	
	this.start = (_args.length > 0)? _args[0] : new VitaminXP.Location(0, 0);
	this.end = (_args.length > 1)? _args[1] : new VitaminXP.Location(100, 100);
	this.parent = (_args.length > 2 && _args[2] != undefined)? _args[2] : document;
	this.color = (_args.length > 3 && _args[3] != undefined)? _args[3] : "#000000";
	this.width = (_args.length > 4 && _args[4] != undefined)? _args[4] : 1;
	this._points = new Array();
	
	this.Draw2 = function()
	{
		var x1 = this.start.x;
		var x2 = this.end.x;
		var y1 = this.start.y;
		var y2 = this.end.y;
		
		if(x1 > x2)
		{
			var _x2 = x2;
			var _y2 = y2;
			x2 = x1;
			y2 = y1;
			x1 = _x2;
			y1 = _y2;
		}
		
		var dx = x2-x1, dy = Math.abs(y2-y1),
		x = x1, y = y1,
		yIncr = (y1 > y2)? -1 : 1;
		
		if(dx >= dy)
		{
			var pr = dy<<1,
			pru = pr - (dx<<1),
			p = pr-dx,
			ox = x;
			while(dx > 0)
			{--dx;
				++x;
				if(p > 0)
				{
					this._mkDiv(ox, y, x-ox, 1);
					y += yIncr;
					p += pru;
					ox = x;
				}
				else p += pr;
			}
			this._mkDiv(ox, y, x2-ox+1, 1);
		}

		else
		{
			var pr = dx<<1,
			pru = pr - (dy<<1),
			p = pr-dy,
			oy = y;
			if(y2 <= y1)
			{
				while(dy > 0)
				{--dy;
					if(p > 0)
					{
						this._mkDiv(x++, y, 1, oy-y+1);
						y += yIncr;
						p += pru;
						oy = y;
					}
					else
					{
						y += yIncr;
						p += pr;
					}
				}
				this._mkDiv(x2, y2, 1, oy-y2+1);
			}
			else
			{
				while(dy > 0)
				{--dy;
					y += yIncr;
					if(p > 0)
					{
						this._mkDiv(x++, oy, 1, y-oy);
						p += pru;
						oy = y;
					}
					else p += pr;
				}
				this._mkDiv(x2, oy, 1, y2-oy+1);
			}
		}
	}
	
	this.Draw = function()
	{
		this.x_displacement = Math.max(this.start.x, this.end.x) - Math.min(this.start.x, this.end.x);
		this.y_displacement = Math.max(this.start.y, this.end.y) - Math.min(this.start.y, this.end.y);
		this.variable_side = (this.x_displacement > this.y_displacement) ? 'width' : 'height';
		this.constant_side = (this.x_displacement > this.y_displacement) ? 'height' : 'width';
		this.horisontal_direction = (this.start.x > this.end.x) ? 'left' : 'right';
		this.vertical_direction = (this.start.y > this.end.y) ? 'up' : 'down';
		
		if(this.vertical_direction == 'up' && this.horisontal_direction == 'right')
		{
			this.direction = 'NE'; // North-East
		}
		else if(this.vertical_direction == 'down' && this.horisontal_direction == 'right')
		{
			this.direction = 'SE'; // South-East
		}
		else if(this.vertical_direction == 'up' && this.horisontal_direction == 'left')
		{
			this.direction = 'NW'; // North-West
		}
		else if(this.vertical_direction == 'down' && this.horisontal_direction == 'left')
		{
			this.direction = 'SW'; // South-West
		}
		
		this.points = Math.min(this.x_displacement, this.y_displacement);
		this._points = new Array(Math.max(this.points, 1));
		
		// Temp Variables used while drawing the line
		this.point_size = Math.max(this.x_displacement, this.y_displacement) / this._points.length;
		this.point_size_buffer = 0;
		this.point_location = this.start;
		this.variable_side_size = 0;
		this.last_variable_side_size = 0;
		
		for(i = 0; i < this._points.length; i++)
		{
			
			this.point_size_buffer += this.point_size;
			this.variable_side_size = parseInt(this.point_size_buffer);
			this.point_size_buffer -= this.variable_side_size;
			
			switch(this.direction)
			{
				case "NE":
				
					if(this.variable_side == 'width')
					{
						this.point_location.x += this.last_variable_side_size;
						this.point_location.y -= (i == 0) ? 0 : 1;
					}
					else
					{
						this.point_location.x += (i == 0) ? 0 : 1;
						this.point_location.y -= this.variable_side_size;
					}
					
					break;
					
				case "SE":
					
					if(this.variable_side == 'width')
					{
						this.point_location.x += this.last_variable_side_size;
						this.point_location.y += (i == 0) ? 0 : 1;
					}
					else
					{
						this.point_location.x += (i == 0) ? 0 : 1;
						this.point_location.y += this.last_variable_side_size;
					}
					
					break;
					
				case "NW":
				
					if(this.variable_side == 'width')
					{
						this.point_location.x -= this.variable_side_size;
						this.point_location.y -= (i == 0) ? 0 : 1;
					}
					else
					{
						this.point_location.x -= (i == 0) ? 0 : 1;
						this.point_location.y -= this.variable_side_size;
					}
					
					break;
					
				case "SW":
					
					if(this.variable_side == 'width')
					{
						this.point_location.x -= this.variable_side_size;
						this.point_location.y += (i == 0) ? 0 : 1;
					}
					else
					{
						this.point_location.x -= (i == 0) ? 0 : 1;
						this.point_location.y += this.last_variable_side_size;
					}
					
					break;
			}
			
			this.last_variable_side_size = this.variable_side_size;
			
			// Create Element
			this._points[i] = (Browser == "Internet Explorer") ? document.createElement('img', true) : document.createElement('div', true);
			this._points[i].style.position = 'absolute';
			this._points[i].style[this.constant_side] = '1px';
			this._points[i].style[this.variable_side] = this.variable_side_size + 'px';
			this._points[i].style.background = this.color;
			
			// Setting location to a point
			this._points[i].style.top = this.point_location.y;
			this._points[i].style.left = this.point_location.x;
			
			// Adding a point to parent element
			this.parent.appendChild(this._points[i]);
		}
	}
	
	this._mkDiv = function(l, t, w, h)
	{
		var div = (Browser == "Internet Explorer") ? document.createElement('img') : document.createElement('div');
		div.style.background = this.color;
		div.style.position = 'absolute';
		div.style.width = w + 'px';
		div.style.height = h + 'px';
		div.style.left = l + 'px';
		div.style.top = t + 'px';
		//if(Browser == "Internet Explorer") div.innerHTML = '<img width="1" height="1" />';
		
		// Add to array
		this._points.push(div);
		
		// Add to parent element
		this.parent.appendChild(div);
	}
	
	this.Clear = function()
	{
		for(line_index = 0; line_index < this._points.length; line_index++)
		{
			this.parent.removeChild(this._points[0]);
			this._points.splice(0, 1);
		}
		
		return (this._points.length == 0)
	}
	
	this.Redraw = function()
	{
		this.Clear();
		this.Draw();
	}
	
	this.SetStart = function(location)
	{
		if(this.start != location)
		{
			this.start = location;
			this.Redraw();
		}
	}
	
	this.SetEnd = function(location)
	{
		if(this.end != location)
		{
			this.end = location;
			this.Redraw();
		}
	}
	
	this.SetColor = function(color)
	{
		this.color = color;
		
		this.Redraw();
	}
	
	this.SetWidth = function(width)
	{
		this.width = width;
		
		this.Redraw();
	}
};

// JavaScript Document
// This class extends Math class adding following functions to it

// Rounds a number to a specified number of decimal places
// Optional parameter [Decimal Places] default is 1
Number.prototype.roundTo = function()
{
	num = parseFloat(this)
	var _args = Number.prototype.roundTo.arguments
	var dec = (_args.length > 0)? Math.pow(10,parseInt(_args[0])) : 1
	
	return Math.round(num*dec)/dec;
}

// returns boolean stating if number is valid integer
Number.prototype.isInt = function()
{
	return (this === parseInt(this));
}

// returns boolean stating if number is valid decimal
Number.prototype.isDecimal = function()
{
	return (this !== parseInt(this) && this === parseFloat(this));
}

// Converts number to an Integer
Number.prototype.toInteger = function()
{
	return parseInt(this);
}

Number.prototype.Add = function(number)
{
	return this + parseFloat(number);
}

Number.prototype.Random = function()
{
	return Math.floor(Math.random() * this);
}

Number.prototype.similarTo = function(number, offset)
{
	var from = this - offset;
	var to = this + offset;
	
	return (from <= number && number <= to);
}


// JavaScript Document
VitaminXP.Namespace("VitaminXP.String");

// Returns the Amount of occurences
String.prototype.Find = function(string)
{
	var position = 0;
	var results = 0;
	
	for(i = 0; i < this.length; i++)
	{
		position = this.indexOf(string, i);
		
		if(position >= 0)
		{
			results++;
			i = position + string.length - 1;
		}else{
			i = this.length;
		}
	}
	
	return results;
}

// Returns true if string is in valid eMail format
String.prototype.isValidEmail = function()
{
	if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/.test(this)){
		return true
	}else{
		return false
	}
}

String.prototype.EncodeURL = function()
{
	url = this.replace(RegExp("\\\\","g"),"/");
	return encodeURI(url);
}

// returns an array of strings that are seperated by passed seperator string
String.prototype.toArray = function(seperator)
{
	var _arr = new Array();
	var _items = this.split(seperator)
	var temp;
	
	for(r = 0; r < _items.length; r++){
		temp = _items[r].split("=");
		_arr[temp[0]] = temp[1];
	}
	
	return _arr
}

// returns boolean stating if number is valid integer
String.prototype.isInt = function()
{
	return (this == parseInt(this));
}

// returns boolean stating if number is valid decimal
String.prototype.isDecimal = function()
{
	return (this == parseFloat(this));
}

// Converts number to an Integer
String.prototype.toInteger = function()
{
	return parseInt(this);
}

// Converts number to an Decimal
String.prototype.toDecimal = function()
{
	return parseFloat(this);
}

// Converts number to an number (Decimal)
String.prototype.toNumber = function()
{
	return parseFloat(this);
}

// Adds or replaces existing value for variable
String.prototype.BuildQuery = function(name, value)
{
	var url = (this.length > 0)? this : window.location.search;
	//if(url.substr(0,1) == "?") url = url.substr(1, url.length);
	
	var start = [url.indexOf("?" + name), url.indexOf("&" + name)].Max();
	
	if(start > -1)
	{
		start += 1 + name.length
		var end = url.indexOf("&", start);
		
		url = url.substring(0, start) + "=" + escape(value) + ((end > -1)? url.substring(end, url.length) : "");
	}
	else
	{
		url += ((url.length <= 1)? name + "=" + escape(value) : "&" + name + "=" + escape(value));
	}
	
	return url;
}

String.prototype.Trim = function()
{
	var _args = String.prototype.Trim.arguments;
	var _characters = (_args.length > 0) ? _args[0] : " ";
	var trim = { right:true, left:true };
	var string = this;
	
	if(_args.length > 1)
	{
		switch(_args[1])
		{
			case "right":
				trim.left = false;
				break;
			
			case "left":
				trim.right = false;
				break;
		}
	}
	
	if(typeof _characters == 'string')
	{
		_characters = new Array(_characters);
	}
	
	for(var i = 0; i < _characters.length; i++)
	{
		if(trim.left)
		{
			while(string.charAt(0) == _characters[i]) string = string.substring(1, string.length);
		}
		
		if(trim.right)
		{
			while(string.charAt(string.length - 1) == _characters[i]) string = string.substring(0, string.length - 1);
		}
	}
	
	return string;
}

String.prototype.RightTrim = function()
{
	var _args = String.prototype.RightTrim.arguments;
	var _characters = (_args.length > 0) ? _args[0] : " ";
	
	return this.Trim(_characters, "right");
}

String.prototype.LeftTrim = function()
{
	var _args = String.prototype.LeftTrim.arguments;
	var _characters = (_args.length > 0) ? _args[0] : " ";
	
	return this.Trim(_characters, "left");
}

String.prototype.replaceString = function(from, to)
{
	var str = this.toString();
	var p = str.indexOf(from);

	while(p >= 0)
	{
		str = str.replace(from, to);
		
		p = str.indexOf(from, p + to.length);
	}
	
	return str;
}


// Detects players/browser/OS and other stuff

VitaminXP.Namespace("VitaminXP.System");

VitaminXP.System.isPlayerInstalled = function(player_name)
{
	var result = undefined;
	
	// Check if can detect player
	if(VitaminXP.System.IECompatible || (navigator.plugins && navigator.plugins.length > 0))
	{
		// Do nothing
	}
	else
	{
		return result; // undefined (because can not check)
	}
	
	switch(player_name)
	{
		case "windows_media":
			
			result = VitaminXP.System.DetectPlugin('Windows Media', 'Pl');
			
			if(!result && VitaminXP.System.IECompatible)
			{
				result = VitaminXP.System.DetectActiveXControl('MediaPlayer.MediaPlayer.1');
			}
			
			break;
		
		case "real":
			
			result = VitaminXP.System.DetectPlugin('RealPlayer');
			
			if(!result && VitaminXP.System.IECompatible)
			{
				result = (VitaminXP.System.DetectActiveXControl('rmocx.RealPlayer G2 Control') ||
					VitaminXP.System.DetectActiveXControl('RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)') ||
					VitaminXP.System.DetectActiveXControl('RealVideo.RealVideo(tm) ActiveX Control (32-bit)'));
			}
			
			break;
		
		case "quicktime":
			
			result = VitaminXP.System.DetectPlugin('QuickTime');
			
			if(!result && VitaminXP.System.IECompatible)
			{
				try
				{
					var QTChecker = new ActiveXObject("QuickTimeCheckObject.QuickTimeCheck.1");
					
					result = QTChecker.IsQuickTimeAvailable(0);
				}
				catch(ex)
				{
					result = false;
				}
			}
			
			break;
		
		case "flip":
			
			result = VitaminXP.System.DetectPlugin('Flip4Mac WMV Web Plugin');
			
			break;
		
		case "flash":
			
			result = VitaminXP.System.DetectPlugin('Shockwave','Flash');
			
			if(!result && VitaminXP.System.IECompatible)
			{
				result = VitaminXP.System.DetectActiveXControl('ShockwaveFlash.ShockwaveFlash.1');
			}
			
			break;
		
		case "director":
			
			result = VitaminXP.System.DetectPlugin('Shockwave','Director');
			
			if(!result && VitaminXP.System.IECompatible)
			{
				result = VitaminXP.System.DetectActiveXControl('SWCtl.SWCtl.1');
			}
			
			break;
		case "html5":
			try
			{
				var obj = new Audio();
				
				_mp3_mime_types = ['audio/mpeg; codecs="mp3"','audio/mpeg','audio/mp3','audio/MPA','audio/mpa-robust'];
				
				for(var i = 0; i < _mp3_mime_types.length; i++)
				{
					var answer = obj.canPlayType(_mp3_mime_types[i]);
					if(answer != '' && 'probably maybe yes'.indexOf(answer) > -1)
					{
						result = true;
						break;
					}
				}
			}
			catch(ex)
			{
				result = false;
			}
			break;
	}
	
	return result;
}

VitaminXP.System.DetectPlugin = function()
{
	var pluginFound = false;
	
	// allow for multiple checks in a single pass
    var daPlugins = VitaminXP.System.DetectPlugin.arguments;
    
    // consider pluginFound to be false until proven true
    var pluginFound = false;
    
    // if plugins array is there and not fake
    if (navigator.plugins && navigator.plugins.length > 0)
    {
		var pluginsArrayLength = navigator.plugins.length;
		
		// for each plugin...
		for (pluginsArrayCounter=0; pluginsArrayCounter < pluginsArrayLength; pluginsArrayCounter++ )
		{
			// loop through all desired names and check each against the current plugin name
			var numFound = 0;
		    
			for(namesCounter=0; namesCounter < daPlugins.length; namesCounter++)
			{
				//	document.writeln((navigator.plugins[pluginsArrayCounter].name) + '<br>');
				//	document.writeln((navigator.plugins[pluginsArrayCounter].description) + '<br>');
				// if desired plugin name is found in either plugin name or description
				if( (navigator.plugins[pluginsArrayCounter].name.indexOf(daPlugins[namesCounter]) >= 0) || (navigator.plugins[pluginsArrayCounter].description.indexOf(daPlugins[namesCounter]) >= 0) )
				{
					// this name was found
					numFound++;
				}   
			}
		    
			// now that we have checked all the required names against this one plugin,
			// if the number we found matches the total number provided then we were successful
			if(numFound == daPlugins.length)
			{
				pluginFound = true;
				// if we've found the plugin, we can stop looking through at the rest of the plugins
				break;
			}
		}
    }
    
    return pluginFound;
}

VitaminXP.System.DetectActiveXControl = function(activeXControlName)
{
	try
	{
		return (typeof new ActiveXObject(activeXControlName) == 'object');
	}
	catch(ex)
	{
		return false;
	}
}

VitaminXP.System.DetectBrowser = function()
{
	var agt=navigator.userAgent.toLowerCase();
    if (agt.indexOf("opera") != -1) return 'Opera';
    if (agt.indexOf("staroffice") != -1) return 'Star Office';
    if (agt.indexOf("webtv") != -1) return 'WebTV';
    if (agt.indexOf("beonex") != -1) return 'Beonex';
    if (agt.indexOf("chimera") != -1) return 'Chimera';
    if (agt.indexOf("netpositive") != -1) return 'NetPositive';
    if (agt.indexOf("phoenix") != -1) return 'Phoenix';
    if (agt.indexOf("firefox") != -1) return 'Firefox';
    if (agt.indexOf("safari") != -1) return 'Safari';
    if (agt.indexOf("skipstone") != -1) return 'SkipStone';
    if (agt.indexOf("msie") != -1) return 'Internet Explorer';
    if (agt.indexOf("netscape") != -1) return 'Netscape';
    if (agt.indexOf("mozilla/5.0") != -1) return 'Mozilla';
    if (agt.indexOf('\/') != -1) {
    if (agt.substr(0,agt.indexOf('\/')) != 'mozilla') {
    return navigator.userAgent.substr(0,agt.indexOf('\/'));}
    else return 'Netscape';} else if (agt.indexOf(' ') != -1)
    return navigator.userAgent.substr(0,agt.indexOf(' '));
    else return navigator.userAgent;
}

VitaminXP.System.DetectOperatingSystem = function()
{
	var OSName="Unknown";
	
	if (navigator.appVersion.indexOf("Win")!=-1) OSName="Windows";
	if (navigator.appVersion.indexOf("Mac")!=-1) OSName="MacOS";
	if (navigator.appVersion.indexOf("X11")!=-1) OSName="UNIX";
	if (navigator.appVersion.indexOf("Linux")!=-1) OSName="Linux";
	if (navigator.appVersion.indexOf("iPhone")!=-1) OSName="iPhone";
	if (navigator.appVersion.indexOf("iPad")!=-1) OSName="iPad";
	if (navigator.appVersion.indexOf("iPod")!=-1) OSName="iPod";
	
	return OSName;
}

VitaminXP.System.DetectOperatingSystemVersion = function()
{
	var version="Unknown";
	
	if (navigator.userAgent.toLowerCase().indexOf("win98")!=-1) version="98";
	if (navigator.userAgent.toLowerCase().indexOf("windows 98")!=-1) version="2000";
	if (navigator.userAgent.toLowerCase().indexOf("nt 5.0")!=-1) version="2000";
	if (navigator.userAgent.toLowerCase().indexOf("nt 5.1")!=-1) version="XP";
	if (navigator.userAgent.toLowerCase().indexOf("nt 6.0")!=-1) version="Vista";
	if (navigator.userAgent.toLowerCase().indexOf("ppc")!=-1) version="Power PC";
	if (navigator.userAgent.toLowerCase().indexOf("powerpc")!=-1) version="Power PC";
	if (navigator.userAgent.toLowerCase().indexOf("68k")!=-1) version="68000";
	
	return version;
}

VitaminXP.System.Browser = VitaminXP.System.DetectBrowser();
VitaminXP.System.OS = VitaminXP.System.DetectOperatingSystem();
VitaminXP.System.OSVersion = VitaminXP.System.DetectOperatingSystemVersion();
VitaminXP.System.IECompatible = document.all ? true : false;

VitaminXP.System.getFlashVersion = function()
{
	var version = '0,0,0';
	
	// ie
	try
	{
		try
		{
			var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
			
			try
			{
				axo.AllowScriptAccess = 'always';
			}
			catch(e)
			{
				version = '6,0,0';
			}
		}
		catch(e)
		{
			// do nothing
		}
		
		version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
	}
	catch(e)
	{
		// other browsers
		try
		{
			if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)
			{
				version = (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
			}
		}
		catch(e)
		{
			// do nothing
		}
	}
	
	return version.split(',').shift();
}


// Create NameSpaces
VitaminXP.Namespace("Timeline");

VitaminXP.Timeline.FramesPerSecond = 15; // In miliseconds
VitaminXP.Timeline.FrameLength = 1000 / VitaminXP.Timeline.FramesPerSecond;
VitaminXP.Timeline.Timer = null; // Container of the timer
VitaminXP.Timeline._scene = [];

VitaminXP.Timeline.ExecuteFrames = function()
{
	for(i = 0; i < VitaminXP.Timeline._scene.length; i++){
		try{
			VitaminXP.Timeline._scene[i].ExecuteFrame();
		}catch(ex){
			window.status = 'Exeption: ' + ex;
		}
	}
};

VitaminXP.Timeline.Timer = setInterval(VitaminXP.Timeline.ExecuteFrames, VitaminXP.Timeline.FrameLength);

VitaminXP.Timeline.AddScene = function(scene)
{
	VitaminXP.Timeline._scene[VitaminXP.Timeline._scene.length] = scene;
}

VitaminXP.Timeline.RemoveScene = function(scene)
{
	this._new_array = new Array();
	
	for(i = 0; i < VitaminXP.Timeline._scene.length; i++)
	{
		if(VitaminXP.Timeline._scene[i] != scene)
		{
			this._new_array[this._new_array.length] = VitaminXP.Timeline._scene[i];
		}
	}
	
	VitaminXP.Timeline._scene = this._new_array;
}

// Create a Blank Scene instence
VitaminXP.Timeline.Scene = function()
{
	// Properties
	this._frame = new Array();
	this.CurrentFrame = 0;
	this.Frames = 0;
	this.State = "Stopped"; // [Stopped | Playing | Paused]
	this.Repeat = false;
	
	// Events
	this.OnStateChange = '';
	this.OnFrameChange = '';
	
	// Methods
	this.AddEvent = function(frame_number, event_string)
	{
		event_string = event_string.replace(" ","");
		
		if(frame_number >= 0 && event_string.length > 0)
		{
			if(event_string.substr(event_string.length - 1, 1) != ";") event_string += ";";
			
			this._frame[frame_number] = (!this._frame[frame_number])? event_string : this._frame[frame_number] + event_string;
		}
		
		// Set amount of frames in this scene
		if(frame_number > this.Frames) this.Frames = frame_number
	}
	
	this.RemoveEvent = function(frame_number, event_string)
	{
		event_string = event_string.replace(" ","");
		
		// remove the passed event
		var _events = this._frame[frame_number].split(";");
		var new_event_list = '';
		
		if(_events.length > 0)
		{
			for(i = 0; i < _events.length; i++)
			{
				if(_events[i] != event_string)
				{
					if(new_event_list != '') new_event_list += ';';
					new_event_list += _events[i];
					
					i = _events.length;
				}
			}
		}
		
		this._frame[frame_number] = new_event_list;
		
		// Remove the current event that called this functions
		var _events = this._frame[this.CurrentFrame].split(";");
		var new_event_list = '';
		
		if(_events.length > 0)
		{
			for(i = 0; i < _events.length; i++)
			{
				if(_events[i] != "this.RemoveEvent(frame_number,'" + event_string + "')")
				{
					if(new_event_list != '') new_event_list += ';';
					new_event_list += _events[i];
					
					i = _events.length;
				}
			}
		}
		
		this._frame[this.CurrentFrame] = new_event_list;
		
		// Calculate total amount of frames in this scene after removing the event
		var LastActiveFrame = 0;
		
		for(i = 1; i <= this.Frames; i++)
		{
			if(this._frame[i]) LastActiveFrame = i;
		}
		
		if(LastActiveFrame < this.Frames) this.Frames = LastActiveFrame
	}
	
	this.Play = function()
	{
		if(this.State == "Stopped") this.CurrentFrame = 0;
		this.State = "Playing";
		VitaminXP.Timeline.AddScene(this);
		
		if(this.OnStateChange != '') eval(this.OnStateChange);
	}
	
	this.Pause = function()
	{
		this.State = "Pause";
		VitaminXP.Timeline.RemoveScene(this);
		
		if(this.OnStateChange != '') eval(this.OnStateChange);
	}
	
	this.Stop = function()
	{
		this.State = "Stopped";
		VitaminXP.Timeline.RemoveScene(this);
		
		if(this.OnStateChange != '') eval(this.OnStateChange);
	}
	
	this.GoToFrame = function(frame_number)
	{
		this.CurrentFrame = frame_number;
	}
	
	this.ExecuteFrame = function()
	{
		if(this.State == "Playing" && this.CurrentFrame <= this.Frames)
		{
			if(this._frame[this.CurrentFrame])
			{
				try
				{
					eval(this._frame[this.CurrentFrame]);
				}
				catch(ex)
				{
					window.status = ex;
				}
			}
			
			try
			{
				if(this.OnFrameChange != '') eval(this.OnFrameChange);
			}
			catch(ex)
			{
				window.status = ex;
			}
			
			this.CurrentFrame ++;
		}
		else if(this.State == "Playing")
		{
			if(this.Repeat === true)
			{
				this.CurrentFrame = 0;
			}
			else
			{
				this.Stop();
			}
		}
		
		var dat = new Date();
		//window.status = this.State + " Frame: " + this.CurrentFrame + " Time: " + (dat.getSeconds())
	}
	
	this.GetProgress = function()
	{
		return Math.round((this.CurrentFrame / this.Frames) * 100);
	}
};

VitaminXP.HideLoadingStatusMessage();
