/**
 * @fileoverview Provides essential methods to fill
 * gaps between what the user agent supports and what
 * should be available using ECMAScript.
 *
 * @author Michael R. Havard mhavard@express-scripts.com
 * @filename ECMAFixes.js
 * @version	1.0.0
 */
/* ***************
 **  Constants  **
 *************** */
	if (!window.Node) 
	{
    	var Node = {          
			ELEMENT_NODE: 1,
			ATTRIBUTE_NODE: 2,
			TEXT_NODE: 3, 
			COMMENT_NODE: 8,
			DOCUMENT_NODE: 9,
			DOCUMENT_FRAGMENT_NODE: 11
		}
	} 
 
/* ********************************
 **  Supplimental Array Methods  **
 ******************************** */

	if(typeof(Function.prototype.apply) === "undefined")
	{
	    Function.prototype.apply = function (oObject, aArguments)
	    {
	        var oReturn;
	        var oObject = (typeof(oObject) === "undefined")? new Object(): oObject;
	        oObject.__apply = this;
	        var iLen = (typeof(aArguments) === "undefined")? 0: aArguments.length;
	 
	        /* for efficiency the arguments are rolled out into a case statement.
	           If there are more than 10 arguments (rare) then we can use a loop */
	        switch(iLen)
	        {
	            case 0: oReturn = oObject.__apply(); break; 
	            case 1: oReturn = oObject.__apply(aArguments[0]); break; 
	            case 2: oReturn = oObject.__apply(aArguments[0], aArguments[1]); break; 
	            case 3: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2]); break; 
	            case 4: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2], aArguments[3]); break; 
	            case 5: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2], aArguments[3], aArguments[4]); break; 
	            case 6: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2], aArguments[3], aArguments[4], aArguments[5]); break; 
	            case 7: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2], aArguments[3], aArguments[4], aArguments[5], aArguments[6]); break; 
	            case 8: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2], aArguments[3], aArguments[4], aArguments[5], aArguments[6], aArguments[7]); break; 
	            case 9: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2], aArguments[3], aArguments[4], aArguments[5], aArguments[6], aArguments[7], aArguments[8]); break; 
	            case 10: oReturn = oObject.__apply(aArguments[0], aArguments[1], aArguments[2], aArguments[3], aArguments[4], aArguments[5], aArguments[6], aArguments[7], aArguments[8], aArguments[9]); break; 
	
	            default:
	                for(var i = 0, sStr = ""; i < iLen; i++)
	                {
	                    sStr += (i !== 0)? ",aArguments[" + i + "]": "aArguments[" + i + "]";
	                    oReturn = eval("oObject.__apply(" + sStr + ")");
	                }
	        }
	        /* destroy the temporary apply call */
	        oObject.__apply = null;
	        return oReturn;            
	    };
	}
	if(typeof(Function.prototype.call) === "undefined")
	{
	    Function.prototype.call = function(oObject)
	    {
	        var aArguments = new Array(arguments.length -1);
	        var iLen = arguments.length;
	        for(var i = 1; i < iLen; i++)
	        {
	            aArguments[i -1] = arguments[i];
	        }
	        return this.apply(oObject, aArguments);
	    };
	}
	if(typeof(Array.prototype.concat) === "undefined")
	{
	    Array.prototype.concat = function(aCatArray)
	    {
	        var aArray = this.copy();
	        var iLen = aCatArray.length;
	        for(var i = 0; i < iLen; i++)
	        {
	            aArray[aArray.length] = aCatArray[i];
	        }
	        return aArray;
	    };
	}
	if(typeof(Array.prototype.copy) === "undefined")
	{
	    Array.prototype.copy = function()
	    {
	        var aCopy = new Array();
	        var iLen = this.length;
	        for(var i = 0; i < iLen; i++)
	        {
	            aCopy[i] = this[i];
	        }
	        return aCopy;
	    };
	}
	if(typeof(Array.prototype.pop) === "undefined")
	{
	    Array.prototype.pop = function()
	    {
	        if(this.length === 0)
	        {
	            try
	            {
	                return undefined;
	            }
	            catch(e)
	            {
	                return null;
	            }
	        }
	        else
	        {
	            return this[this.length--];
	        }
	    };
	}
	if(typeof(Array.prototype.push) === "undefined")
	{
	    Array.prototype.push = function()
	    {
	        var iLen = this.length;
	        var iArgLen = arguments.length;
	        for(var i = 0; i < iArgLen; i++)
	        {
	            this[this.length] = arguments[i];
	        }
	        return this.length;
	    };
	}
	if(typeof(Array.prototype.shift) === "undefined")
	{
	    Array.prototype.shift = function()
	    {
	        this.reverse();
	        var oObject = this.pop();
	        this.reverse();
	        return oObject;
	    };
	}
	if(typeof(Array.prototype.slice) === "undefined")
	{
	    Array.prototype.slice = function(iIndex, iHowMany)
	    {
	        var iEnd = (iEnd === null || iEnd === '')? this.length: iEnd;
	        if(iEnd < 0)
	        {
	            iEnd = this.length + iEnd;
	        }
	        var iBegin = (iBegin < 0)? this.length + iBegin: iBegin;
	        if(iEnd < iBegin)
	        {
	            var iTemp = iEnd;
	            iEnd = iBegin;
	            iBegin = iTemp;
	            iTemp = null;            
	        }
	        var aArray = new Array();
	        var iLen = iEnd - iBegin;
	        for(var i = 0; i < iLen; i++)
	        {
	            aArray[i] = this[iBegin + 1];
	        }
	        return aArray;
	    };
	}
	if(typeof(Array.prototype.splice) === "undefined")
	{
	    Array.prototype.splice = function(iBegin, iCount)
	    {
	        var iCount = (iCount === null || iCount === '')? this.length - iBegin: iCount;
	        var aArray = this.copy();
	        var iLen = iBegin + arguments.length - 2;
	        for(var i = iBegin; i < iLen; i++)
	        {
	            this[i] = arguments[i - iBegin + 2];
	        }
	        
	        var iNewLen = this.length - iCount + arguments.length - 2;
	        for(var i = iLen; i < iNewLen; i++)
	        {
	            this[i] = aArray[i + iCount - arguments.length + 2];
	        }
	        this.length = this.length - iCount + (arguments.length - 2);
	        return aArray.slice(iBegin, iBegin + iCount);
	    };
	}
	if(typeof(Array.prototype.unshift) === "undefined")
	{
	    Array.prototype.unshift = function(oItem)
	    {
	        var aArray = [0,0];
	        var iLen = arguments.length;
	        
	        for(var i = 0; i < iLen; i++)
	        {
	            aArray.push(arguments[i]);
	        }
	        var aRet = this.splice.apply(aArray);
	        return this.length;
	    };
	}
	
	if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement)
	{
		HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode)
		{
			switch (where){
			case 'beforeBegin':
				this.parentNode.insertBefore(parsedNode,this);
				break;
			case 'afterBegin':
				this.insertBefore(parsedNode,this.firstChild);
				break;
			case 'beforeEnd':
				this.appendChild(parsedNode);
				break;
			case 'afterEnd':
				if (this.nextSibling)
				{ 
					this.parentNode.insertBefore(parsedNode,this.nextSibling);
				}
				else
				{
					this.parentNode.appendChild(parsedNode);
				}
				break;
			}
		};
		HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
		{
			var r = this.ownerDocument.createRange();
			r.setStartBefore(this);
			var parsedHTML = r.createContextualFragment(htmlStr);
			this.insertAdjacentElement(where,parsedHTML);
		};
		HTMLElement.prototype.insertAdjacentText = function(where,txtStr)
		{
			var parsedText = document.createTextNode(txtStr);
			this.insertAdjacentElement(where,parsedText);
		};
	}
