﻿//---------------------------------------------------------------------------------------------------------------------
// Copyright 2007 WonderHowTo, Inc.
// 
// Origional Author:    Bryan Crow
// Last Modified By:    Marat Khoudabakhshiev
// Last Modified:       04/13/2010
//---------------------------------------------------------------------------------------------------------------------

//*********************************************************************************************************************
// Start Base JavaScript Object Prototype Extensions
//*********************************************************************************************************************

// String extension to make Replace() function like it's c# counterpart:
String.prototype.Replace = function($sFrom, $sTo) {
    return this.split($sFrom).join($sTo);
};


// String extension to allow quick replacements with ordered delimitors ("{0}, {1}, {2}, ..."), or if an object is
// passed in, named delimiters ({Name1:"value1", Name2:"value2"} :> "{Name1}, {Name2}, ..."):
String.prototype.format = function() {
    var s = this;
    if (arguments.length == 1 && typeof arguments[0] == 'object') {
        var oHash = arguments[0];
        for (var sKey in oHash) {
            s = s.Replace('{' + sKey + '}', String(oHash[sKey]));
        }
    } else {
        for (var i = 0; i < arguments.length; i++) { 
            s = s.Replace('{' + i + '}', String(arguments[i]));
        }
    }
    return s;
};


// String extension adding a c#-like trim() method:
String.prototype.trim = function($cTrim) {
    var x = 0, y = this.length, z = ($cTrim == null || $cTrim == '') ? ' \t\r\n' : $cTrim;
    while ((x < y) && (z.indexOf(this.charAt(x)) > -1)) x++;
    while ((y > x) && (z.indexOf(this.charAt(y - 1)) > -1)) y--;
    return this.substring(x, y);
};


// String extension to escape special characters so the string will render as text when embedded as html:
String.prototype.htmlEscape = function() {
    var sEscaped = this.Replace('&', '&amp;');
    sEscaped = sEscaped.Replace('<', '&lt;');
    sEscaped = sEscaped.Replace('>', '&gt;');
    return sEscaped.Replace('"', '&quot;');
};


// String extension to escape special characters so the string will transfer properly to javascript:
String.prototype.jsEscape = function() {
    var sEscaped = this.Replace('\\', '\\\\');
    sEscaped = sEscaped.Replace('\'', '\\\'');
    sEscaped = sEscaped.Replace('"', '\\"');
    sEscaped = sEscaped.Replace('\n', '\\n');
    return sEscaped.Replace('\t', '\\t');
};


