/**
 * Core TWP JavaScript Famework
 * @version 1.0
 * @author Jesse Foltz
 * @author David Johnson
 * @author Chris Kankel
 * @author Steven King
 * @author Larry Landerson
 * @author Chad Shryock
 * @author Lee Trout
 */
var TWP = window.TWP || {}

var TWP_tmp = {

    version : '1.0.0',
    debug : false,


    // A registry of objects in the framework
    registry : [],

    /**
     *
     * Creates a new namespace.
     * @param ns (String) A fully qualified namespace (parent ns must be included)
     * @return Object A new namespaces object
     */
    namespace : function(ns){

        // This function should accept multiple ns arguments

        if(!ns || !ns.length){
            return null;
        }

        var twp_2 = ns.split(".");
        var twp_3 = TWP;

        for(var i=(twp_2[0]=="TWP")?1:0;i<twp_2.length;++i){
            twp_3[twp_2[i]] = twp_3[twp_2[i]] || {};
            twp_3 = twp_3[twp_2[i]];
        }

        return twp_3;

    },

    /**
     * Creates a new object
     * @param parent (Object) The parent the newly returned object inherits from
     * @return Object A new "subclass" object
     */
    createObject : function(parent){
        var F = function(){};
        F.prototype = parent || {};
        return new F();
    },

    /**
     * Creates a new object with the signature of the "parent"
     * @param parent (Object) The parent the newly returned object inherits from
     * @return Object A new "subclass" object
     */
    extend : function(o){
        var F = function(){};
        F.prototype = o || {};
        return new F();
    },

    memoize : function(){

    },

    /**
     * Registers a new object
     * @param name (String) The name of the object
     * @param objClass (Object) The object "class" to be registered
     */
    register : function(name, objClass){

        if(!this.registry[name]){
            this.registry[name] = {}
        }

        var module = this.registry[name];
        module.name = name
        module.objClass = objClass;

        TWP.log(name + " added to registry.");
    },

    /**
     * Gets a new instance of a class in the registry
     * @param name (String) The name of the object that was used to register it
     * @return Object A new instance of the requested object
     */
    get : function(name) {
        var temp = TWP.registry[name].objClass;
        if (typeof temp == 'object') {
            return temp;
        }
        return new temp();
    },

    /**
     * Looks for debug=true in the request url
     */
    requestDebug : function() {
        if (window.location.href.indexOf('debug=true') != -1) {
            this.debug = true;
        }
    },

    /**
     * Prints out a div at the bottom of the <body> with information about the registry
     */
    showInfo : function() {
        // TODO create a <div> at the bottom of the <body> printing out a table of registry information
    },

    log : function(message, exceptionObject) {
        try {
            if (this.debug) {
                if (exceptionObject) {
                    console.log(message + ' %o', exceptionObject);
                } else {
                    console.log(message);
                }
            }
        } catch (e) {
        }
    }
};
for (var key in TWP_tmp) {
    TWP[key] = TWP_tmp[key];
}
TWP_tmp = null;

// Look for debug flag
TWP.requestDebug();

// create core namespaces
TWP.namespace("Util");
TWP.namespace("Plugin");
TWP.namespace("Page");
TWP.namespace("Module");
TWP.namespace("Events");

(function(){

    TWP.Util.Cookie = function(){

        return {

            // Gets the cookie for the domain
            get : function(){
                return document.cookie;
            },

            /// <summary>Gets the value of the a cookie by name</summary>
            /// <param name="name" type="string">The name of the cookie</param>
            /// <returns>The name's value</returns>
            read : function(name){

                if(!name){
                    return null;
                }

                if(document.cookie.length > 0){

                    var strStart = name + "=";
                    var cookieSplit = document.cookie.split(";");

                    for(var b=0;b<cookieSplit.length;b++){

                        var c = cookieSplit[b];

                        while(c.charAt(0) == ' '){
                            c = c.substring(1, c.length);

                            if(c.indexOf(strStart) == 0){
                                return c.substring(strStart.length, c.length);
                            }
                        }

                    }
                }

                return null;
            },

            /// <summary>Sets a cookie</summary>
            /// <param name="name" type="string">The name of the cookie</param>
            /// <param name="value" type="string">The value for the cookie</param>
            /// <param name="path" type"string"></param>
            /// <param name="expires" type"object">When the cookie will expire, defaults to 30 days</param>
            /// <param name="domain" type="string"></param>
            /// <returns></returns>
            create : function(name, value, path, expires, domain){
                var cookieVal = "";

                if(!name && !expires && !value){
                    return;
                }

                if (!expires) {
                    var d = new Date();
                    d.setTime(d.getTime() + (30*24*60*60*1000));
                    expires = d;
                }

                cookieVal = name + "=" + value + "; expires=" + expires.toGMTString();

                if(path){
                    cookieVal += "; path=" + path;
                }

                if(domain){
                    cookieVal = "; domain=" + domain;
                }

                document.cookie = cookieVal;

            },

            /// <summary>Removes a cookie</summary>
            /// <param name="name">The name of the cookie to remove</param>
            /// <returns></returns>
            remove : function(name){
                this.set(name, "", -1);
            }
        }
    }();
})();

