﻿var		IsIE6				= /*@cc_on !window.XMLHttpRequest  || @*/false;
var		IEBody				= (document.compatMode && document.compatMode != "BackCompat")? document.documentElement : document.body
var		IsIE				= typeof document.attachEvent!="undefined";
var		IsIE8OrLess			= IsIE==false ? false : typeof document.body.style.opacity=="undefined";
// Fixes IE9's console.log
if (Function.prototype.bind && console && typeof console.log == "object") 
{  
	[    "log","info","warn","error","assert","dir","clear","profile","profileEnd"  ]
				.forEach(function (method) 
					{    console[method] = this.call(console[method], console);  }, 
				Function.prototype.bind);
}
// Attempts to provide prototype functionality for browsers that don't have ECMA5. Doesn't work in IE7/6 (don't know why)
if ((Function.prototype) && (typeof Array.forEach=="undefined"))
{
	Array.prototype.forEach = function(object, block, context)
	{
		for (var i = 0; i < object.length; i++) 
		{
			block.call(context, object[i], i, object);
		}
	};
}
var		LastLogged		=	null;
/**  * The purpose of this function is to begin the fading out of an element.
	* @param {HtmlElement}	element				The Html Element to fade out.
	* @param {Integer}		durationInMS		The duration of the whole fade-out process in milliseconds
	* @param {Integer}		intervalPeriods		The frequency at which the element should be faded out. Recommended values will usually be 10-30 times per 1000 milliseconds (1 second). The higher the more seamless the transition will be.
	* @param {Integer}		activeFadeAction	If provided should be a reference to a just incremented Global variable that is used to stop the fading action. Will be compared to window.ActiveFadeAction. Simply do not provide this value if you do not wish to use this feature.
	*/
function	FadeOut				(element, durationInMS, intervalPeriods, activeFadeAction)							
{
	if ((typeof intervalPeriods=="undefined") || (intervalPeriods==null))
		{ intervalPeriods = 10; }
	var		Decrement		= -1 / intervalPeriods;
	FadeCallback(element, 1, Decrement, 0, durationInMS / intervalPeriods, activeFadeAction);
}
/**  * The purpose of this function is to begin the fading in of an element.
	* @param {HtmlElement}	element				The Html Element to fade in.
	* @param {Integer}		durationInMS		The duration of the whole fade-in process in milliseconds
	* @param {Integer}		intervalPeriods		The frequency at which the element should be faded out. Recommended values will usually be 10-30 times per 1000 milliseconds (1 second). The higher the more seamless the transition will be.
	* @param {Integer}		activeFadeAction	If provided should be a reference to a just incremented Global variable that is used to stop the fading action. Will be compared to window.ActiveFadeAction. Simply do not provide this value if you do not wish to use this feature.
	*/
function	FadeIn				(element, durationInMS, intervalPeriods, activeFadeAction)							
{
	if ((typeof intervalPeriods=="undefined") || (intervalPeriods==null))
		{ intervalPeriods = 10; }
	var		Increment		= 1 / intervalPeriods;
	FadeCallback(element, 0, Increment, 1, durationInMS / intervalPeriods, activeFadeAction);
}
/**  * The purpose of this function is to fading an @element from it's current opacity level to the value of @destOpacity.
	* @param {HtmlElement}	element				The Html Element to fade in.
	* @param {Double}		destOpacity			The destination of the opacity.
	* @param {Integer}		durationInMS		The duration of the whole fade-in process in milliseconds
	* @param {Integer}		intervalPeriods		The frequency at which the element should be faded out. Recommended values will usually be 10-30 times per 1000 milliseconds (1 second). The higher the more seamless the transition will be.
	* @param {Integer}		activeFadeAction	If provided should be a reference to a just incremented Global variable that is used to stop the fading action. Will be compared to window.ActiveFadeAction. Simply do not provide this value if you do not wish to use this feature.
	*/