// NOTE: UNTESTED CODE!!! USE AT OWN RISK!!!
String.prototype.fullHtmlEscape = function() {
	var oRegEx = /&amp;(euro|quot|amp|lt|gt|nbsp|iexcl|cent|pound|curren|yen|brvbar|sect|uml|copy|ordf|not|shy|reg|macr|deg|plusmn|sup2|sup3|acute|micro|para|middot|cedil|sup1|ordm|raquo|frac14|frac12|frac34|iquest|Agrave|Aacute|Acirc|Atilde|Auml|Aring|AElig|Ccedil|Egrave|Eacute|Ecirc|Euml|Igrave|Iacute|Icirc|Iuml|ETH|Ntilde|Ograve|Oacute|Ocirc|Otilde|Ouml|times|Oslash|Ugrave|Uacute|Ucirc|Uuml|Yacute|THORN|szlig|agrave|aacute|acirc|atilde|auml|aring|aelig|ccedil|egrave|eacute|ecirc|euml|igrave|iacute|icirc|iuml|eth|ntilde|ograve|oacute|ocirc|otilde|ouml|divide|oslash|ugrave|uacute|ucirc|uuml|yacute|thorn|#\d{2,3});/gi;
	var sEscaped = this.Replace('&', '&amp;');
	return sEscaped.replace(oRegEx, '&$1;');
};


// String extension to escape quotations as needed when written as html node-attribute values:
String.prototype.htmlArgEscape = function() {
    return this.Replace('"', '&quot;');
};


// String extension to perform both jsEscape() & htmlArgEscape at once:
String.prototype.jhaEscape = function() {
    return this.jsEscape().htmlArgEscape();
};


String.prototype.regexEscape = function() {
    var oSpRE = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
    return this.replace(oSpRE, "\\$&");
};


// Date extension to return a clean hh:mm:ss pm format:
Date.prototype.to12HourTime = function() {
    var h=this.getHours(),m=this.getMinutes(),s=this.getSeconds(),a;
    if (m < 10){m='0'+m;}
    if (s < 10){s='0'+s;}
    if (h > 12){h-=12;a=' pm';}else{a=' am';}
    return h+':'+m+':'+s+a;
};


// Date extensions to return a new Date() with the specified number of seconds/minutes/hours/days added to it:
Date.prototype.addSeconds = function($iSeconds){return new Date(this.getTime()+($iSeconds*1000));};
Date.prototype.addMinutes = function($iMinutes){return this.addSeconds($iMinutes*60);};
Date.prototype.addHours = function($iHours){return this.addMinutes($iHours*60);};
Date.prototype.addDays = function($iDays){return this.addHours($iDays*24);};


// Add indexOf support to IE arrays
Array.prototype.indexOf = function($val, $iFrom) {
    $iFrom = ($iFrom) ? $iFrom : 0;
    
    if ($iFrom < this.length) {
        for (var i = $iFrom; i < this.length; i++) {
            if (this[i] === $val) return i;
        }
    }
    
    return -1;
};
//*********************************************************************************************************************
// End Base JavaScript Object Prototype Extensions
//*********************************************************************************************************************





//*********************************************************************************************************************
// Start usefull common method declarations:
//*********************************************************************************************************************

// Adds 'px' to the end of a number, or strips the 'px' from the end of a string:
function px(n) {
    if (String(n).indexOf('px') > -1) {
        return Number(n.substring(0,n.length-2));
    }
    return String(n) + 'px';
};


// Returns a child node by name from an XML document, or null if the node doesn't exist.
// The third & fourth optional parameters will only return the node if the named attribute / value
// combo are also found in the node. If specified, the third parameter requires the node to be visible.
function getChildNode($oElement, $sElementName, $sAttributeName, $sAttributeValue, $bVisible, $bStartsWith) {
    if (($bVisible && $oElement.className.indexOf('hide') == -1 && $oElement.style.display != 'none' && $oElement.style.visibility != 'hidden') || ($bVisible == null || $bVisible == false)) {
        for(var i = 0; i < $oElement.childNodes.length; i++){
		    if ($oElement.childNodes[i].nodeName != null && $oElement.childNodes[i].nodeName.toLowerCase() == $sElementName.toLowerCase()){
			    if ($sAttributeName != null && $sAttributeValue != null){
			        var sAttributeValue = $oElement.childNodes[i].getAttribute($sAttributeName);
			        if (($bStartsWith && sAttributeValue.indexOf($sAttributeValue) == 0) || sAttributeValue == $sAttributeValue) {
					    return $oElement.childNodes[i];
			        }
			    } else {
				    return $oElement.childNodes[i];
			    }
		    }
		    if ($oElement.childNodes[i].nodeType == 1) {
		        var oChildNode = getChildNode($oElement.childNodes[i], $sElementName, $sAttributeName, $sAttributeValue, $bVisible);
		        if (oChildNode != null) return oChildNode;
		    }
	    }
	}
	
	// The requested node was not found. Return null:
	return null;
};


// Gets a value from the class attribute of an element based on the starting characters of the class:
function getPrefixedClassValue($oElement, $sClassPrefix) {
    var sValue = null;
    if ($oElement == null || $sClassPrefix == null || $sClassPrefix == '') return sValue;
    if ($oElement.className == null) return sValue;
    if ($oElement.className.indexOf($sClassPrefix) == 0) {
        sValue = $oElement.className.substring($sClassPrefix.length);
    } else if ($oElement.className.indexOf(' ' + $sClassPrefix) > -1) {
        sValue = $oElement.className.substring($oElement.className.indexOf(' ' + $sClassPrefix) + $sClassPrefix.length + 1);
    }
    if (sValue == null) return sValue;
    if (sValue.indexOf(' ') > -1) sValue = sValue.substring(0, sValue.indexOf(' '));
    return sValue;
};


// Converts seconds to appropriate format and returns it as a string:
function secondsToTime($iSeconds) {
    var oD = new Date(0,0,0,0,0,$iSeconds,0);
    var h=oD.getHours(),m=oD.getMinutes(),s=oD.getSeconds();
    h=(h > 0)?''+h+':':'';
    m=(h != '' && m < 10)?'0'+m+':':''+m+':';
    s=(s < 10)?'0'+s:s.toString();
    return h+m+s;
};


// Reload home page after 90 min:
var ____iIdleTO = setTimeout(function(){navigateTo('/');},5400000);

// Navigates to a given URL:
function navigateTo($sPath) {
    clearTimeout(____iIdleTO);
    if (self.location.href) {
        self.location.href = $sPath;
    } else {
        self.location = $sPath;
    }
};


// Does a poor-man's reload of the currently active page:
function refresh() {
    if (oPage) { oPage._noKeepAlive = true; setTimeout(function(){oPage._noKeepAlive = false;},100); }
    navigateTo(($_activeURL) ? $_activeURL : (self.location.href) ? self.location.href : self.location);
    try{document.body.style.cursor = 'progress';}catch(e){}
};


// Returns the text of the selected option:
function getSelectedText($oSelect) {
    for (var x = 0; x < $oSelect.options.length; x++) {
        if ($oSelect.options[x].selected) {
            return $oSelect.options[x].text;
        }
    }
    return null;
};


// Returns the value of the selected option from a <select/> list.
function getSelectedValue($oSelect) {
    for (var x = 0; x < $oSelect.options.length; x++) {
        if ($oSelect.options[x].selected) {
            return $oSelect.options[x].value;
        }
    }
    return null;
};


// Sets the value of the selected option in a <select/> list to the passed-in value (if available).
function setSelectedValue($oSelect, $sValue) {
    for (var x = 0; x < $oSelect.options.length; x++) {
        if (String($oSelect.options[x].value) == String($sValue)) {
            $oSelect.options[x].selected = true;
            break;
        }
    }
};


// Performs a series of document.writes to write out an object/embed tag.
function writeObject($sObject) {
    var aObjectParts = $sObject.split('>');
    for (var x = 0; x < aObjectParts.length; x++) {
        if (aObjectParts[x].length > 0) document.write(aObjectParts[x] + '>');
    }
};


// Sets a cookie for a specified number of days:
function setCookie($sName,$sValue,$iDays) {
    var sExpires = '';
	if ($iDays) {
		var oDate = new Date();
		oDate.setTime(oDate.getTime() + ($iDays * 86400000));
		sExpires = '; expires=' + oDate.toGMTString();
	}
	var iDotIndex = String(window.location).indexOf('.');
	var sDomain = (iDotIndex > 0) ? String(window.location).substring(String(window.location).indexOf('.')) : 'localhost/';
	var iSlashIndex = sDomain.indexOf('/');
	document.cookie = $sName + '=' + $sValue + sExpires + '; path=/;' + String((arguments.length < 4) ? ' domain=' + sDomain.substring(0,iSlashIndex) : '');
};


// Returns the value of a stored cookie:
function getCookie($sName) {
    $sName = $sName + "=";
	var aCookies = document.cookie.split(';');
	for(var i = 0; i < aCookies.length; i++) {
		var sValue = aCookies[i].trim();
		if (sValue.indexOf($sName) == 0) return sValue.substring($sName.length, sValue.length);
	}
	return null;
};


// Deletes a cookie:
function deleteCookie($sName) {
    setCookie($sName, '', -365, false);
    setCookie($sName, '', -365);
};


// Converts the first letter to lowercase
function firstToLower($sString) {
    if ($sString.length == 0) return $sString;
    if ($sString.length == 1) return $sString.toLowerCase();
    
    var sNewString = $sString[0].toLowerCase() + $sString.substring(1);
    
    return sNewString;
};


// Prints content of $sMessage in Firebug console
function printDebug($sMessage) {
    try {
        console.log($sMessage);
    } catch (err) { }
};


// Converts string to HTML object
function stringToDomObject($sHtmlString, $oDoc) {
    $oDoc = ($oDoc) ? $oDoc : document;
    
	var oTempDiv = $oDoc.createElement('div');
	oTempDiv.innerHTML = $sHtmlString;
	
	var oDomObject = oTempDiv.firstChild;
	oTempDiv.removeChild(oDomObject);
	
	return oDomObject;
};

// Sets focus & blur events on an input or textarea to show a default string when it contains no value. To change an existing default
// value (for when re-using input elements), just call this method again.
function setFieldDefaultValue($oEl, $sVal, $sColorDef, $sColorFoc) {
    if ($oEl._sDefaultValue == null) {
        $oEl._sDefaultValue = '';
        $oEl._sColorDef = $sColorDef;
        $oEl._sColorFoc = $sColorFoc;
        if ($oEl.onfocus != null) $oEl.___onfocus = $oEl.onfocus;
        if ($oEl.onblur != null) $oEl.___onblur = $oEl.onblur;
        $oEl.onfocus = function() {
            if (this._sColorFoc != null) { this.style.color = this._sColorFoc; }
            if (this.value.trim().toLowerCase() == this._sDefaultValue.toLowerCase()) { this.value = ''; }
            if (this.___onfocus != null) {try{this.___onfocus.apply(this, arguments);}catch(e){}}
        };
        $oEl.onblur = function() {
            if (this.value.trim().toLowerCase() == this._sDefaultValue.toLowerCase() || this.value.trim() == '') { this.value = this._sDefaultValue; if (this._sColorDef != null) { this.style.color = this._sColorDef; } }
            if (this.___onfocus != null) {try{this.___onfocus.apply(this, arguments);}catch(e){}}
        };
        $oEl.getValue = function() { return (this.value.trim().toLowerCase() == this._sDefaultValue.toLowerCase()) ? '' : this.value; };
        $oEl.resetValue = function() { if (this.getValue() == '') this.value = this._sDefaultValue; if (this._sColorDef != null) { this.style.color = this._sColorDef; } }
    }
    if ($oEl.getValue() == '') { $oEl.value = $sVal; if (this._sColorDef != null) { this.style.color = this._sColorDef; } }
    $oEl._sDefaultValue = $sVal;setTimeout(function(){$oEl.onblur.apply($oEl);},1);
};


// Returns all text nodes from the root. If root is not specified, uses body of the document as root.
// Uses recursion to inspect children of child nodes.
function getTextElements($oRoot, $iUpTo) {
    var oRoot = ($oRoot) ? $oRoot : this._oBody;
	var aTxts = [];
	var iUpTo = ($iUpTo) ? $iUpTo : (oRoot.childNodes) ? oRoot.childNodes.length : 0;
	
	if (oRoot && oRoot.childNodes) {
		for (var i = 0; i < iUpTo; i++) {
			if (oRoot.childNodes[i].nodeName.toLowerCase() == '#text') {
				aTxts.push(oRoot.childNodes[i]);
			} else {
				aTxts = aTxts.concat(getTextElements(oRoot.childNodes[i]));
			}
		}
	}
	
	return aTxts;
};


// Checks whether the supplied node is the ancestor of the child node or it is itself
function isAncestorOrSelf($oNode, $oChild) {
    if ($oNode == $oChild) return true;
    
    // Go up the DOM tree and see of it's the ancestor
    while ($oChild.parentNode != null) {
        if ($oNode == $oChild.parentNode) return true;
        
        $oChild = $oChild.parentNode;
    }
    
    return false;
};


// Returns text content of the node
function getNodeText($oNode) {
    if ($oNode) {
        if ($oNode.nodeValue || $oNode.nodeValue === '') return $oNode.nodeValue;
        if ($oNode.textContent || $oNode.textContent === '') return $oNode.textContent;
	    if ($oNode.innerText || $oNode.innerText === '') return $oNode.innerText;
    	
	    return $oNode.toString();
	}
	
	return '';
};


// Scrolls to the element. Possible to pass in element's ID
/*
function scrollToElement($oScrollTo) {
    if (typeof($oScrollTo) == 'string') {
        $oScrollTo = document.getElementById($oScrollTo);
    }
    
    if (!$oScrollTo) return;
    
    var iSelectedPosX = 0;
    var iSelectedPosY = 0;
    
    while($oScrollTo != null) {
        iSelectedPosX += $oScrollTo.offsetLeft;
        iSelectedPosY += $oScrollTo.offsetTop;
        $oScrollTo = $oScrollTo.offsetParent;
    }
    
    window.scrollTo(iSelectedPosX, iSelectedPosY);
};
*/


// Enable outerHTML for all browsers
if (document.__defineGetter__ && !HTMLElement.outerHTML) {
    HTMLElement.prototype.__defineGetter__("outerHTML", function() {
        var emptyTags = {
		   "img":   true,
		   "br":    true,
		   "input": true,
		   "meta":  true,
		   "link":  true,
		   "param": true,
		   "hr":    true
		};

		var attrs = this.attributes,
		tagName = this.tagName.toLowerCase(),
		str = "<" + tagName;
		for (var a = 0; a < attrs.length; a++)
		  str += " " + attrs[a].name + "=\"" + attrs[a].value + "\"";

		if (emptyTags[tagName])
		  return str + "/>";

		return str + ">" + this.innerHTML + "</" + tagName + ">";
    });
}
//*********************************************************************************************************************
// End usefull common method declarations
//*********************************************************************************************************************





//*********************************************************************************************************************
// Start httpGet Method/Object Definition
//*********************************************************************************************************************



//=============================================================================================
// httpGet base method declaration:
//=============================================================================================
// Used to easily perform in-line synchronous or asynchronous http requests:
function httpGet($oURI, $oArgs, $fOnLoad, $bSynch) {
    var bAsync = ($bSynch) ? false : true;
    var oReturn, xmlHttp = httpGet.getNewXMLHttpRequest();
    if (xmlHttp) {
        var bSynchReadyStateHandled = false;
        var fReadyStateChange = function() {
            try {
                if (xmlHttp) {
                    if (xmlHttp.readyState == 4) {
                        var iStatus;
                        try { if (xmlHttp.status != undefined && xmlHttp.status != 0) {iStatus = xmlHttp.status;} else {iStatus = 13030;} } catch(err) {iStatus = 13030;}
                        if (xmlHttp.responseText) {
                            oReturn = $fOnLoad(httpGet.fromJSON(xmlHttp.responseText), $oArgs);
                        } else if (iStatus == 13030) {
                            oReturn = null;
                        } else {
                            oReturn = $fOnLoad(httpGet.fromJSON(), $oArgs);
                        }
                        // Flag the event as completed:
                        bSynchReadyStateHandled = true;
                        
                        // Remove the circular reference & release the memory used by the XMLHttpRequest object:
                        delete xmlHttp['onreadystatechange'];
                        xmlHttp = null;
                        delete xmlHttp;
                        if (window['CollectGarbage']) { CollectGarbage(); }
                    }
                }
            } catch(err) {
                oReturn = $fOnLoad({errorNumber:500.1, errorText:'Sorry, we had some trouble talking to the server. Unexpected AJAX Exception.', value:null}, $oArgs);
                bSynchReadyStateHandled = true;
                
                // Remove the circular reference & release the memory used by the XMLHttpRequest object:
                delete xmlHttp['onreadystatechange'];
                xmlHttp = null;
                delete xmlHttp;
                if (window['CollectGarbage']) { CollectGarbage(); }
            }
        };
        
        if (typeof $oURI == 'string') {
            xmlHttp.open("GET", $oURI, bAsync);
            xmlHttp.onreadystatechange = fReadyStateChange;
            xmlHttp.setRequestHeader('If-Modified-Since', 'Wed, 8 Aug 2007 00:00:00 GMT');
            xmlHttp.send(null);
        } else {
            xmlHttp.open("POST", $oURI.uri, bAsync);
            xmlHttp.setRequestHeader($oURI.xrl, $oURI.prn);
            xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            xmlHttp.setRequestHeader('If-Modified-Since', 'Wed, 8 Aug 2007 00:00:00 GMT');
            if (String(navigator.userAgent).indexOf('AppleWebKit') == -1) {
                xmlHttp.setRequestHeader("Content-Length", $oURI.args.length);
                xmlHttp.setRequestHeader("Connection", "Close");
            }
            xmlHttp.onreadystatechange = fReadyStateChange;
            xmlHttp.send($oURI.args);
        }
        
        // Some browsers don't fire the onreadystatechange event handler for synchronous calls.
        // Manually fire it here if this was a synchronous call & the event wasn't fired:
        if (!bAsync && !bSynchReadyStateHandled) {
            fReadyStateChange.call();
        } else if (bAsync) {
            oReturn = xmlHttp;
        }
    } else {
        var fNoXHR = function(){oReturn = $fOnLoad(httpGet.fromJSON('{errorNumber:13, errorText:"Sorry, we ' +
        'cannot continue in the browser you\'re using. Please use a modern browser such as Firefox, Safari,' +
        ' Opera, or Internet Explorer. If you are using a modern browser, check to verify that your securit' +
        'y settings aren\'t set too high.", value:null}'), $oArgs);};if(bAsync){setTimeout(function(){fNoXHR()
        ;},0);}else{fNoXHR();}
    }
    return oReturn;
};


// Loads a javascript file via async or blocking call & evals it:
httpGet.loadScript = function($sScriptName, $bSynch) {
    var bAsync = ($bSynch) ? false : true;
    var oReturn = false, xmlHttp = httpGet.getNewXMLHttpRequest();
    if (xmlHttp) {
        var bSynchReadyStateHandled = false;
        var fReadyStateChange = function() {
            try {
                if (xmlHttp) {
                    if (xmlHttp.readyState == 4) {
                        if (xmlHttp.responseText) {
                            try {
                                eval(xmlHttp.responseText);
                                oReturn = true;
                            } catch (evalErr){ oReturn = false; window.status = 'Error Executing Dynamic Script: ' + $sScriptName + ': ' + String((evalErr.message) ? evalErr.message : evalErr.toString()) }
                        }
                        // Flag the event as completed:
                        bSynchReadyStateHandled = true;
                        
                        // Remove the circular reference & release the memory used by the XMLHttpRequest object:
                        delete xmlHttp['onreadystatechange'];
                        xmlHttp = null;
                        delete xmlHttp;
                        if (window['CollectGarbage']) { CollectGarbage(); }
                    }
                }
            } catch(err) {
                // Remove the circular reference & release the memory used by the XMLHttpRequest object:
                delete xmlHttp['onreadystatechange'];
                xmlHttp = null;
                delete xmlHttp;
                if (window['CollectGarbage']) { CollectGarbage(); }
            }
        };
        
        var sVersion = (window.JSVersion) ? window.JSVersion : (new Date()).getTime();
        var sFullPath = '/js/' + $sScriptName + '.js?v=' + sVersion;
        xmlHttp.open("GET", sFullPath, bAsync);
        xmlHttp.onreadystatechange = fReadyStateChange;
        xmlHttp.setRequestHeader('If-Modified-Since', 'Wed, 8 Aug 2007 00:00:00 GMT');
        xmlHttp.send(null);
        
        // Some browsers don't fire the onreadystatechange event handler for synchronous calls.
        // Manually fire it here if this was a synchronous call & the event wasn't fired:
        if (!bAsync && !bSynchReadyStateHandled) {
            fReadyStateChange.call();
        } else if (bAsync) {
            oReturn = xmlHttp;
        }
    }
    return oReturn;
};


// Loads a string from a file via blocking call:
httpGet.loadString = function($sSrc) {
    var sReturn = '', xmlHttp = httpGet.getNewXMLHttpRequest();
    if (xmlHttp) {
        var bSynchReadyStateHandled = false;
        var fReadyStateChange = function() {
            try {
                if (xmlHttp) {
                    if (xmlHttp.readyState == 4) {
                        if (xmlHttp.responseText) {
                            try {
                                sReturn = String(xmlHttp.responseText);
                            } catch (evalErr){ sReturn = ''; window.status = 'Error Loading String From ' + $sSrc + ': ' + String((evalErr.message) ? evalErr.message : evalErr.toString()) }
                        }
                        // Flag the event as completed:
                        bSynchReadyStateHandled = true;
                        
                        // Remove the circular reference & release the memory used by the XMLHttpRequest object:
                        delete xmlHttp['onreadystatechange'];
                        xmlHttp = null;
                        delete xmlHttp;
                        if (window['CollectGarbage']) { CollectGarbage(); }
                    }
                }
            } catch(err) {
                // Remove the circular reference & release the memory used by the XMLHttpRequest object:
                delete xmlHttp['onreadystatechange'];
                xmlHttp = null;
                delete xmlHttp;
                if (window['CollectGarbage']) { CollectGarbage(); }
            }
        };
        
        // Add versioning
        var sVersion = (window.JSVersion) ? window.JSVersion : (new Date()).getTime();
        $sSrc += '?v=' + sVersion;
        xmlHttp.open("GET", $sSrc, false);
        xmlHttp.onreadystatechange = fReadyStateChange;
        xmlHttp.setRequestHeader('If-Modified-Since', 'Wed, 8 Aug 2007 00:00:00 GMT');
        xmlHttp.send(null);
        
        // Some browsers don't fire the onreadystatechange event handler for synchronous calls.
        // Manually fire it here if the event wasn't fired:
        if (!bSynchReadyStateHandled) {
            fReadyStateChange.call();
        }
    }
    return sReturn;
};


// Returns an appropriate XMLHttpRequest object based on the browser's capabilities:
httpGet.getNewXMLHttpRequest = function() {
    var xmlHttp = false;
    try {
        if (window.ActiveXObject) {
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (err) {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
        } else if (window.XMLHttpRequest) {
            xmlHttp = new XMLHttpRequest();
            if (xmlHttp.overrideMimeType) { xmlHttp.overrideMimeType('text/html'); }
        }
    } catch(ex) {}
    return xmlHttp;
};


// Used to build the URI for an http GET ajax request:
httpGet.buildURI = function($sPage) {
    var sURI = String(($sPage.toLowerCase().indexOf('http') == 0) ? $sPage : '/ajax/' + $sPage) + '.aspx?rt=json&rn=' + String((new Date()).valueOf()) + String(Math.random() * 1000);
    for (var x = 1; x < arguments.length; x+=2) {
        sURI += '&' + arguments[x] + '=' + encodeURIComponent(arguments[x+1]);
    }
    return sURI;
};


// Used to build the URI for a validated http POST ajax request (deliberately cryptic):
httpGet.buildPostURI = function($sPage) {
    var sURI= httpGet.buildURI($sPage);var aRNS=sURI.substring(
    sURI.lastIndexOf('=')+1).split('.'),iAL;var iPRN=Math.ceil(
    Math.random() * 1000), sT='t',sTs='',iRO,iRL=9;var iRNO=iRO
    =Math.floor(Math.random()*iRL)+2,sE='e', sU='_', sM='-';var
    sArgs='rk='+String((Number(aRNS[0])%Number(aRNS[1]))+iPRN);
    while(--iRNO>0)sTs+='%'+String(3729+203-3932)+iRL;for(var i
    =1; i < arguments.length;i+= 2)sArgs+='&'+arguments[i]+'='+
    encodeURIComponent(arguments[i+1]);sArgs=sU+'='+sTs+'&'+sArgs
    ;iAL=sArgs.length; return {uri:sURI,xrl:['x'.toUpperCase(),
    'r'.toUpperCase()+ sE+'qu'+sE+'s'+ sT,'l'.toUpperCase()+sE+
    'ng'+sT+'h'].join(sM),args:sArgs,prn:String(iPRN-iRO+iAL)};
};


// Parses a JSON response to return it's represented object:
httpGet.fromJSON = function($sResult) {
    var bErrorParsingResult = false;
    if ($sResult != null) {
        try {
            eval('var oHttpGetResultValue=' + $sResult + ';');
            return oHttpGetResultValue;
        } catch(e) { bErrorParsingResult = true; }
    }
    if (console) { if (console.log) console.log($sResult); }
    return {errorNumber:500, errorText:'Sorry, we had some trouble talking to the server.' + String((bErrorParsingResult) ? ' The response was unexpected.' : ' Please try again.'), value:null};
};


// Function to be called if the asynchronous call wishes to do nothing when the request is complete.
httpGet.doNothing = function(){};

//*********************************************************************************************************************
// End httpGet Method/Object Object Definition
//*********************************************************************************************************************


//*********************************************************************************************************************
// Start WHTAdManager Method/Object Definition
//*********************************************************************************************************************
window.WHTAdManager = function() {
    this._aSlots = [];
    this._oLastSlot = {'300x250':'','728x90':'','160x600':'','150x150':''};
    this._oLastPhr = {};
    this._oAds = {};
    this._oPhs = {};
    this.bBaseWritten = false;
    this.sGAMBase = new String();
    
    this.Reposition = function() {
        for (var x = 0; x < this._aSlots.length; x++) {
            this.repositionSlot(this._aSlots[x]);
        }
    };
    
    this.writeBase = function() {
        if (this.bBaseWritten) return;
        this.bBaseWritten = true;
        var sBase = String(this.sGAMBase).Replace('{BREAKER}','');
        var aBases = sBase.split('</scr'+'ipt>');
        for (var x = 0; x < aBases.length - 1; x++) {
            document.write(aBases[x] + '</scr'+'ipt>\n');
        }
    };
    
    this.writeSlot = function($sSlot,$sPreFill) {
        this._aSlots.push($sSlot);
        this._oLastSlot[($sSlot.indexOf('300x250') > -1) ? '300x250' : ($sSlot.indexOf('728x90') > -1) ? '728x90' : ($sSlot.indexOf('160x600') > -1) ? '160x600' : '150x150'] = ($sPreFill == null) ? '' : $sSlot;
        if ($sPreFill == null) {
            this.writeBase();
            document.write(String('<sc{BREAKER}ript type=\"text/javasc{BREAKER}ript\">\n' + 'GA_googleFillSlot("'+$sSlot+'");' + '\n</sc{BREAKER}ript>').Replace('{BREAKER}',''));
        } else {
            document.write(String($sPreFill).Replace('{BREAKER}',''));
        }
        setTimeout('window.oWHTAdManager.repositionSlot.apply(window.oWHTAdManager,["'+$sSlot+'"]);',10);
    };
    
    this.backFill = function($sSize) {
        var sBackfill = this._oLastSlot[$sSize];
        if (sBackfill == null || sBackfill == '') {
            switch($sSize) {
                case '300x250':
                    this._oLastSlot[$sSize] = sBackfill = 'gno_overflow_ros_300x250';
                    break;
                case '728x90':
                    this._oLastSlot[$sSize] = sBackfill = 'gno_overflow_ros_728x90';
                    break;
                case '160x600':
                    this._oLastSlot[$sSize] = sBackfill = 'gno_overflow_ros_160x600';
                    break;
                case '150x150':
                default:
                    return;
            }
        } else if (sBackfill.indexOf('gno_overflow') == 0) {
            switch($sSize) {
                case '300x250':
                    this._oLastSlot[$sSize] = sBackfill = 'lvl3_remnant_300x250';
                    break;
                case '728x90':
                    this._oLastSlot[$sSize] = sBackfill = 'lvl3_remnant_728x90';
                    break;
                case '160x600':
                    this._oLastSlot[$sSize] = sBackfill = 'lvl3_remnant_160x600';
                    break;
                case '150x150':
                default:
                    return;
            }
        } else if (sBackfill.indexOf('lvl3_remnant') == 0) {
            sBackfill = '';
        } else {
            this._oLastSlot[$sSize] = '';
        }
        if (sBackfill != null && sBackfill != '') {
            this.writeBase();
            document.write(String('<sc{BREAKER}ript type=\"text/javasc{BREAKER}ript\">\n' + 'GA_googleFillSlot("'+sBackfill+'");' + '\n</sc{BREAKER}ript>').Replace('{BREAKER}',''));
        } else {
            // No backfill available.
        }
    };
    
    this.repositionSlot = function($sSlot) {
        var oAd = this._oAds[$sSlot] || document.getElementById('rad_' + $sSlot);
        var oPh = this._oPhs[$sSlot] || document.getElementById('aph_' + $sSlot);
        var oPhr = YAHOO.util.Dom.getRegion(oPh);
        
        if (this._oLastPhr[$sSlot] == null) {
            oAd.style.position = 'absolute';
            if ($sSlot.indexOf('top_728x90') > -1) {
                oAd.style.zIndex = 11;
            }
            oAd.style.display = 'block';
            this._oAds[$sSlot] = oAd;
            this._oPhs[$sSlot] = oPh;
        } else if (oPhr.top == this._oLastPhr[$sSlot].top && oPhr.left == this._oLastPhr[$sSlot].left) {
            return;
        }
        
        var iYOffset = (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8) ? -2 : 0;
        var iXOffset = (YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 8) ? -2 : 0;
        
        oAd.style.top = String(iYOffset + oPhr.top + oPh.style.paddingTop)+'px';
        oAd.style.left = String(iXOffset + oPhr.left)+'px';
        this._oLastPhr[$sSlot] = oPhr;
    };
    
    this.OkThatsEnoughAds = function() {
        this.Reposition();
        YAHOO.util.Event.addListener(window, 'resize', this.Reposition, this, true);
        setTimeout('window.oWHTAdManager.Reposition.apply(window.oWHTAdManager,[]);',1000);
    };
};
window.oWHTAdManager = new window.WHTAdManager();
//*********************************************************************************************************************
// End WHTAdManager Method/Object Definition
//*********************************************************************************************************************