(function(){

    TWP.Util.User = function(){
        var initialized = false;
        var isAuthenticated = false;
        var userName = null;
        var userId = "";
        var userCookie = null;
        var isFacebookUser = false;
        var userType = "washington-post";
        var validCookies = ["fbuname", "wpniuser"];

        function parseCookieUserName(cookie, startStr, offset){
            var start = -1, end = -1;
            start = (cookie.indexOf(startStr) + offset);
            end = (userCookie.indexOf(";", start)) == -1 ? userCookie.length : userCookie.indexOf(";",start);

            return cookie.substring(start, end);
        }

        function setCustomCookie(){
            var upcUrl = document.location.href;

            if(upcUrl.indexOf("localhost") > -1){
                var c = TWP.Util.Cookie.get();

                if(c.indexOf("WPNIUCID") == -1){
                    var d = new Date();
                    var i = "WPNI" + d.getTime() + "." + Math.round(Math.random()*10000);
                    d.setTime(d.getTime() + 31104000000);
                    TWP.Util.Cookie.create("WPNIUCID", i, "/", d, ".washingtonpost.com");
                }
            }
        }

        return {
            // Determine whether the user has the appropriate cookie
            init : function(){

                if(initialized){
                    return;
                }

                initialized = true;

                var userCookieName = "";

                // START: TEST
                // add a cookie for testing
                //TWP.Util.Cookie.create("headzip", "20009", "/");
                // END: TEST

                for(var a=0;a<validCookies.length;a++){
                    if(document.cookie.indexOf(validCookies[a]) != -1){
                        userCookie = document.cookie;
                        userType = validCookies[a];
                        isAuthenticated = true;
                        break;
                    }
                }

                if(isAuthenticated){
                    switch(userType){
                        case 'fbuname' :
                            userCookieName = parseCookieUserName(userCookie, userType, 8);
                            break;
                        default :
                            userCookieName = parseCookieUserName(userCookie, userType, 9);
                            break;
                    }

                    userName = (userCookieName.indexOf("@") !== -1) ? userCookieName.substring(0, userCookieName.indexOf("@")) : userCookieName;
                    userId = userCookieName;
                }

                setCustomCookie();
            },

            getUserCookie : function(){
                return (userCookie.length > 0 && typeof userCookie == "string") ? userCookie : null;
            },

            getUserType : function(){
                return (userType.length > 0 && typeof userType == "string") ? userType : null;
            },

            getUserId : function(){
                return userId;
            },

            getUserName : function(){
                return (typeof userName == "string") ? userName : "";
            },

            getAuthentication : function(){
                return isAuthenticated;
            }
        }

    }();
})();
/* Utility for returning commom url attributes */
TWP.Util.Url = {

    /// <summary>Returns the paramters as an object, key=>value pairs</summary>
    /// <param name="url" type="string">The url to be parsed</param>
    /// <returns>An object</returns>
    getParameters : function(url){
        var paramList = [], params = {}, kvPairs, tmp;

        url = (url !== '' && typeof url === 'string') ? url : document.URL;

        if(url){
            if(url.indexOf("?") !== -1){
                paramList = url.split("?")[1];

                if(paramList){
                    if(paramList.indexOf("&")){
                        kvPairs = paramList.split("&");
                    } else {
                        kvPairs = [paramList];
                    }

                    for(var a=0;a<kvPairs.length;a++){
                        if(kvPairs[a].indexOf("=") !== -1){
                            tmp = kvPairs[a].split("=");
                            params[tmp[0]] = unescape(tmp[1]);
                        }
                    }
                }
            }
        }
        
        return (params) ? params : null;
    },

    getUrl : function(){
        return window.location.href || document.url;
    },

    getRootPath : function(){
        return this.getProtocol() + "//" + this.getHost() + this.getPathName();
    },

    getSubDomain : function(){

    },

    getTopLevelDomain : function(){
        return window.document.domain;
    },

    getHost : function(){
      return window.location.host;
    },

    getHostName : function(){
        return window.location.hostname;
    },

    getProtocol : function(){
        return window.location.protocol || window.document.protocol;
    },

    getPort : function(){
        return window.location.port;
    },

    getHash : function(){
        return window.location.hash;
    },

    getPathName : function(){
        return window.location.pathname;
    },

    getFileName : function(){

    },

    getFileNameExtension : function(){

    },

    isSSL : function(){
        var isSSL = false;

        if(this.getProtocol().indexOf('https://') !== -1){
            isSSL = true;
        }

        return isSSL;
    }
};