function	FadeTo				(element, destOpacity, durationInMS, intervalPeriods, activeFadeAction, sCompletedCallback)
{
	if ((typeof intervalPeriods=="undefined") || (intervalPeriods==null))
		{ intervalPeriods = 10; }
	var		CurrentOpacity		= parseFloat(element.style.opacity);
	if (isNaN(CurrentOpacity)==true)
	{
		if (IsIE8OrLess==true)
		{
			var AlphaFilter		= null;
			var Errored			= false;
			var Exception		= null;
			try { AlphaFilter = element.filters.item("DXImageTransform.Microsoft.Alpha"); }
				catch (ex) { Errored = true; Exception = ex; }
			if (Errored==true)
				{ /* created */ }
			if (AlphaFilter==null)
			{ 
				element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=100)'; 
				AlphaFilter	= element.filters.item('DXImageTransform.Microsoft.Alpha');
			}
			if (AlphaFilter==null)
				{ alert('filter was null after creation'); return; }
		}
		CurrentOpacity		= 1;
	}
	if ((CurrentOpacity<=0) && (destOpacity>CurrentOpacity))
		{ element.style.display = ''; }
	var		Increment			= (destOpacity - CurrentOpacity) / (durationInMS / intervalPeriods);
	//LogMessage('Starting Fade To from ' + CurrentOpacity + ' to ' + destOpacity + " at {0} and it should take " + durationInMS + " millieseconds at + " + intervalPeriods + " with an increment of " + Increment + ".");
	FadeCallback(element, CurrentOpacity, Increment, destOpacity, durationInMS / intervalPeriods, activeFadeAction, sCompletedCallback);
}
/** * Used internally to alter the opacity of an @element. This method calls itself at the @interval specified by @durationInMS until value exceeds the value of stopAt (where exceeds may be is less than or greater than depending upon the sign of @interval.
	* Supports Internet Explorer 6-8 where DXImageTransform.Microsoft.Alpha filters are supported. Supports all browsers that implement the CSS 3 Opacity attribute. 
	* @param {HtmlElement}	element				The Html Element to fade in.
	* @param {Double}		value				A value in between 0 and 1 that defines the new opacity. (A percentage).
	* @param {Double}		increment			The amount by which the value should be incremented for the next call.
	* @param {Integer}		durationInMS		The duration of the current fade-in step (Used by @FadeOut / @FadeIn so this is the parameters from those functions durationInMS / intervalPeriods)
	* @param {Integer}		intervalPeriods		The frequency at which the element should be faded out. Recommended values will usually be 10-30 times per 1000 milliseconds (1 second). The higher the more seamless the transition will be.
	* @param {Integer}		activeFadeAction	If provided should be a reference to a just incremented Global variable that is used to stop the fading action. Will be compared to window.ActiveFadeAction. Simply do not provide this value if you do not wish to use this feature.
	*/
