/**
 * @author Adam McIntyre
 * Wrapper module for Omniture tagging business logic.
 */




OmnitureHelper = (function(){
    var DELIMETER = "|",
      bcRegex = /\//g,
      commandQueue = [],
      undefined;

    var allProps = [2,3,4,5,8,9,10,12,13,14,16,17,18,19,20];  // All active sProp values. Used to reset to null after data transmissions.
    var allEvars = [6,7,8,9,10,11,20,21,22,23];  // All active sProp values. Used to reset to null after data transmissions.
    var propLength = 100;  // Maximum length of a "prop" string

    return{
        _getUrlPath : function(sUrl){
            if(! sUrl) sUrl = window.location.href;
            var h = document.location.hostname;
            if(document.location.port){
                h += ':' + document.location.port;
            }

            return sUrl.substr(sUrl.indexOf(h) + h.length);
        },
        _getFileName : function(type,sUrl){
            var remainingChars = propLength - type.length;
            var path = this._getUrlPath(sUrl);

            if(path.length > remainingChars){
                return path.substr(path.length - remainingChars);
            }
            else{
                return path;
            }
        },
        /***
         * Walks up crumb's parent tree, constructing a string based on parent Elements' innerHTML.
         * Assumes HTMLElement is a ListItem.
         * @param {HTMLElement} breadcrumb Base-level Element
         */
        _buildBreadCrumb : function(breadcrumb){
            return this._getUrlPath().replace(bcRegex, ' &gt; ');
        },
        /***
         * Queues up a given setProp event if s (Omniture) is not available or fires it immediately.
         * @param {String} propNumber Number of sProp we'd like to call
         * @param {String|Array} args String or Array of strings to add to set sProp's value to
         */
        setProp : function(propNumber,args){
            if(typeof s == 'undefined'){
                var o = this;
                o.queueCommand(function(){
                    o._configureProp(propNumber,args);

					if(jQuery.inArray('prop' + propNumber, o.linkTrackVars) == -1) {
						o.linkTrackVars.push('prop' + propNumber);
					}
                });
            }
            else{
                this._configureProp(propNumber,args);

				if(jQuery.inArray('prop' + propNumber, this.linkTrackVars) == -1) {
					this.linkTrackVars.push('prop' + propNumber);
				}
            }

            return this;
        },
        /***
         * Sets a given "sProp" variable, given by propNumber, to a DELIMTER-delimted string of vals
         * @param {String} propNumber Number of sProp we'd like to call
         * @param {String|Array} args String or Array of strings to add to set sProp's value to
         */
        _configureProp : function(propNumber,args){
            var prop = s['prop'+propNumber];

            if(typeof prop == 'undefined'){
                s['prop'+propNumber] = '';
            }

            if((typeof s['prop'+propNumber]) != 'undefined'){
                if(typeof args === 'string' || typeof args === 'number' || args === null) {
                    s['prop'+propNumber] = args;
                }
                else{
                    s['prop'+propNumber] = args.join('|');
                }
            }
            return this;
        },
        /***
         * Queues up a given setEvar event if s (Omniture) is not available or fires it immediately.
         * @param {String} varNumber Number of eVar we'd like to call
         * @param {String|Array} args String or Array of strings to add to set eVar's value to
         */
        setEvar : function(varNumber,args){
            if(typeof s == 'undefined'){
                var o = this;
                YAHOO.util.Event.addListener(window,'load',function(){
                    if(typeof s == 'undefined'){
                        setTimeout(function(){
                            o._configureEvar(varNumber,args);
                        },1600);
                    }
                    else{
                        o._configureEvar(varNumber,args);

						if(jQuery.inArray('eVar' + varNumber, o.linkTrackVars) == -1) {
							o.linkTrackVars.push('eVar' + varNumber);
						}
                    }
                });
            }
            else{
                this._configureEvar(varNumber,args);

				if(jQuery.inArray('eVar' + varNumber, this.linkTrackVars) == -1) {
					this.linkTrackVars.push('eVar' + varNumber);
				}
            }

            return this;
        },
        /***
         * Sets a given "eVar" variable, given by varNumber, to a DELIMTER-delimted string of vals
         * @param {String} varNumber Number of eVar we'd like to call
         * @param {String|Array} args String or Array of strings to add to set eVar's value to
         */
        _configureEvar : function(varNumber,args){
            var sEVar = s['eVar'+varNumber];

            if(typeof sEVar == 'undefined'){
                s['eVar'+varNumber] = '';
            }

            if((typeof s['eVar'+varNumber]) != 'undefined'){
                if(typeof args === 'string' || typeof args === 'number' || args === null) {
                    s['eVar'+varNumber] = args;
                }
                else{
                    s['eVar'+varNumber] = args.join('|');
                }
            }
            return this;
        },
        /***
         * Queues up a given setProducts event if s (Omniture) is not available or fires it immediately.
         * @param {String} prod_id is the product ID to set
         * @param {String} prod_name is the product Name to set
         */
        setProductIdAndName: function(prod_id, prod_name) {
        	this.setProducts(prod_id + '|' + prod_name);

        	return this;
        },
        /***
         * Queues up a given setProducts event if s (Omniture) is not available or fires it immediately.
         * @param {String} val Value we'd like to set s.products to
         */
        setProducts : function(val){
            var cVal = val;
            var o = this;
            if(typeof s == 'undefined'){
                this.queueCommand(function(){
                    o._addProduct(cVal);
                });
            }
            else{
                o._addProduct(cVal);
            }
            return this;
        },
        /***
         * Adds a product in a non-destructive manner.
         * @param {String|Array} ars Name/ID of product we're adding, i.e. "D80" or ["25343","D2000"]
         */
        _addProduct : function(args){
            if(args === null){
                s.products = null;
            }
            else if(typeof s.products === "string"){
                if(typeof args === 'string' || typeof args === 'number'){
                    s.products += ";" + args;
                }
                else{
                    s.products += ";" + args.join('|');
                }
            }
            else{
                if(typeof args === 'string' || typeof args === 'number'){
                    s.products = ";" + args;
                }
                else{
                    s.products = ";" + args.join('|');
                }
            }

			if(s.products !== null) {
				if(s.products.indexOf(',') == 0){
					s.products = s.products.substr(1);
				}
				s.products += ',';
			}

            if(s !== undefined && jQuery.inArray('products', this.linkTrackVars) == -1 && s.products) {
            	this.linkTrackVars.push('products');
            }
        },
        _cleanUpProducts: function() {
            if(s.products && s.products.lastIndexOf(',') == (s.products.length-1)) {
                s.products = s.products.substr(0, s.products.length-1);
            }
        },
        /***
         * Sets the s.events tag to eventName
         * @param {String} eventName Name of event we're triggering i.e. "event13"
         */
        setEvents : function(eventName){
            var eName = eventName;
            if(typeof s == 'undefined'){
                this.queueCommand(function(){
                    if(typeof s.events == 'undefined'){
                        s.events = eName;
                    }
                    else if(s.events && s.events.indexOf(eName) < 0){
                        s.events = eName;
                    }
                });
            }
            else{
                if(typeof s.events == 'undefined'){
                    s.events = eName;
                }
                else if(s.events && s.events.indexOf(eName) < 0){
                    s.events = eName;
                }
            }
            return this;
        },
        /***
         * Sets the s.events tag to eventName in a non-destructive manner.
         * If you're setting more than one on a page, use this method.
         * @param {String} eventName Name of event we're triggering i.e. "event13"
         */
        setEvents_safe : function(eventName){
            var eName = eventName;
            var o = this;
            if(typeof s == 'undefined'){
                this.queueCommand(function(){
                    o._addEvent(eName);

					if(jQuery.inArray('events', o.linkTrackVars) == -1) {
						o.linkTrackVars.push('events');
					}

					o.linkTrackEvents.push(eName);
                });
            }
            else{
                o._addEvent(eName);

				if(jQuery.inArray('events', this.linkTrackVars) == -1) {
					o.linkTrackVars.push('events');
				}

            	o.linkTrackEvents.push(eName);
            }

            return this;
        },
        /***
         * Adds an event tags in a non-destructive manner.
         * @param {String} eventName Name of event we're triggering i.e. "event13"
         */
        _addEvent : function(eventName){
            if(typeof s.events === "string"){
                if(s.events.indexOf(eventName) < 0){
                    s.events += "," + eventName;
                }
            }
            else{
                s.events = eventName;
            }
        },
        /***
         * Removes event tags. Use after an s.tl() call or data transmit.
         */
        _removeEvents : function(){
            s.events = null;
        },
        /***
         * Clears all data, resetting all sProps and eVars identified in the arrays above.
         */
        _clearAllData : function(){
        	try {
        		s.test = 'test';
        	} catch(e) {
        		return;
        	}

            for(var i = 0, max = Math.max(allProps.length, allEvars.length); i < max;i++){
                if(i < allProps.length){
                    s['prop' + allProps[i]] = null;
                }
                if(i < allEvars.length){
                    s['eVar' + allEvars[i]] = null;
                }
            }
            s.products = null;
            s.pageName = null;
			this.linkTrackVars = [];
			this.linkTrackEvents = [];
            this._removeEvents();
        },
        /***
         * Sets the Omniture variables required to track interactions with the navigation.
         * Must be transmitted immediately.
         * @param {String} navName The "name" of this navigation element (i.e. "top_nav", "side_nav");
         * @param {String} linkName The text-portion of this link.
         */
        setNavEvents : function(navName,linkName){
            this.setProp('19',[this._buildBreadCrumb(),navName,linkName]).sendLinkData("Breadcrumb Click");
            return this;
        },
        /***
         * Sets the "Products You've Viewed" interaction events
         * @param {String} pId The product ID of the product we're tracking
         * @param {String} pName The name of the product we're tracking
         */
        setPYVEvents : function(pId,pName){
            this.setEvents('event14').setProductIdAndName(pId, pName).sendLinkData("Products You've Viewed");
            return this;
        },
        /***
         * Sets the "Articles You've Viewed" interaction events
         * @param {String} aId The article ID of the article we're tracking
         * @param {String} aName The name of the article
         * @param {String} aCategory The category this article belongs to (i.e. "Nikon World")
         * @param {String} aLevel The level (beginner/advanced) of this article's content
         */
        setAYVEvents : function(aId,aName,aCategory,aLevel){
            this.setEvents('event15').setProp('14',[aId,aName,aCategory,aLevel]).setProp('13','Articles You\'ve Viewed|').setEvar('10',[aId,aName,aCategory,aLevel]).sendLinkData("Articles You've Viewed");
            return this;
        },
        /***
         * Sets the promo box link interaction events
         * @param {HTMLElement} linkEl The HTMLElement interacted with. Used to figure out "rank"/order/position that
         *   this link's parent box occurs in inside a row of promos (1, 2, 3...)
         * @param {String} boxTitle The title of this link's parent box
         * @param {String} linkUrl The URL of the given link
         * @param {String} linkTitle The title/text of this link
         */
        setPromoBoxEvents : function(linkEl,boxTitle,linkUrl,linkTitle){
            var ancestorPromo = YAHOO.util.Dom.getAncestorByClassName(linkEl,'promo_bw');

            var promos = YAHOO.util.Dom.getElementsByClassName('promo_bw');
            var boxRank = 0;
            for(var i = 0; i < promos.length; i++){
                if(promos[i] == ancestorPromo){
                    boxRank = i;
                    break;
                }
            }
            this.setEvents('event16').setEvents_safe('event13').setProp('12',boxRank + '').setProp('13',['Promo Box',boxTitle]).setProp('16',[linkUrl,linkTitle]).setProp('20',boxTitle)
                .setEvar('11',boxTitle).sendLinkData("Promobox Click");
            return this;
        },
        /***
         * Sets the Page View event
         */
        setPageViewEvent: function() {
        	s.pageName = s.getPageName();
        	this.setEvents_safe('event8').sendData();
        	this._clearAllData();
        	return this;
        },
        /***
         * Sets the overview/Component 5 link interaction events
         * @param {String} ovTitle The title used for component 5
         * @param {String} ovUrl The URL of the given link
         * @param {String} ovLinkText The text/copy of the given link
         */
        setOverviewEvents : function(ovTitle,ovUrl,ovLinkText){
            var pn = "";
            if(s.pageName){
                pn = s.pageName;
            }
            else{
                pn = document.title;
            }
            this.setEvents('event13').setProp('13',["Section Overview Header",ovTitle,pn]).setProp('16',[ovUrl,ovLinkText]).sendLinkData("Component 5 Click");
            return this;
        },
        /***
         * Sets up the events fired by clicking on articles under the "related content" tabs
         * @param {String} aId The ID of the parent article clicked on
         * @param {String} aName The name of the given article
         * @param {String} aLevel The level of the given article
         * @param {String} tabTitle The title of the currently active tab.
         */
        setRelatedTabEvents : function(aId,aName,aLevel,tabTitle){
            this.setEvents('event13').setProp('14',[aId,aName,aLevel]).setProp('13',['Related Content Tab',tabTitle]).setProp('16',tabTitle).sendLinkData('Related Content Tab');
            return this;
        },
        /***
         * Toggles the state of the in-page glossary
         * @param {Boolean} bState The on/off state of the glossary: true = on, false = off
         */
        setIPGStateEvent : function(bState){
            s.eVar16 = bState;
            this.sendLinkData("Glossary Toggle");
            return this;
        },
        /***
         * Sets the events associated with clicking on an in-page glossary term
         * @param {String} gTerm The term clicked on.
         */
        setIPGTermClickEvents : function(gTerm){
            this.setEvents('event13').setProp('13',['Glossary Term',gTerm]).sendLinkData('Glossary Term Click');
            return this;
        },
        /***
         * Sets the events associated with clicking on a Media Center thumbnail.
         * @param {String} tabTitle The title of the currently selected tab
         * @param {String} aType The "type" (Image, Video, Audio, Document) of the clicked item
         * @param {String} aUrl The URL this item's asset.
         * @param {String} aTitle The Title of the item, if available.
         */
        setMCThumbClickEvents : function(tabTitle,aType,aUrl,aTitle){
        	/*FIXIT?, needs productID & productName */
            // Transmit these events immediately, as clicks on multiple elements would clobber them.
            this.setEvents('event12').setProp('13',['Media Center',tabTitle]).setProp('18',[aType,this._getFileName(aType,aUrl),aTitle]).sendLinkData('Media Center');

            return this;
        },
        /***
         * Sets the events associated with enlarging a Media Center Image/playing Video or Audio/linking to a document.
         * @param {String} aType The "type" (Image, Video, Audio, Document) of the clicked item
         * @param {String} aUrl The URL this item's asset.
         * @param {String} aTitle The Title of the item, if available.
         */
        setMCEnlargeClickEvents : function(aType,aUrl,aTitle){
        	/*FIXIT, needs productID & productName */
            // Transmit these events immediately, as clicks on multiple elements would clobber them.
            this.setEvents('event14').setProp('18',[aType,this._getFileName(aType,aUrl),aTitle]).sendLinkData("Media Center Image Click");

            return this;
        },
        /***
         * Sets the events associated with clicking on a Media Bar thumbnail. At some point, I'd imagine this will match
         * what we're tracking above.
         * @param {String} aType The "type" (Image, Video, Audio, Document) of the clicked item
         * @param {String} aUrl The URL this item's asset.
         * @param {String} aTitle The Title of the item, if available.
         */
        setMediaBarThumbClickEvents : function(aType,aUrl,aTitle){
        	/*FIXIT, needs productID & productName */
            // Transmit these events immediately, as clicks on multiple elements would clobber them.
            this.setEvents('event12').setProp('18',[aType,this._getFileName(aType,aUrl),aTitle]).sendLinkData("Media Bar thumbnail Click");

            return this;
        },
        /***
         * Sets the events associated with clicking on a product view Media Bar thumbnail.
         */
        setMBProdView : function(){
        	/*FIXIT, needs productID & productName */
            // Transmit these events immediately, as clicks on multiple elements would clobber them.
            this.setEvents_safe('event10').sendLinkData("Media Bar thumbnail Click");

            return this;
        },
        /***
         * Sets the events associated with clicking on a product view.
         */
        setProdViewClick : function(){
        	/*FIXIT, needs productID & productName */
            this.setEvents_safe('event10').sendLinkData("Product View Click");

            return this;
        },
        /***
         * Flags whether or not we've altered the AddThis core functions on this page.
         *
         */
        _addThisSet : false,
        /***
         * Sets and immediately sends all events/props associated with mousing over or clicking "AddThis" widget
         */
        setAddThisEvents : function(){
        	/*FIXIT, needs productID & productName */
            this.setEvents('event13').sendLinkData("AddThis Widget Click");
            var o = this;

            if(typeof addthis_sendto === 'function' && ! this._addThisSet){
                var f = addthis_sendto;
                addthis_sendto = function(str){
                    o.setAddThisShareEvent(str);
                    f(str);
                    return false;
                }

                this._addThisSet = true;
            }

            return this;
        },
        /***
         * Sets and immediately sends the events/props associated with sharing an item through "AddThis" widget.
         * @param {String} str Name of service used to share
         */
        setAddThisShareEvent : function(str){
        	/*FIXIT, needs productID & productName */
            this.setProp('13',['AddThis',str]).sendLinkData("AddThis Widget Click");
            return this;
        },
        /***
         * Sets and immediately sends the events/props associated with printing a page.
         * @param {String} s Name of service used to share
         */
        setPrintEvent : function(){
        	/*FIXIT, needs productID & productName */
            this.setEvents('event13').setProp('13',['Print Page']).sendLinkData("Print Page Click");
            return this;
        },
        /***
         * Sets the events/props associated with filtering on the Nikon World Past Issue page.
         * @param {String} cat Current category filter
         * @param {String} subcat Current subcategory filter.
         */
        setWorldFilterEvent : function(cat,subcat){
            this.setProp('17',[cat,subcat]);
            return this;
        },
        /***
         * Sets up the events fired by clicking on articles under the "related content" tabs
         * @param {String} aId The ID of the parent article clicked on
         * @param {String} aName The name of the given article
         * @param {String} aCategory The category of the given article
         * @param {String} aLevel The level of the given article
         */
        setArticleDetailEvent : function(aId,aTitle,aCategory,aLevel){
            this.setProp('14',[aId,aTitle,aCategory,aLevel]);
        },
        /***
         * Sets up the events fired by performing a search
         * @param {String} term The value of the term being searched for
         * @param {String} type (Optional) Optional "type" of search conducted, i.e. "product" for a product search,
         *     "noResults" for a search yielding no results.
         */
        setSearchEvent : function(term,type){
            var o = this;
            this.addPixel(function(){
                var tmpTerm = term.replace(/'/g,"&#39;").replace(/"/g,"&quot;");
                var sChannel = "";
                if(s.channel){
                    sChannel = s.channel;
                }

                if(type && type == 'noResults'){
                    o.setEvents('event5').setProp('3',[tmpTerm,sChannel]);
                }
                else if(type && type == 'product'){
                    o.setEvents('event5').setProp('8',[tmpTerm,sChannel]).setEvar('7',[tmpTerm,sChannel]).setEvents_safe('event11');
                }
                // This data will be captured from search forms originally.
                // If there is a search string, the user has performed another search on the search results page.
                else if(document.location.search){
                    o.setEvents('event5').setProp('2',[tmpTerm,sChannel]);
                }

                return o;
            });
            return true;    // Return true here in case this is bound to a search form.
        },
        /***
         * Sets up the events fired by performing a search via a form
         * @param {HTMLElement} f The form used to submit the search
         */
        setSearchFormEvent : function(f){
            var o = this;

                var inputs = f.getElementsByTagName('input');
                var term;
                for(var i = 0; i < inputs.length; i++){
                    if(inputs[i].name == 'q'){
                        term = inputs[i].value;
                        break;
                    }
                }

                var tmpTerm = term.replace(/'/g,"&#39;").replace(/"/g,"&quot;");
                var sChannel = "";
                if(s.channel){
                    sChannel = s.channel;
                }
                o.setEvents('event5').setProp('2',[tmpTerm,sChannel]).sendLinkData("Search Form Click");

            return true;    // Return true here in case this is bound to a search form.
        },
        /***
         * Sets the events associated with the various tracking points on the WTB page
         * @param {String} type The type of event that we'd like to trigger.
         * @param {Array|String|Object} vals (Optional) The value(s) we'd like to set type to.
         */
         setWTBEvent : function(type,vals){
             switch(type){
                 case "checkout":
                     this.setEvents_safe('scCheckout').sendData();
                     break;
                 case "add":
                     this.setEvents_safe('scAdd').sendData();
                     break;
                 case "zip":
                     this.setProp('9',vals).setEvar('8',vals).sendData().setProp('9',null).setEvar('8',null);
                     break;
                 case "category":
                     this.setProp('10',vals).setEvar('9',vals).sendData().setProp('10',null).setEvar('9',null);
                     break;
                 case "product":
                     this.setProducts(vals).setEvents_safe('scAdd').sendData().setProducts(null);
             }
             return this;
         },
        /***
         * Sets the events associated with "viewing" a product on a given page. Note that these are "non-detailed" views, like those associated with
         * a component 1 or category page view.
         * @param {String|Array} p ID/name of product that's been viewed, i.e. "D80" or ["25443","D200"]
         */
         setProdViewEvent : function(p){
             this.setEvents_safe('prodView').setProducts(p);
             return this;
         },
        /***
         * Queues up all of the various products we see on a product listing page
         * @param {String|Array} p ID/name of product that's been viewed, i.e. "D80" or ["25443","D200"]
         */
        setProdViewListEvent : function(p){
            this.setProducts(p);
        },
        /***
         * Sends data for the various products we see on a product listing page
         */
        sendProdViewList : function(p){
            this.setEvents_safe('prodView').sendLinkData("Product View Click");
        },
        /***
         * Sets the events associated with "viewing" a product detail page.
         * @param {String} pId ID of product that's been viewed, i.e. "25443"
         * @param {String} pName Name of product that's been viewed, i.e. "D80"
         */
         setProdDetailEvents : function(pId,pName){
             this.setEvents_safe('event7').setProdViewEvent([pId,pName]);
             return this;
         },
        /***
         * Sets the events associated with initiating a download.
         * @param {HTMLElement} el The link element we're clicking on to initiate the download.
         */
         setDownloadEvent : function(el){
             var pn = s.pageName || document.title.replace(' ','-');
             var fileName = el.pathname || el.href;
             this.setEvents_safe('event4').setProp('4',this._getUrlPath(fileName)).setProp('5',pn).setEvar('6',this._getUrlPath(fileName)).sendData().setProp('4',null).setProp('5',null).setEvar('6',null);
             return true;
         },
        /***
         * Invokes Omniture's s.t function, transmitting all data to Omniture
         */
        sendData : function(){
            if(this.tmpOmnitureVar){
                this.tmpOmnitureVar.t();
            	this._clearAllData();
                this._removeEvents();
            }
            else{
                if(typeof s !== 'undefined'){
                	s.linkTrackVars = this.linkTrackVars.join(',');
					s.linkTrackEvents = this.linkTrackEvents.join(',');
                    this._cleanUpProducts();
                    s.t();
            		this._clearAllData();
                    this._removeEvents();
                }
            }
            return this;
        },
        /***
         * Invokes Omniture's s.tl function, transmitting all data to Omniture
         */
        sendLinkData : function(text){
            if(this.tmpOmnitureVar){
                this.tmpOmnitureVar.tl(true, 'o', text);
            	this._clearAllData();
                this._removeEvents();
            }
            else{
                if(typeof s !== 'undefined'){
                	s.linkTrackVars = this.linkTrackVars.join(',');
					s.linkTrackEvents = this.linkTrackEvents.join(',');
                    this._cleanUpProducts();
                    s.tl(true, 'o', text);
            		this._clearAllData();
                    this._removeEvents();
                }
            }
            return this;
        },
        /***
        *  Initializes Omniture, writing it to the page, etc.
        */
        init : function(siteName){
            var o = this;
            if(typeof YAHOO !== undefined && !(window.location.href.indexOf('iw-cc')>0)){
            	var callback = {onSuccess : function(){
									s.server = location.hostname;
									/*
									var s_code = s.t();
									if(s_code) {
										var div = document.createElement('div');
										div.style.display = 'none';
										div.innerHTML = s_code;
										document.body.appendChild(div);
									}
									*/
									o.processQueue();
									o.setPageViewEvent();

									try {
                						init_omniture_event_tracker();
                					} catch(e) {
                						//Not on product details page.
                					}
                              },
                              onFailure : function(){}};

				if(YAHOO.env.ua.ie > 0 && YAHOO.env.ua.ie < 7) {
                    YAHOO.util.Event.addListener(window, 'load', function() {
                        setTimeout(function() {
                          // Standard sitecatalyst script. Version R.14.
                          YAHOO.util.Get.script('/static/js/omniture/s_code_' + siteName + '.js?v=20100722', callback);}, 1500);
                   });
                } else {
                    YAHOO.util.Event.onDOMReady(function(){
                      // Standard sitecatalyst script. Version R.14.
                      YAHOO.util.Get.script('/static/js/omniture/s_code_' + siteName + '.js?v=20100722', callback);
                   });
                }
            }

        },
        /***
        *   Safely adds a JavaScript tracking pixel to the page
        *   @param f {Function} Function used to set pixel
        */
        addPixel : function(f){
            if(typeof s === 'undefined'){
                this.queueCommand(f);
            }
            else{
                f();
            }
        },
        /***
        *   Adds a command to the queue, which will be processed on Omniture's load
        *   @param f {Function} Function we'd like to queue
        */
        queueCommand : function(f){
            commandQueue.push(f);
        },
        /***
        *   Processes any commands queued up while Omniture was loading
        */
        processQueue : function(){
            for(var i = 0; i < commandQueue.length; i++){
                if(typeof commandQueue[i] == 'function'){
                    commandQueue[i]();
                }
            }
        },
        linkTrackEvents: [],
        linkTrackVars: []
    }
})();