// Supports the new global masthead v3.0.0, because some pages still in quirks and CSS menus will not work in IE6+
(function(){

	TWP.Util.DropDownMenuIE = function(setup){
		var config = setup;
		var html = null;
		var ctx = null;

		if(config.target){
			ctx = config.target;
		}

        var currTarget;

		bindNav();


        function addClass(e){

            if(e.stopPropagation){
                e.stopPropagation();
            }
            e.cancelBubble = true;

            var self = currTarget =  e.srcElement;

            if(self.parentNode.className && self.parentNode.className.indexOf('selected') != -1){
                return;
            }

            var itemClass = '';

            if(self.parentNode.className){
                itemClass = self.parentNode.className;
            }

            self.parentNode.className = (itemClass != '') ? itemClass +  ' selected' :  'selected';

            currTarget.parentNode.attachEvent('onmouseleave', removeClass);
        }

        function removeClass(e){

            if(currTarget.parentNode.className != ''){
                currTarget.parentNode.className = (currTarget.parentNode.className).replace('selected', '');
            }

            currTarget.detachEvent(addClass);
        }

		function bindNav(){

            if(ctx){
                var navItems = ctx.childNodes;

                for(var i=0;i<navItems.length;i++){
                    if(navItems[i].nodeName == "LI"){
                        var item = navItems[i];
                        var itemChildNodes = item.childNodes;
                        var len = itemChildNodes.length;
                        for(var j=0;j<len;j++){
                            if(itemChildNodes[j].nodeName == "A"){
                                var anchor = itemChildNodes[j];
                                anchor.attachEvent('onmouseover', addClass);
                                break;
                            }
                        }
                    }
                }
            }
		}
	}
})();

// Wires up a form for basic behaviors and validation
(function(){

    // class
    TWP.Util.Form = function(setup){
        var self = this;
        var config = setup;
        var ctx = null;
        var inputFields = [];
        var restoreFields = [];

        if(!config){
            return;
        }

        if(config.context){
            ctx = config.context;
        }

        // find all restore fields
        var ipt = ctx.getElementsByTagName('input');

        for(var a=0;a<ipt.length;a=a+1){
            if(ipt[a].getAttribute('type') == 'text'){
                inputFields.push(ipt[a]);

                if((ipt[a].className).indexOf('restore') != -1){
                    restoreFields.push(ipt[a]);
                }
            }
        }

        for(var b=0;b<restoreFields.length;b=b+1){
            defaultTextRestore(restoreFields[b]);
        }

        function defaultTextRestore(field){
            var defaultText = field.defaultValue;

            field.onfocus = function(){
                if(this.value == defaultText){
                    this.value = '';
                }

                field.onblur = function(){

                   if(this.value != '' && this.value != defaultText){
                       return;
                   }
                   this.value = defaultText;
                }
            }
        }

        return {
            removeDefaultTextRestore : function(field){

            }
        }
    }

     // find all forms in the DOM and wire them up

     /*window.onload = function(){
         var forms = document.forms;

         for(var c=0;c<forms.length;c=c+1){
            var self = forms[c];
            var setup = {
               context : self
            }
            new TWP.Util.Form(setup);
         }
     }*/
})();