function	FadeCallback		(element, value, increment, stopAt, durationInMS, activeFadeAction, sCompletedCallback)			
{
	if ((typeof activeFadeAction!="undefined") && (activeFadeAction!=null) && (ActiveFadeAction!=activeFadeAction))
		{ return; }
	if (IsIE8OrLess==true)
	{ 
		var AlphaFilter		= null;
		var Errored			= false;
		var Exception		= null;
		try { AlphaFilter = element.filters.item("DXImageTransform.Microsoft.Alpha"); }
			catch (ex) { Errored = true; Exception = ex; }
		if (Errored==true)
			{ /* created */ }
		if (AlphaFilter==null)
		{ 
			element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=100)'; 
			AlphaFilter	= element.filters.item('DXImageTransform.Microsoft.Alpha');
		}
		if (AlphaFilter==null)
			{ alert('filter was null after creation'); return; }
		AlphaFilter.opacity = value * 100; 
	}
	else 
		{ element.style.opacity	= value; }
	value += increment;
	if (((increment<0) && (value>stopAt)) || ((increment>0) && (value<=stopAt)))
		{ setTimeout(function() { FadeCallback(element, value, increment, stopAt, durationInMS, activeFadeAction, sCompletedCallback); }, durationInMS); }
	else 
	{ 
		if (value<=0) { element.style.display = 'none'; }
		if ((typeof sCompletedCallback!="undefined") && (sCompletedCallback!=null))
			{ sCompletedCallback(); }
		LogMessage('Stopping at ' + value + ' with increment of ' + increment + ' and stop value at ' + stopAt + ' End time of : {0} with a difference of {1} from {2}'); 
	}
}
/**
	* Returns the absolute position of an element by calculating scrollLeft and scrollTop and navigating it's offsetParent.
	* @param {HtmlElement}	element				The Html Element to calculate the absolute position of.
	@returns {x, y}			Returns a structure holding the calculated scrollLeft and scrollTop in an .x/.y structure.
*/
function GetAbsolutePosition(element)
{
	var x=0;
	var y=0;
	while (element!=null)
	{
		x+=element.offsetLeft-element.scrollLeft;
		y+=element.offsetTop-element.scrollTop;
		element=element.offsetParent;
	}
	return { x:x, y:y};
}
/**
	* Returns the Window's ScrollLeft and ScrollTop. Attempts to take various browser inconsistencies into consideration.
	@returns {ScrollLeft, ScrollTop}	Returns a structre holding the ScrollLeft and ScrollTop pulled from scrollLeft/scrollTop or pageXOffset/pageYOffset
*/
function GetWindowScrollInfo()
{
	var ScrollLeft =	IEBody.scrollLeft	? IEBody.scrollLeft		: window.pageXOffset;
	var ScrollTop =		IEBody.scrollTop	? IEBody.scrollTop		: window.pageYOffset;
	if (isNaN(ScrollLeft))
		{ ScrollLeft	= 0; }
	else 
		{ ScrollLeft = parseInt(ScrollLeft, 10); }
	if (isNaN(ScrollTop))
		{ ScrollTop		= 0; }
	else 
		{ ScrollTop = parseInt(ScrollTop, 10); }
	return { ScrollLeft: ScrollLeft, ScrollTop:ScrollTop };
}
/**
	* Attempts to Return the browser viewport width and height.
	@returns {Width, Height}	Returns a structure holding the Viewport's width and height pulled from innerWidth/innerHeight or documentElement.offsetWidth/documentElement.offsetHeight.
*/
function GetBodyViewportDimensions		()
{
	var WindowHeight	= 0;
	var WindowWidth		= 0;
	if (typeof window.innerHeight!="undefined")
	{
		WindowWidth		= window.innerWidth;
		WindowHeight	= window.innerHeight;
	}
	else if (document.documentElement)
	{
		WindowWidth		= document.documentElement.offsetWidth; 
		WindowHeight	= document.documentElement.offsetHeight; 
	}
	return { Width: WindowWidth, Height: WindowHeight };
}
/*
	* Inserts the element before the parent's next sibling if it's available otherwise it appends the child to the parent's parent's children collection.
	* @param {HtmlElement}		element		Element to insert
	* @param {HtmlEleemnt}		parent		Parent that the element is going to be inserted after.
*/
function InsertElementAfter		(element, parent) 
{  
	if (parent.nextSibling) 
		{ parent.parentNode.insertBefore(element, parent.nextSibling); } 
	else 
		{ parent.parentNode.appendChild(element);}
}