// Wires up a form for basic behaviors and validation
(function(){

    // class
    TWP.Util.Form = function(setup){
        var self = this;
        var config = setup;
        var ctx = null;
        var inputFields = [];
        var restoreFields = [];

        if(!config){
            return;
        }

        if(config.context){
            ctx = config.context;
        }

        // find all restore fields
        var ipt = ctx.getElementsByTagName('input');

        for(var a=0;a<ipt.length;a=a+1){
            if(ipt[a].getAttribute('type') == 'text'){
                inputFields.push(ipt[a]);

                if((ipt[a].className).indexOf('restore') != -1){
                    restoreFields.push(ipt[a]);
                }
            }
        }

        for(var b=0;b<restoreFields.length;b=b+1){
            defaultTextRestore(restoreFields[b]);
        }

        function defaultTextRestore(field){
            var defaultText = field.defaultValue;

            field.onfocus = function(){
                if(this.value == defaultText){
                    this.value = '';
                }

                field.onblur = function(){

                   if(this.value != '' && this.value != defaultText){
                       return;
                   }
                   this.value = defaultText;
                }
            }
        }

        return {
            removeDefaultTextRestore : function(field){

            }
        }
    }

     // find all forms in the DOM and wire them up
     // this function is commented out because of a bug that was discovered in Sept 2010   
//     window.onload = function(){
//         var forms = document.forms;

//         for(var c=0;c<forms.length;c=c+1){
//            var self = forms[c];
//            var setup = {
//               context : self
//           }
//            new TWP.Util.Form(setup);
//         }
//     } 
})();

(function(){

    TWP.Module.GlobalHeader = function(){

        var defaults = {
            showWeather : false,
            target : document.getElementById('header-v3'),
            initialized : false,
            headerType : 'default',
            mainNavRoot : document.getElementById('main-nav'),
            mainNavChildren : null,
            navNode : null,
            thisNode : null,
            nodeRoot : null,
            nodeRootChild : null,
            nodeRootChildCategory : null,
            paramList : {},
            nodeMatched : false,
            version : -1,
            browser : null,
            url : window.location.href,
            rootPath : null,
            fileName : null,
            qString : null
        };

        // Private Methods
        function getEnvInfo(){
            if (navigator.appName == 'Microsoft Internet Explorer'){
                defaults.browser = "msie";
                var ua = navigator.userAgent;
                var re  = /MSIE ([0-9]{1,}[\.0-9]{0,})/;
                if (re.exec(ua) !== null){
                    defaults.version = parseFloat( RegExp.$1 );
                }
            }

            if(defaults.qString){
                var params = defaults.qString.split("&");

                for(var j=0;j<params.length;j++){
                    var k = params[j].split("=")[0], v = params[j].split("=")[1];
                    defaults.paramList[k] = v;
                }
            }
        }

        // Get children elements
        function getChildren(parent, name){
            var nodes = [];
            for(var r=0;r<parent.childNodes.length;r++){
                if(parent.childNodes[r].nodeType === 1 && parent.childNodes[r].nodeName === name.toUpperCase()){
                    nodes.push(parent.childNodes[r]);
                }
            }
            return nodes;
        }

        // Gets the current date
        function getCurrentDate(){
            var curr = new Date(), day = curr.getDay(), month = curr.getMonth(), date = curr.getDate(), year = curr.getFullYear();
            var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "Decemeber"];
            var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];


            var currDate = document.getElementById('current-date');
            if(currDate){
                currDate.innerHTML = days[day] + ", " + months[month] + " " + date + ", " + year;
            }
        }


function setNavContext(){

            if(!defaults.mainNavRoot){
                return;
            }

            // Check by commercial node
            var mainNavRoot = defaults.mainNavRoot;
            var mainSubNavRoot = document.getElementById('main-sub-nav');
            var mainNavChildren = getChildren(mainNavRoot, 'li');
            var subcategoryNav = document.getElementById('main-category-nav-wrapper');

            for(var a=0;a<mainNavChildren.length;a=a+1){
                var item = mainNavChildren[a];
                if(item.getAttribute('data') == defaults.nodeRoot){
                    var currClass = (item.getAttribute('class')) ? item.getAttribute('class') : '';
                    item.className = (currClass !=  '') ? currClass + ' active' : ' active';
                    defaults.nodeMatched = true;
                    break;
                }
                
            }

            // check next by nid
            if(!defaults.nodeMatched){
                for(var b=0;b<mainNavChildren.length;b=b+1){
                    var item = mainNavChildren[b];
                    var dataAttr = (item.getAttribute('data')) ? item.getAttribute('data') : '';
                    if(defaults.paramList && defaults.paramList.nid == dataAttr) {
                        var currClass = (item.getAttribute('class')) ? item.getAttribute('class') : '';
                        item.className = currClass + 'active';
                        break;
                    }
                }
            }

            if(mainSubNavRoot){
                var mainSubNavChildren = getChildren(mainSubNavRoot, 'li');
                for(var c=0;c<mainSubNavChildren.length;c=c+1){
                    var item = mainSubNavChildren[c];
                    var dataAttr = (item.getAttribute('data')) ? item.getAttribute('data') : '';
                    if(defaults.nodeRootChild && dataAttr == defaults.nodeRootChild){
                        var currClass = (item.getAttribute('class')) ? item.getAttribute('class') : '';
                        item.setAttribute('class', currClass + ' active');
                        break;
                    }
                }
            }

            // Highlight CategoryNode
            if(subcategoryNav){

                subcategoryNav.style.display = "block"

                var ulNodes = getChildren(subcategoryNav, 'ul');
                for (var i=0;i<ulNodes.length;i++){

                    var dataAttr = ulNodes[i].getAttribute("data");

                    if (dataAttr && dataAttr == defaults.nodeRootChild) {
                        ulNodes[i].style.display = "block";
                      
                        var liNodes = getChildren(ulNodes[i], 'li');

                        for (var j=0;j<liNodes.length;j++) {
                            if (liNodes[j].getAttribute("data") == defaults.nodeRootChildCategory){
                                var currClass = (liNodes[i].getAttribute('class')) ? liNodes[j].getAttribute('class') : '';
                                liNodes[j].className = 'active';
                                
          
                            }
                        }
                    }
                }


                var mainSubNavChildren = getChildren(mainSubNavRoot, 'li');
                for(var c=0;c<mainSubNavChildren.length;c=c+1){
                    var item = mainSubNavChildren[c];
                    var dataAttr = (item.getAttribute('data')) ? item.getAttribute('data') : '';
                    if(defaults.nodeRootChild && dataAttr == defaults.nodeRootChild){
                        var currClass = (item.getAttribute('class')) ? item.getAttribute('class') : '';
                        item.className = 'active';
                        break;
                    }
                }
            }
        }

        function setBranding(){
            var logo = document.getElementById('logo');
            //var logoChildren = getChildren(logo, 'a');

            if(defaults.nodeRoot == 'politics'){
                logo.className = defaults.nodeRoot;
                //logoChildren[0].setAttribute('href', 'http://www.washingtonpost.com/politics');
            } else if (defaults.nodeRoot == 'business') {
                logo.className = defaults.nodeRoot;
                //logoChildren[0].setAttribute('href', 'http://www.washingtonpost.com/business');
            } else if (defaults.nodeRoot == 'local') {
                logo.className = defaults.nodeRoot;
                //logoChildren[0].setAttribute('href', 'http://www.washingtonpost.com/local');
            } else if (defaults.nodeRoot == 'national') {
                logo.className = defaults.nodeRoot;
                //logoChildren[0].setAttribute('href', 'http://www.washingtonpost.com/national');
            }


        }

        function addEvent(el, evt, callback, cap){
            if(el && evt){
                if(el.addEventListener){
                    el.addEventListener(evt, callback, cap);
                } else {
                    evt = (evt == 'mouseover') ? 'mouseenter' : evt;
                    evt = (evt == 'mouseout') ? 'mouseleave' : evt;
                    el.attachEvent('on' + evt, callback);
                }
            }
        }

        function removeEvent(el, evt, callback, cap){
            if(el && evt){
                if(el.removeEventListener){
                    el.removeEventListener(evt, callback, cap);
                } else {
                    evt = (evt == 'mouseover') ? 'mouseenter' : evt;
                    evt = (evt == 'mouseout') ? 'mouseleave' : evt;
                    el.detachEvent('on' + evt, callback);
                }
            }
        }

        function setAuthenticationLinks(){
            // Determine if the user is authenticated, show the proper creds
            var signin = document.getElementById('global-signin');
            var registration = document.getElementById('global-registration');
            var userName = null;
            var pref = ' | <a href="http://www.washingtonpost.com/ac2/wp-dyn?node=admin/registration/manage&destination=manage&nextstep=gather">Change Preferences</a>';

            if(signin && registration){
                if(TWP.Util.User.getAuthentication()){
                    userName = TWP.Util.User.getUserName();

                    // User is signed in
                    if(TWP.Util.User.getUserType() == 'fbuname'){
                        var html = '<span class="icon facebook sm"><a href="http://www.washingtonpost.com/wp-srv/community/mypost/index.html?newspaperUserId=' + userName + '">' + userName + '</a></span>';
                        if(defaults.nodeRoot == 'mypost'){
                            html += pref;
                        }

                        signin.innerHTML = html;
                        registration.innerHTML = '<a href="http://www.washingtonpost.com/ac2/wp-dyn?node=admin/registration/login&destination=logout&nextstep=confirm">Sign Out</a>';
                        return;
                    }

                    var html = '<span>Hello</span> <a href="http://www.washingtonpost.com/wp-srv/community/mypost/index.html?newspaperUserId=' + userName + '">' + userName + '</a>';
                    if(defaults.nodeRoot == 'mypost'){
                        html += pref;
                    }

                    signin.innerHTML = html;
                    registration.innerHTML = '<a href="http://www.washingtonpost.com/ac2/wp-dyn?node=admin/registration/login&destination=logout&nextstep=confirm">Sign Out</a>';
                } else {
                    signin.innerHTML = '<a href="http://www.washingtonpost.com/ac2/wp-dyn?node=admin/registration/register&destination=login&nextstep=gather&application=reg30-globalnav&applicationURL=' + defaults.url + '">Sign In</a>';
                    registration.innerHTML = '<a href="http://www.washingtonpost.com/ac2/wp-dyn?node=admin/registration/register&destination=register&nextstep=gather&application=reg30-globalnav&applicationURL=' + defaults.url + '">Register Now</a>';
                }
            }
        }

        // Sets up user tools
        function setupUserTools(){
            // Tools menu
            var userTools = document.getElementById('user-tools');
            var utilityWrapper = document.getElementById('utility-wrapper');
            var userToolsActive = false;
            var openTimer = null;
            var closeTimer = null;
            var listItems = getChildren(userTools, 'li');

            function onExpand(){
                addEvent(userTools, 'mouseout', hideTools, true);
            }

            function onCollapse(){
                for(var c=0;c<userTools.childNodes.length;c=c+1){
                    if(userTools.childNodes[c].nodeName == "LI"){
                        var listItem = userTools.childNodes[c];

                        if(listItem.className != ""){
                            listItem.className = (listItem.className).replace('selected', '');
                        }
                    }
                }

                addEvent(userTools, 'mouseover', showTools, false);
            }

            function showTools(e){
                removeEvent(userTools, 'mouseover', showTools, false);

                if(!e){
                    var e = window.event;
                }
                e.cancelBubble = true;

                if (e.stopPropagation){
                    e.stopPropagation();
                }

                if(userToolsActive){
                    clearTimeout(closeTimer);
                    closeTimer = null;
                    return false;
                }

                var setup = {
                    target : utilityWrapper,
                    speed : 300,
                    height : 50,
                    callback : onExpand
                };

                if(!openTimer){
                    openTimer = setTimeout(function(){
                        if(!userToolsActive && utilityWrapper.getAttribute('style') != ''){
                            userToolsActive = true;
                            animate(setup);
                        }
                        openTimer = null;
                    }, 1000);
                } else {
                    clearTimeout(openTimer);
                    openTimer = null;
                }
                return false;
            }

            function hideTools(e){
                var oldRelated = e.relatedTarget;
                var related = e.relatedTarget;
                // Traverse up the tree
                while (related && related != userTools){
                    try {
                        related = related.parentNode;
                    } catch(ex) {
                        related = userTools;
                    }
                }
                if(oldRelated === related || related === null){
                    setup = {
                        target : utilityWrapper,
                        speed : 300,
                        height : 23,
                        callback : onCollapse
                    };

                    closeTimer = setTimeout(function(){
                        if(userToolsActive){
                            removeEvent(userTools, 'mouseout', hideTools, true);
                            animate(setup);
                            userToolsActive = false;
                        }
                    }, 1000);
                } else {
                    return false;
                }
            }

            if(userTools){
                addEvent(userTools, 'mouseover', showTools, false);

                function addSelected(e){
                    if(!e){
                        var e = window.event;
                    }

                    for(var c=0;c<listItems.length;c=c+1){
                        var listItem = listItems[c];
                        if(listItem.className != ""){
                            listItem.className = (listItem.className).replace('selected', '');
                        }
                    }

                    var node = (e.target) ? e.target.parentNode : e.srcElement.parentNode;
                    while (node && node.nodeName != "LI"){
                        node = node.parentNode;
                    }
                    node.className = "selected";
                }

                for(var j=0;j<listItems.length;j=j+1){
                    var li = listItems[j];
                    var anchor = getChildren(li, 'A')[0];
                    addEvent(anchor, 'mouseover', addSelected, false);
                }
            }
        }


        function moveSingleVal(currentVal, finalVal, frameAmt){
            if(frameAmt === 0 || currentVal === finalVal){
                return finalVal;
            }

            currentVal += frameAmt;
            if((frameAmt> 0 && currentVal>= finalVal) || (frameAmt <0 && currentVal <= finalVal)){
                return finalVal;
            }

            return currentVal;
        }

        function doFrame(el, currHt, ht, fHt, callback){
            if(el === null){
                return;
            }
            currHt = moveSingleVal(currHt, ht, fHt);

            if(defaults.browser == 'msie' && defaults.version < 8){
                el.style.height = Math.round(currHt);
            } else {
                el.setAttribute('style', 'height:' + Math.round(currHt) + 'px;');
            }

            if(currHt == ht){
                if(callback !== null){
                    callback();
                }
                return;
            }

            setTimeout(function(){
                doFrame(el, currHt, ht, fHt, callback);
            }, 40);
        }

        function animate(config){
            var el = config.target;
            var speed = config.speed;
            var ht = config.height;
            var currHt = (el.offsetHeight) ? el.offsetHeight : el.style.pixelHeight;
            var totalFrames = 1;
            var callback = config.callback;

            if(speed>0){
                totalFrames = speed/40;
            }

            var fHt = ht - currHt;
            if(ht!==0){
                fHt /= totalFrames;
            }

            doFrame(el, currHt, ht, fHt, callback);
        }

        // END: Private Methods


        // BEGIN: Set everything up
        getEnvInfo();

        var nodeHierarchy = null;

        // Determine where we are in the heirarchy by nodes
        if(window.thisNode){
            defaults.thisNode = window.thisNode;
        }

        if(window.navNode || window.commercialNode){
            defaults.navNode = window.navNode || window.commercialNode;

            if(defaults.navNode.indexOf("/")){
                nodeHierarchy = defaults.navNode.split("/");
            }

            if(nodeHierarchy.length){
                defaults.nodeRoot = nodeHierarchy[0];
                if(nodeHierarchy.length > 1){
                    defaults.nodeRootChild = nodeHierarchy[1];
                    if (nodeHierarchy.length > 2) {
                        defaults.nodeRootChildCategory = nodeHierarchy[2];
                    }
                }
            } else {
                defaults.nodeRoot = nodeHierarchy;
            }
        }


        // Initialize the user, available globally
        TWP.Util.User.init();

        // Set global authentication links
        setAuthenticationLinks();

        // Initialize drop menu in IE
        if(defaults.browser == 'msie'){
            var setup = {
                target : document.getElementById('user-tools')
            };
            TWP.Util.DropDownMenuIE(setup);

            setup = {
                target : document.getElementById('main-nav')
            };
            TWP.Util.DropDownMenuIE(setup);
        }

        // Set the navigation context
        setNavContext();

        // set branding
        setBranding();

        // Get current date
        getCurrentDate();
    };
})();