function LogMessage(message)
{
	var		TmpDate		= new Date();
	var		Difference	= (TmpDate - LastLogged);
	message				= message
								.replace(/\{0\}/, TmpDate.getSeconds() + "." + TmpDate.getMilliseconds())
								.replace(/\{1\}/, Difference)
								.replace(/\{2\}/, (LastLogged==null) ? null : (LastLogged.getSeconds() + "." + LastLogged.getMilliseconds()))
							;
	LastLogged			= TmpDate;
	if (typeof console=="undefined")
		{ /* alert(message); */ }
	else 
		{ console.log(message); }
}
/** 
	* Centers an @element via absolutely positioning in the middle of the browser's viewport taking scrolling into account. By specifying @ensureFit you can ensure that the element will fit.
	* @param (HtmlElement)	element			Element to absolutely position.
	* @param (Boolean)		ensureFit		If true then a check is done to ensure that the control fits vertically and horizontally in the viewport. If not then overflow is set to auto.
*/
function	CenterAbsPosDomElemnt		(element, ensureFit, zIndex)
{
	if ((typeof zIndex=="undefined") || (zIndex==null))
		{ zIndex	= 500; }
	var		ScrollInfo				= GetWindowScrollInfo();
	var		WindowDimensions		= GetBodyViewportDimensions();
	//alert(WindowDimensions.Width + 'x' + WindowDimensions.Height + ' - ' + ScrollInfo.ScrollLeft + 'x' + ScrollInfo.ScrollTop);
	element.style.position			= 'absolute';
	element.style.display			= '';
	element.style.left				= (WindowDimensions.Width	- element.offsetWidth)/2	+ ScrollInfo.ScrollLeft		+ 'px';
	element.style.top				= (WindowDimensions.Height	- element.offsetHeight)/2	+ ScrollInfo.ScrollTop		+ 'px';
	element.style.zIndex			= zIndex;
	if ((ensureFit==true) && ((element.offsetWidth>WindowDimensions.Width) || (element.offsetHeight>WindowDimensions.Height)))
	{
		element.setAttribute("data-EnsureFit",					"true"						);
		element.setAttribute("data-PriorOverflow",				element.style.overflow		);
		if (element.offsetWidth>WindowDimensions.Width)
		{ 
			if ((typeof PriorWidth=="undefined") || (PriorWidth==null))
				{ element.setAttribute("data-PriorWidth",			element.style.width		); }
			var		PaddingLeft		= parseInt(element.style.paddingLeft		);
			var		PaddingRight	= parseInt(element.style.paddingRight	);
			if (isNaN(PaddingLeft)==true)		{ PaddingLeft		= 0; }
			if (isNaN(PaddingRight)==true)		{ PaddingRight		= 0; }
			element.style.width	= (WindowDimensions.Width - PaddingLeft - PaddingRight) + 'px';
			element.style.left		= '0px';
		}
		if (element.offsetHeight>WindowDimensions.Height)
		{ 
			
			var		PriorHeight		= element.getAttribute("data-PriorHeight");
			if ((typeof PriorHeight=="undefined") || (PriorHeight==null))
				{ element.setAttribute("data-PriorHeight",			element.style.height		); }
			var		PaddingTop		= parseInt(element.style.paddingTop		);
			var		PaddingBottom	= parseInt(element.style.paddingBottom	);
			if (isNaN(PaddingTop)==true)		{ PaddingTop		= 0; }
			if (isNaN(PaddingBottom)==true)		{ PaddingBottom		= 0; }
			element.style.height	= (WindowDimensions.Height - PaddingTop - PaddingBottom) + 'px';
			element.style.top		= '0px';
		}
		if (typeof element.style.overflowX!="undefined")	
			{ element.setAttribute("data-PriorOverflowX",		element.style.overflowX		);	}
		if (typeof element.style.overflowY!="undefined")		
			{ element.setAttribute("data-PriorOverflowY",		element.style.overflowY		);	}
		element.style.overflow		= 'auto';
	} 
	else if ((ensureFit==true) && (element.getAttribute("data-EnsureFit")=="true"))
	{
		var		PriorOverflow		= element.getAttribute("data-PriorOverflow"		);
		var		PriorOverflowX		= element.getAttribute("data-PriorOverflowX"	);
		var		PriorOverflowY		= element.getAttribute("data-PriorOverflowY"	);
		var		PriorWidth			= element.getAttribute("data-PriorWidth"		);
		var		PriorHeight			= element.getAttribute("data-PriorHeight"		);
		if (typeof PriorOverflow!="undefined")			{	element.style.overflow		= PriorOverflow;		element.removeAttribute("data-PriorOverflow"	);	}
		if (typeof PriorOverflowX!="undefined")			{	element.style.overflowX		= PriorOverflowX;		element.removeAttribute("data-PriorOverflowX"	);	}
		if (typeof PriorOverflowY!="undefined")			{	element.style.overflowY		= PriorOverflowY;		element.removeAttribute("data-PriorOverflowY"	);	}
		if (typeof PriorWidth!="undefined")				{	element.style.width			= PriorWidth;			element.removeAttribute("data-PriorWidth"		);	}
		if (typeof PriorHeight!="undefined")			{	element.style.height		= PriorHeight;			element.removeAttribute("data-PriorHeight"		);	}
	}
}
function AttachEvent				(mObject, eventName, eventHandler)
{
	if (mObject.addEventListener)
		{ mObject.addEventListener(eventName, eventHandler, false);		}
	else if (mObject.attachEvent)
		{ mObject.attachEvent("on" + eventName, eventHandler);			}
}
