
/*** 
ITEM = Creates the SJourney application parent object which the application is namespaced under.
PARAM =
VALUE = SJourney application parent object
***/
if(!window.SJourney) var SJourney = {};


/*** 
ITEM = Method extension to built-in Object.
PARAM = Any valid Object
VALUE = Returns the size( like array length ) of the object members
***/
Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

/*** 
ITEM = Method to abstract event delegation
PARAM = An objec that defines the delegating element, and the function to run
VALUE = Returns a function closure holding the event state
***/
SJourney.eventDispatcher = function(rules){
    return function(e){
        var target = e.target;
        var targetNodeList = dojo.query(target);	
        for(var selector in rules){	
            if(targetNodeList.filter(selector).length){
                return rules[selector].apply(target, arguments);
            }
        }
    }
} 

/*** 
ITEM = Object to serialize / deserialize objects for cookie persistence
PARAM = Cookie name and Object to store, or cookie name to retrieve
VALUE = Stores a given object or returns the retrieved object
***/
SJourney.simplePersistence = {
    store: function(name, obj){
        dojo.cookie(name, dojo.toJson(obj), {expires: 7, path : "/"});
    },
    retrieve: function(name){
        return dojo.fromJson(dojo.cookie(name));
    }
};

/*** 
ITEM = Boolean flag used to notify the system that Card operations are the result of data being restored
from the cookie, if true. Otherwise, a user triggered an action that indicates the persistent state should update
PARAM = boolean true or false
VALUE = boolean true or false
***/
SJourney.restoreState = false;

/*** 
ITEM = Object to set/get page level variables with values set by AET
PARAM = 
VALUE = Stores a given object or returns the retrieved object
***/
SJourney.pageInfo = {
    pageName: "",
	context: "",
	contextPath: "",
	
	init: function() {
		try {
			this.context = sj_pageContext.toLowerCase();
			
		} catch (e) {
		this.context = (sj_pageContext === null) ? "prospect" : "cardmember";
		}
		
		try { this.pageName = sj_pageName; } catch(e) { this.pageName="not set"; }

		this.contextPath = "ngaccsg";
		
		//change previously established global variables, done here for timing
		appContextPath = "/"+SJINFO.contextPath+"/";
		jsContextPath = "/"+SJINFO.contextPath+"/SJjs/";	
	}
};
var SJINFO = SJourney.pageInfo;

/*** 
ITEM = Parent object for utilities used on multiple pages
***/
SJourney.Utilities = {
	pageType: "",
	
	//sets pageType if value is obtainable.
	//value is taken from AET page level/global variable sj_PageType set in header of jsps
	setPageType: function() {
		if(typeof(sj_PageType!="undefined")) {
			this.pageType = (typeof(sj_pageType)=="undefined") ? sj_PageType : sj_pageType;
			this.pageType = this.pageType.toLowerCase();
		} else {
			this.pageType = "not set";
		}
	},
	
	//pass an element to this to add an event listener that will add/remove class "hover" on mouseover/out
	//must be an array (dojo nodeList) so leave out [0]
	setHover: function(element) { //console.log("setHover");
		dojo.forEach(element,function(element,index,array) {
			dojo.connect(element,"onmouseover",function(element) {
				dojo.addClass(element.target,"hover");
			});	
			dojo.connect(element,"onmouseout",function(element) {
				dojo.removeClass(element.target,"hover");
			});
		});
	},
	
    //Function to dynamically activate all dormant dojo tooltips within a given element. 
	//Mainly to be used when an ajax request has placed new HTML into an element. 
    sj_activateTooltipsInElement: function(element){
	   var children=element.childNodes;
	   //cancel the link action for the footnote a tags
	   dojo.query(".sj_tooltipLegal a").onclick(function(e){
			   dojo.stopEvent(e);
	   });
	   for(var i=0;i<children.length;i++){
			 var this_child=children[i];
			 if(this_child.nodeType!=1){continue;}
			 if(!dojo.attr(this_child, 'dojoType')||dojo.attr(this_child,'dojotype')!="dijit.Tooltip"||!dojo.attr(this_child, 'connectId')){
				   SJourney.Utilities.sj_activateTooltipsInElement(this_child);
				   continue;
			 }
			 if(this_child.id && dijit.byId(this_child.id)){continue;}
			 var this_tooltip=new dijit.Tooltip({connectId:[dojo.attr(this_child,'connectId')]}, this_child);
			 this_tooltip.startup();
	   }
    },
	
	//is this a flash page? do they have the right version? display the error if they dont
	checkFlash: function(){
	  if(dojo.query("#sj_flashContent")[0]) {
		try{
		   var playerVersion = swfobject.getFlashPlayerVersion(); // returns a JavaScript object
		   var majorVersion = playerVersion.major; 
		   if(majorVersion<8 || !majorVersion) {
			 dojo.query("#sj_flashError")[0].style.display="block";
		   } else {}
		}
		catch (err){
		   dojo.query("#sj_flashError")[0].style.display="block";
		}
	  }
	},
	
	//cookie checker
	cookieCheck: function() {
	    dojo.cookie('test','test');
		var sj_cookies = dojo.cookie('test');
		if(sj_cookies != "test") {
			if(dojo.query("#sj_noCookies")[0]) {
				dojo.query("#sj_noCookies")[0].style.display="block";
			}
		}
	},
	
	// switch pertinent elements for secure paths
	changePathsSSL: function (){
		if(window.location.protocol == "https:"){
			var links = document.getElementsByTagName("a");
			for(var x = 0, ln = links.length; x < ln; x++ ){
				for(var item in SSLPaths){
					if( links[x].href.match(SSLPaths[item][0]) ){
						links[x].href = links[x].href.replace(/http:/i, "https:");
						links[x].href = links[x].href.replace(SSLPaths[item][0], SSLPaths[item][1]);
					}
				}
			}
			// now change the base getCardContextPath to secure for scripts that make use of it later.
			getCardContextPath = SSLPaths.getCardSecure[1];
		}
	},
	
	// dojo xhr helper functions.
	replaceNode: function (node, url){
		return {
			sync: true,
			url: url,       
			handleAs: "text",
			node: dojo.byId(node),
			load: function (data, xhr){
					if(xhr.args.node){
						var frag = document.createElement("div");
						frag.innerHTML = data;
						xhr.args.node.parentNode.replaceChild(frag, xhr.args.node);
					}
			},
			error: function(response, ioArgs){
				return response;	
			}
		};
	},

	appendToNode: function (node, url){
		return {
			sync: true,
			url: url,       
			handleAs: "text",
			node: dojo.byId(node),
			load: function (data, xhr){
					if(xhr.args.node){
						var frag = document.createElement("div");
						frag.innerHTML = data;
						xhr.args.node.appendChild(frag);
					}
			},
			error: function(response, ioArgs){
				return response;	
			}
		};
	},

	insertIntoNode: function (node, url){
		return {
			sync: true,
			url: url,       
			handleAs: "text",
			node: dojo.byId(node),
			load: function(data, xhr){
					if(xhr.args.node){
						xhr.args.node.innerHTML = "";
						xhr.args.node.innerHTML = data;
					}
			},
			error: function(response, ioArgs){
				return response;	
			}
		};
	},
	
	screenHeight: function () {
		return  window.innerHeight != null? window.innerHeight : document.documentElement && document.documentElement.clientHeight ?  document.documentElement.clientHeight : document.body != null? document.body.clientHeight : null;
	},
	
	screenTop: function() {
		return typeof window.pageYOffset != 'undefined' ?  window.pageYOffset : document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop ? document.body.scrollTop : 0;
	},
	
	/* turns a mutable collection, like a NodeList, into an array. useful because NodeLists are live
	and still part of the DOM, whereas an array will be stand alone copies of the objects */
	collectionToArray: function (collection) {
		var tmp = [];
		for(var i=0, len = collection.length; i < len; i++){ tmp.push(collection[i]); }
		return tmp;
	},
	
	/* pass element name to create and array of name/value objects for each attribute. */
	createNewElement: function(obj){
		var newElm = document.createElement(obj.element);
		if(typeof obj.attribs != "undefined")
			for(var i=0; i < obj.attribs.length; i++){
				for(property in obj.attribs[i]){
					newElm.setAttribute(property, obj.attribs[i][property]);
				}
			}
		return newElm;
	},
	
	/* remove children */
	removeChildrenFromNode: function (node) {
		if(node.hasChildNodes()) {
			while(node.childNodes.length >= 1 ) {
				node.removeChild(node.firstChild);       
			} 
		}
	},
	renderFlash: function (bucketID/*id of container to place inside*/,swfURL,xmlURL,width,height,href,params/*array*/) {
        var div = document.createElement("div");
        div.setAttribute("id","sj_tc_flashHero");
        var bucket = dojo.query(bucketID)[0];
        bucket.appendChild(div);
        var so = new SWFObject(swfURL, "mymovie", width, height, "8");
        so.addParam("wmode", "opaque");
        so.addVariable("xmlPath", xmlURL);
        so.addVariable("config","loop: true");
        so.addVariable("clickURL",href);
        so.write("sj_tc_flashHero");
	}

}
var SJU = SJourney.Utilities;
	

/********* INTIALIZE ***/

SJourney.init = function (){

  
};
/** TaskBar package **/
SJourney.TaskBar = {};
var SJTB = SJourney.TaskBar;
/*** 
ITEM = TaskBar Object
VALUE = Container for member objects, and other possible operations the TaskBar may need.
***/
SJourney.TaskBar.Bar = {
    init: function(){
        //console.log("TaskBar initialized");
    }
};

/*** 
ITEM = CardTray Object
VALUE = Controls the list of cards in the TaskBar
***/
SJourney.TaskBar.CardTray = {
    cards : [],
    cardtray: null,
	numSlots: "",

    init: function(){
        // store ref to CardTray
        var self = this;

		//based on context (CardMember or Prospect), set the amount of cards
		this.numSlots = (SJINFO.context=="prospect") ? 5 : 4;

        /*@@ dojo.dnd.manager is a Singleton object. Changes made here affect ALL dnd behaviors on a page.
            It is worth considering an attempt to subclass this to make unique instances. Possible? Don't know yet... */
        var dndManager = dojo.dnd.manager();
        
        /*@@ the avatar offsets interact with these dojo functions in a bad way. it is a bug and causes dnd operations to fail.
            the functions are defined in dojo.dnd.autoscroll. they define two constants:
            dojo.dnd.V_AUTOSCROLL_VALUE = 16; and dojo.dnd.H_AUTOSCROLL_VALUE = 16;
            that happen to be the same values as the dojo.dnd.Manager constants OFFSET_X and OFFSET_Y. These are somehow related
            when dojo calculates positioning for dragged nodes and the drop targets they can drop to. Oddly, this all worked fine
            and then the bug manifested. I stripped all code to the bare bones and the problem still persisted. It was then I
            narrowed down to the apparent cause, the overriding of the OFFSET_* defaults. So, disabling the autoScroll by
            overidding with empty functions ( null will not work. dojo loader expects functions ), stops the problem, allows
            us to set our OFFSETS, it also prevents the scrolling problem but only in IE. Would still like to find a way to
            constrain to viewport. Too bad dojo does not provide proper interfaces to overriding behaviors....
        */
        dojo.dnd.autoScroll = function(e){};
        dojo.dnd.autoScrollNodes = function(e){};
        
        // change avatar offsets
        dndManager.OFFSET_X = -25;
        dndManager.OFFSET_Y = -50;

        // suppress avatar node "helper" text
        dojo.dnd.Avatar.prototype._generateText = function(){ return ""};

        // create drag source, set horizontal to get drag targeting to work left to right, call creator to build nodes
        this.cardtray = new dojo.dnd.Source("cardtray", {horizontal: true, creator: this.nodeCreator});
        
        // Source insertNodes requires a data array to tell it how many items to make. Also provides node metadata.
        this.cardtray.insertNodes(false, this.nodeDataCreator() );
        
        // suppress draggable on non-image card items
        this.cardtray.forInItems(function(item, id, map){
            if(item.data.type === "addCardSlot" || item.data.type === "cardslot")
            dojo.removeClass(dojo.byId(id), "dojoDndItem");
        }); 
        
        // wire card "remove" feature
        dojo.query("#cardtray").onclick(
            SJourney.eventDispatcher( 
            { 'span': function(){ self.updateSelfRemove(this.id) } }
        ));
        
        // listen for drop event, and animate the dropped node
        //@@ the anon function runs in the scope of the dojo object, not 'this'
        dojo.subscribe("/dnd/drop", function(){
            SJourney.TaskBar.CardTray.Animation.animateCardIn(self.cardtray.getSelectedNodes()[0]);
        });
        // handles returning card to its default place when a drop occurs outside the drop Source.
        //@@ scope of this is changed to the div, and cardDivOut must account for an empty event obj.
        dojo.subscribe("/dnd/cancel", function(e){
            SJourney.TaskBar.CardTray.Animation.cardDivOut.apply(self.cardtray.getSelectedNodes()[0]);
        });

        dojo.subscribe("/CardMenu/updateAdd", this, this.updateRemove);
        dojo.subscribe("/CardMenu/updateRemove", this, this.updateAdd);
        
        //console.log("CardTray initialized");
    },
    
    // helper method used by dojo.dnd.Source constructor for creating the tray nodes
    // nodeCreator will use this object to determine the created node content
    nodeDataCreator: function(){
        var nodeData = [];
        var addCardSlotFlag = false;
        
        for(var i=0; i < this.numSlots; i++){
            // if card object..
            if( this.cards[i] ){ nodeData.push( this.cards[i] ); }
            // or insert add card object
            else if( !addCardSlotFlag ){
                nodeData.push( SJourney.Cards.CardAddSlot );
                addCardSlotFlag = true;
            }
            // or empty slot object
            else{
                nodeData.push( SJourney.Cards.CardEmptySlot );				
            }
        }
        return nodeData;
    },
    
    // helper method used by dojo.dnd.Source constructor for creating the tray nodes
    // works in conjunction with nodeDataCreator
    nodeCreator: function (item, hint){ //console.log(item);
        var divTag = document.createElement("div");
        // need actual node for avatar to work.
        var img = document.createElement("img");
        img.src = "/"+SJINFO.contextPath+"/SJimages/clear.gif";
        dojo.addClass(img, item.cssClass);
        if(item.type === "cardslot"){ dojo.addClass(divTag, "stopEvt"); }
        divTag.appendChild(img);
        if(item.type === "card"){
            var removeImg = document.createElement("span");
            dojo.addClass(removeImg, "hide");
            removeImg.id = item.pmc;
            divTag.appendChild(removeImg);
        }
        return {node: divTag, data : item};
    },
    
    getCardByID: function(id){
        if(SJourney.TaskBar.CardTray.cards) {
            for(var i in this.cards)
            if( this.cards[i].pmc == id ) {
                return this.cards[i];
            }
            return null;
        }
    },
    
    numCardsCheck: function() {
        if(SJourney.TaskBar.CardTray.cards.length < SJourney.TaskBar.CardTray.numSlots) {
//            console.log("numCards less than 5, numCards = " + SJourney.TaskBar.CardTray.cards.length);
			if (dojo.hasClass("cardtray","noCards")) { 
				var cardImgNodesTest = dojo.query("#cardtray .stopEvt")
				var duration = 1000; var position = -25;
	            cardImgNodesTest.forEach(function(item){ 
					SJourney.TaskBar.CardTray.Animation.animateCardInSlow(item,duration,position);
					duration = (duration+1000);
					position = (position-25);
	            });
			}
			dojo.removeClass("savedCards","noCards");
			dojo.removeClass("cardtray", "noCards");
            return true;
        } else { 
            //console.log("numCards == 5");
            return false; }
    },
    
    cardInTrayCheck: function(cardObj) {
        var flag;
        if( SJourney.TaskBar.CardTray.getCardByID(cardObj.pmc)) {
            flag = 1;
        } else {
            flag=0;
        }
        if(flag==1) { return true; }
        else { return false; }
    },
    
    updateSelfRemove: function(pmc){
        var cardObj;
        for(var i in this.cards)
        if( this.cards[i].pmc === pmc ){
            cardObj = this.cards.splice(i,1)[0];
            this.removeFromTray( cardObj );
            this.updatePersistence(this.cards);
            dojo.publish("/CardTray/updateSelfRemove", [ cardObj ]); 
            break;
        }
    },
    
    updateRemove: function(cardObj){ console.log("CT: updateRemove");
        for(var i in this.cards)
        if( this.cards[i].pmc === cardObj.pmc ){
            cardObj = this.cards.splice(i,1)[0];
            this.removeFromTray( cardObj );
            this.updatePersistence(this.cards);     
            break;
        }
    },
    
    updateAdd: function(cardObj){
        console.log("CT: updateAdd");
        if(this.cards.length == 5) {
            SJourney.TaskBar.CardMenu.prepareModal(cardObj);
        } else {
            this.cards.push( cardObj );
            this.addToTray( cardObj );
            this.updatePersistence(this.cards);
        }
    },
    
    updatePersistence: function(cards){
        // store current cards
		//var guid = SJourney.simplePersistence.retrieve("blueboxpublic");
        if( !SJourney.restoreState ) {
        SJourney.simplePersistence.store("sj_cardsInTray", cards);
		}
    },
    
    addToTray: function(cardObj){
        // get add slot div, get tray, get next
        var addDiv = dojo.query("#cardtray .addCardSlot")[0].parentNode;
        var trayDiv = addDiv.parentNode;
        var nxtSib = addDiv.nextSibling;
        var newNodeRef; // store node for animation
        if( nxtSib ){
            // remove sib, add cardObj node, move it to the beginning
            trayDiv.removeChild( nxtSib );
            this.cardtray.insertNodes(null, [cardObj]);
            newNodeRef = trayDiv.lastChild;
            trayDiv.insertBefore(trayDiv.lastChild, addDiv);
        }
        else{
            // replace addDiv with new cardObj
            trayDiv.removeChild( addDiv );
            this.cardtray.insertNodes(null, [cardObj]);
            newNodeRef = trayDiv.lastChild;
        }
        SJourney.TaskBar.CardTray.Animation.animateCardIn(newNodeRef);
    },
    
    removeFromTray: function(cardObj){
        // get card div, get tray, look for addCard and add that if needed
        var selector = "#cardtray ." + cardObj.cssClass;
        var cardDiv = dojo.query( selector )[0].parentNode;
        var trayDiv = cardDiv.parentNode;
        
        SJourney.TaskBar.CardTray.Animation.animateCardOut(cardDiv,cardObj);
        
        if(SJourney.TaskBar.CardTray.cards.length < 5) {
            //this needs a better solution at some point. IE adds the slot before the old card fades, 
            //causing the bar to jump
            setTimeout("SJourney.TaskBar.CardTray.addCardSlot()",1000);
        }
        
    },
    
    addCardSlot: function(cardObj) {
        var trayDiv = dojo.query("#cardtray")[0];
        var slotDiv = document.createElement("div");
        var slotImg = document.createElement("img");
        slotImg.src = "/"+SJINFO.contextPath+"/SJimages/clear.gif";
        var addDiv = dojo.query("#cardtray .addCardSlot")[0];
        if(addDiv){ 
            dojo.addClass(slotImg, "cardslot");
            dojo.addClass(slotDiv, "stopEvt"); 
        }
        else{ dojo.addClass(slotImg, "addCardSlot"); }
        slotDiv.appendChild( slotImg );
        trayDiv.appendChild( slotDiv );
    }
};
var SJTBCT = SJourney.TaskBar.CardTray;
/*** 
ITEM = CardTray Animation Object
VALUE = Indicates to user they can remove a card, or drag it. Triggered by Mouse Over events.
***/
SJourney.TaskBar.CardTray.Animation = {
    init: function(){
        // get item lists
        var cardtray = dojo.query("#cardtray");
        
        cardtray.onmouseover(
            SJourney.eventDispatcher( 
                {'img': this.cardImgOver}
        ));
        
        cardtray.onmouseout(
            SJourney.eventDispatcher( 
                {'img': this.cardImgOut, 'div': this.cardDivOut}
        ));
        
        cardtray.onclick(
            SJourney.eventDispatcher( 
                {'.addCardSlot': SJourney.TaskBar.CardMenu.Animation.show}
        ));
        
        // attach class as 'switch' to suppress event when a drag starts, remove when dropped
        dojo.subscribe("/dnd/start", cardtray[0], function(){
            var cardImgNodes = dojo.query("div img", this);
            cardImgNodes.forEach(function(item){ 
                dojo.addClass(item, "stopEvt"); 
            });
        });
        dojo.subscribe("/dnd/drop", cardtray[0], function(){
            var cardImgNodes = dojo.query("div img", this);
            cardImgNodes.forEach(function(item){
                if(!dojo.hasClass(item, "cardslot"))
                dojo.removeClass(item, "stopEvt");
            });
        });
    },

    // order of statements is important. first, check if drag, then check if non-cards.
    specialEvents: function(obj, evt){
        // stop event if drag is in progress
        if( dojo.hasClass(obj, "stopEvt") ){
            dojo.stopEvent(evt);
            return true;
        } 
        // stop animation( but allow events to propagate) if not a card img, handle addCardSlot display
        if( dojo.hasClass(obj, "addCardSlot") || dojo.hasClass(obj, "cardslot") ){
            if( dojo.hasClass(obj, "addCardSlot"))
            dojo.toggleClass(obj, "addCardSlotOver");
            return true;
        }
        // if moused to child, stop event
        if( dojo.isDescendant(evt.relatedTarget, obj) ){
            dojo.stopEvent(evt);
            return true;
        }      
        return false;
    },
    
    animateCardIn: function(node) {
//		console.log("animateCardIn, node = " + node);
        dojo.animateProperty({
        node: node, duration: 1000,
        properties:{
            top: { start:-25, end:0 }, opacity: { start:0, end:1 }
        },
        easing: dojo.fx.easing.bounceOut
        }).play();
    },

    animateCardInSlow: function(node,duration,start) {
//		console.log("animateCardInSlow, node = " + node + ", duration = " + duration);
        dojo.animateProperty({
        node: node, duration: duration,
        properties:{
            top: { start:start, end:0 }, opacity: { start:0, end:1 }
        },
        easing: dojo.fx.easing.bounceOut
        }).play();
    },
    
    animateCardOut: function(node) {
//		console.log("animateCardOut, node = " + node);
        dojo.animateProperty({
        node: node, duration: 1000,
        properties:{
            top: { start:0, end:-25 }, opacity: { start:1, end:0 }
        },
        onEnd: function(){ 
                node.parentNode.removeChild(node); 
            }
        }).play();
    },

    cardImgOver: function(e){
        if( SJourney.TaskBar.CardTray.Animation.specialEvents(this, e) ) return;

        var animProps = {top: { start:0, end:-15 }, opacity: { start: .65, end: 1 } };
        // if moving from remove to card, after first entering this card area, just do opacity
        if(this.style.position == "absolute"){ animProps = { opacity: { start: .65, end: 1 } }; }

        dojo.animateProperty({
            node: this, duration: 200, properties:animProps,
            beforeBegin: function() {
                this.node.style.position = "absolute";
                this.node.style.cursor = "move";
                dojo.query("span", this.node.parentNode).removeClass("hide");
            } 
        }).play();
    },
    
    cardImgOut: function(e){
        if(SJourney.TaskBar.CardTray.Animation.specialEvents(this, e) ) return;
        // if mouseout from raised card to page content, execute cardDivOut( and switching the context to the div )
        if( !dojo.isDescendant(e.relatedTarget, this.parentNode.parentNode) ){
            dojo.stopEvent(e); 
            SJourney.TaskBar.CardTray.Animation.cardDivOut.apply(this.parentNode, [e]);
            return;
        }
        
        // prevents delegate from causing this to fire when a drag to a card triggers it
        // after dropping the dragged item. because this "moves" the card you are dropping
        // on to, it makes this fire as you are over the card.
        if( !dojo.isDescendant(e.relatedTarget, this.parentNode)){
            dojo.stopEvent(e);
            return;
        }

        dojo.animateProperty({
            node: this, duration: 200,
            properties:{ opacity: { start: 1, end: .65 } }
        }).play();
    },
    
    cardDivOut: function(e){
        //@@ can be called from two contexts. a mouseout from the cardDiv, or from a drop event NOT on the drop Source
        //@@ this means there will be NO event object for the context. See CardTray.init subscriber for this case.
        if(e)
            if(SJourney.TaskBar.CardTray.Animation.specialEvents(this, e) ) return;

        var img = dojo.query("img", this)[0];
        // @@ inside animateProperty, context of 'this' is no longer the div
        var thisDiv = this;
        dojo.animateProperty({
            node: img, duration: 1000,
            properties:{
                top: { start:-15, end:0 }, opacity: { start: .65, end: 1 }
            },
            easing: dojo.fx.easing.bounceOut,
            beforeBegin: function() { dojo.query("span", thisDiv).addClass("hide"); },
            onEnd: function() { this.node.style.position = "static"; }
        }).play();
    }
};

/*** 
ITEM = CardMenu Object
VALUE = Controls the popup menu of cards for the user to choose to add to the CardTray
***/
SJourney.TaskBar.CardMenu = {
    cards : [],
    menu: null,
    swapCard : null,
    
    init: function(){
        this.menu = dojo.query("#addCardMenu ul")[0];
        this.cardMenuLoader(this, this.menu);
        dojo.subscribe("/CardTray/updateSelfRemove", this, this.updateAdd);
        dojo.subscribe("/SaveCompare/saved", this, this.updateRemove);
        dojo.subscribe("/SaveCompare/unsaved", this, this.updateAdd);
        dojo.subscribe("/TaskBar/restoreTray", this, this.updateRestore);
        
        dojo.query("#addCardMenu ul").onclick(
        SJourney.eventDispatcher( 
            {'li': this.updateSelfRemove}
        ));
	
		
        //console.log("CardMenu initialized");
    },
    
    cardMenuLoader: function(menuObj, menuNode){
        var CD = SJourney.Cards.CardData, CARDS = SJourney.Cards;
        // create card and push on to card menu array, sort
        for(var key in CD){        
            menuObj.cards.push( new CARDS.Card(key, CD[key]) );
        }
        menuObj.cards.sort(CARDS.sortCards);
        // now build and insert nodes from the list
        for(var i in menuObj.cards){
            var li = document.createElement("li");
            dojo.addClass(li, menuObj.cards[i].cssClass);
            menuNode.appendChild(li);
        }
    },
    
    getCardByID: function(id){
        for(var i in this.cards)
        if( this.cards[i].pmc === id )
        return this.cards[i];
        return null;
    },

    updateAdd: function(cardObj){
        // store card, sort, prepare node
        console.log("CM: updateAdd");
        this.cards.push( cardObj );
        this.cards.sort(SJourney.Cards.sortCards);          
        var li = document.createElement("li");
        if(!dojo.isIE=="6") {
		    li.setAttribute("title",cardObj.descript);
		}
        dojo.addClass(li, cardObj.cssClass);
        // insert card into menu
        for(var i in this.cards){
            if(this.cards[i].ordinal > cardObj.ordinal){
                var sibling = dojo.query("." + this.cards[i].cssClass, this.menu)[0];
                this.menu.insertBefore(li, sibling);
                break;
            } else {
                this.menu.appendChild(li);
			}
        }
        dojo.publish("/CardMenu/updateAdd", [ cardObj ]);
    },
    
    updateRemove: function(cardObj){
        console.log("CM: updateRemove");
        if(SJourney.TaskBar.CardTray.numCardsCheck()) {
            
            if(!SJourney.TaskBar.CardTray.cardInTrayCheck(cardObj)) {
	            for(var i in this.cards){
	                if( this.cards[i].pmc == cardObj.pmc ){
	                    var child = dojo.query("li." + this.cards[i].cssClass, this.menu)[0];
	                    this.menu.removeChild(child);
	                    cardObj = this.cards.splice(i,1)[0];
	                    break;
	                } 
	            }
	            dojo.publish("/CardMenu/updateRemove", [cardObj]);
            }
			if(SJourney.TaskBar.CardMenu.swapCard!=null) {
			    SJourney.TaskBar.CardMenu.swapCard="";
			}
        } else {
            this.prepareModal(cardObj);
        }
    },
    
    updateSelfRemove: function(e){
        //console.log("updateSelfRemove");
        if(SJourney.TaskBar.CardTray.numCardsCheck) {
            var STCM = SJourney.TaskBar.CardMenu;
            for(var i in STCM.cards){
                if( STCM.cards[i].cssClass == this.className ){
                    STCM.updateRemove(STCM.cards[i]);
                    break;
                }
            }
            SJourney.TaskBar.CardMenu.Animation.hide(e);
            if(dojo.query(".sj_cardNameFlyout")!="") {
                SJourney.TaskBar.CardMenu.Animation.hideNameFlyout();
            }
        } else {}
    },
    
    updateRestore: function(cardsObj){
        for(var i in cardsObj){ this.updateRemove(cardsObj[i]); }
        SJourney.restoreState = false;
    },
    
    prepareModal: function(swapCard) {
        var modalContentDiv = dojo.byId("modal_tooManyCardsError");
        var modalContentParent = dojo.query(".sj_modalWindowBody")[0]; 
        var trayParent = dojo.query("#sj_modalWindowRemoveCards")[0];
        //store reference to content div for passing to Modal functions
        var content = modalContentDiv;
        
        // get card to swap, store it for later use
        this.swapCard = swapCard;
        
        //remove old card content if there is any
        if(trayParent.hasChildNodes()) {
            var trayAsChild = dojo.query("#clonedTray")[0];
            trayParent.removeChild(trayAsChild);
        }

        // create modal tray
        var cloneTray = SJU.createNewElement( {
            element:"div", 
            attribs:[{id: "clonedTray"}]
        });

        // create modal cards and markup
        for(var i=0; i < SJourney.TaskBar.CardTray.cards.length; i++){
            // get card...
            var card = SJourney.TaskBar.CardTray.cards[i];   
            // wrapper holds all the pieces, it gets special id and keys for later use
            var wrapper = SJU.createNewElement( {
                element:"div", 
                attribs:[{"id": "clone_" + card.cssClass},{"key": card.pmc}]
            });
            var cardElement = SJU.createNewElement({
                element: "div",
                attribs:[{"id": "_"+card.cssClass},{"key": card.pmc}]
            });
            //cardElement.setAttribute("class",card.cssClass);
            
            wrapper.className="sj_card_wrapper";
            // the card name blurb
            var cardTxt = SJU.createNewElement( {
                element:"div"
            });
            cardTxt.className="sj_remTxtBox";
            cardTxt.appendChild( document.createTextNode(card.descript) );
            
            // spacer row, works great in FF, IE needs help still...
            var blocker = SJU.createNewElement( { element:"div" } );
            blocker.className="sj_modalblock";
            
            // the checkbox to select a card to remove, uses key as the value
            var chkbox = SJU.createNewElement( {
                element:"input",
                attribs:[{"type": "checkbox", "name": "sj_remCard", "value": i, "id": "sj_remCard"+i}]
            });

			var lbl = SJU.createNewElement( { 
				element:"label",
				attribs:[{"for": "sj_remCard"+i}]
			});
            lbl.appendChild( document.createTextNode(" remove card") );
			
            
            // attach it all... 
            wrapper.appendChild(cardElement);
            dojo.addClass(cardElement, "sj_remImg");
            dojo.addClass(cardElement, card.cssClass);
            wrapper.appendChild(cardTxt);
            wrapper.appendChild(blocker);
            wrapper.appendChild(chkbox);
			wrapper.appendChild(lbl);
            cloneTray.appendChild(wrapper);
            //attach the remove card text node last
        }
        // attach it all... 
        dojo.query("#sj_modalWindowRemoveCards")[0].appendChild(cloneTray);
		// wire up the continue button for action when card limit is exceeded and user makes changes
        // in modal dialog
		var continueEvent = dojo.connect(dojo.byId("sj_modal_continue"), 'onclick', function(e) {
            var chkboxes = dojo.query("#sj_modalRemoveForm")[0].elements;
            var cardObjs = [];
            var callFlag = 0;
            for(var i=0; i < chkboxes.length; i++){
                if(chkboxes[i].checked){
                    cardObjs.push(SJourney.TaskBar.CardTray.cards[ chkboxes[i].value ]);
                    callFlag++;
                }
            }
            if(callFlag>=1) {
                for(var i=0; i < callFlag; i++) {
                    SJourney.TaskBar.CardMenu.updateAdd(cardObjs[i]);
                }
				//add the currently selected card( the one they tried to add after having 5 already )
				swapCardTimer = setTimeout("SJourney.TaskBar.CardMenu.updateRemove(SJourney.TaskBar.CardMenu.swapCard)",1000);
				dojo.disconnect(continueEvent);
                // close too many cards dialog
                SJourney.Modal.hide("modal_tooManyCardsError");
            }
        });
		
        // close too many cards dialog
        dojo.connect(dojo.byId("sj_modal_cancel"), 'onclick', function() {
            SJourney.Modal.hide("modal_tooManyCardsError");
			SJourney.TaskBar.CardMenu.swapCard="";
			if(continueEvent!="") {
			    dojo.disconnect(continueEvent);
			}
        });
        SJourney.Modal.show("modal_tooManyCardsError");
        
    }
};
var SJTCM = SJourney.TaskBar.CardMenu;
/*** 
ITEM = CardMenu Animation Object
VALUE = Controls logic for scrolling/dropping from CardMenu.
***/
SJourney.TaskBar.CardMenu.Animation = {
    sj_scrollTimerDown: null,
    sj_scrollTimerUp: null,
    
    init: function(){
        var cardMenuObj = dojo.query("#addCardMenu");
        var STCA = SJourney.TaskBar.CardMenu.Animation;

        cardMenuObj.onmouseover(function(e) {
            SJourney.eventDispatcher({
                '#addCardDown': STCA.scrollDown,
                '#addCardUp': STCA.scrollUp
            })(e);
        });

        cardMenuObj.onmouseout(function(e){
            if(e.target.id=="addCardDown"){
                e.stopPropagation;
                STCA.scrollStop(e);
            } 
            else if(e.target.id=="addCardUp"){
                e.stopPropagation;
                STCA.scrollStop(e);
            } 
            else if(e.target.id=="addCardMenu" && !dojo.isDescendant(e.relatedTarget, this)){
                STCA.hide(e);
            } 
            else {
                dojo.stopEvent(e);
                return;
            }
        });
        //prepare name flyout handlers
        dojo.query("#addCardMenu").onmouseover(function(e) {
            SJourney.eventDispatcher( 
            { 'li': function(e){ SJourney.TaskBar.CardMenu.Animation.showNameFlyout(e); } }
            )(e);
        });
        dojo.query("#addCardMenu").onmouseout(function(e) {
            SJourney.eventDispatcher( 
            { 'li': function(e){ SJourney.TaskBar.CardMenu.Animation.hideNameFlyout(e); } }
            )(e);
        });
    },

    scrollUp: function(e){
        var listEl=dojo.query("#addCardMenu div#cardScroller")[0];
        if(listEl.scrollTop != 0){
            listEl.scrollTop--;
            this.sj_scrollTimerUp = setTimeout("SJourney.TaskBar.CardMenu.Animation.scrollUp()", 1);
        } 
        else { SJourney.TaskBar.CardMenu.Animation.scrollStop(); }
    },
    
    scrollDown: function(e) {
        var listEl=dojo.query("#addCardMenu div#cardScroller")[0];
        if (dojo.query("div#cardScroller ul")[0].clientHeight != listEl.scrollTop) {
            listEl.scrollTop++;
            this.sj_scrollTimerDown = setTimeout("SJourney.TaskBar.CardMenu.Animation.scrollDown()", 1);
        } 
        else{ SJourney.TaskBar.CardMenu.Animation.scrollStop(); }
    },
    
    scrollStop: function() {
        if(this.sj_scrollTimerUp!=null) {
            clearTimeout(this.sj_scrollTimerUp);
        }
        if(this.sj_scrollTimerDown!=null){
            clearTimeout(this.sj_scrollTimerDown);
        }
    },
    
    show: function(){
        var addCard_xy = dojo.coords(this);
        var cardMenu = dojo.query("#addCardMenu")[0];
        cardMenu.style.left=addCard_xy.x+"px";
        cardMenu.style.height="162px";
        dojo.toggleClass(cardMenu,"menuShow");
    },
    
    hide: function(e){
        if(dojo.isDescendant(e.relatedTarget, this)){ dojo.stopEvent(e); } 
        else { dojo.toggleClass("addCardMenu","menuShow"); }
    },
    
    showNameFlyout: function(e){
        /*if(dojo.query(".sj_cardNameFlyout")!="") {
                    SJourney.TaskBar.CardMenu.Animation.hideNameFlyout();
                }*/
        var STCM = SJourney.TaskBar.CardMenu;
        for(var i in STCM.cards){
            if( STCM.cards[i].cssClass == e.target.className ){
                var p = document.createElement("p");
                dojo.addClass(p,"sj_cardNameFlyout");
                p.innerHTML = STCM.cards[i].descript;
               var appendParent = dojo.query("#taskbar_align")[0];
                var addCardXOffset = dojo.query("#addCardMenu")[0].style.left;
                addCardXOffset=addCardXOffset.replace(/px/,"");
                addCardXOffset=addCardXOffset-170;
                addCardXOffset=addCardXOffset+"px";
                p.style.left=addCardXOffset;
                appendParent.appendChild(p);
                 break;
            }
        }
    },
    
    hideNameFlyout: function(e){
        var flyout = dojo.query(".sj_cardNameFlyout")[0];
        flyout.parentNode.removeChild(flyout);
    }
};

SJourney.TaskBar.RestoreTray = function(){
	var cardTrayIsEmpty = true;
    // restore any cards from prior session
    var storedCards = SJourney.simplePersistence.retrieve("sj_cardsInTray");
	console.log("restore tray!!!!!!!!!!!!");
    if(storedCards) { 
    	if (storedCards.length > 0) { 
			cardTrayIsEmpty = false;
		}
		console.log("PRE GUID LOG");
		//GUID check to keep old cards from persisting
		var GUID = dojo.cookie("blueboxpublic");
		console.log("POST GUID LOG, PRE SJ_GUID LOG");
		var storedGUID = dojo.cookie("sj_guid");
		console.log("before GUID business; GUID: "+GUID+" storedGUID: "+storedGUID);
		if(GUID!="" && storedGUID!="" && GUID!=storedGUID) { console.log("*********** GUIDS DONT MATCH *****");
			cardTrayIsEmpty = true;
			SJourney.simplePersistence.store("sj_cardsInTray","");
			dojo.cookie("sj_guid",GUID,{expires: 7, path : "/"});
		} else {
			console.log("GUIDS MATCH! ::: GUID: "+GUID+" sj_guid: "+storedGUID);
			dojo.cookie("sj_guid",GUID,{expires: 7, path : "/"});
		}
    } else {
		var GUID = dojo.cookie("blueboxpublic");
		dojo.cookie("sj_guid",GUID,{expires: 7, path : "/"});
		console.log("GUIDS STORED! ::: GUID: "+GUID+" sj_guid: "+storedGUID);
    }
    if(cardTrayIsEmpty) {
		//console.log('cardTrayIsEmpty (empty) = ' + cardTrayIsEmpty);
		//do alternate 'start here' layer here via CSS manipulation
		dojo.addClass("savedCards", "noCards");
		dojo.addClass("cardtray", "noCards");
	} else { 
	//	console.log('storedCards.length (1 or more) = ' + storedCards.length);
        SJourney.restoreState = true;
        dojo.publish("/TaskBar/restoreTray", [storedCards]);
    }
};

/*** 
ITEM = ExternalItems Object
VALUE = Controls logic for items that need to interact with, or be aware of, change in the CardTray.
***/
SJourney.TaskBar.SaveCompareTriggers = {
    init: function(){
        // saveCompare delegate
        dojo.query("body").onclick(
        SJourney.eventDispatcher( 
            { ".sj_save_compare" : this.updateSaveCompare }
	        )
		);
        dojo.subscribe("/CardMenu/updateRemove", this, this.updateCardMenuChanged);
        dojo.subscribe("/CardMenu/updateAdd", this, this.updateCardMenuChanged);
    },
    
    updateSaveCompare: function(e){
        var cardObj;
        // if it's in the tray, check tray list
        nodeID = this.id.slice(1, this.id.length);
        if( dojo.hasClass(this, "saveCompare_saved") ){
            cardObj = SJTBCT.getCardByID( nodeID );
            if( cardObj == null ) return;
            SJTCM.updateAdd(cardObj);
        } // or it's in the menu, so check its list
        else{ console.log("cardObj:"+nodeID);
            cardObj = SJTCM.getCardByID( nodeID );
			
            if( cardObj == null ) return;
            SJTCM.updateRemove(cardObj);
        }
    },
    
    updateCardMenuChanged: function(cardObj){
		//when tabs are all on page the IDs on the tab save to compare triggers MUST be changed to classes, and this code
		//must be changed accordingly!!!

        //differing IDs from nav and page save buttons, do everything twice
        var saveCompareItemPage = "p"+cardObj.pmc;
        var saveCompareItemNav = "_"+cardObj.pmc;
		var saveCompareItemNavPA = "a"+cardObj.pmc;
		var saveCompareItemTabs = "q"+cardObj.pmc;
		var saveCompareItemPerkTool = "b"+cardObj.pmc;

        //never know when elements are present so check first
        if(dojo.byId(saveCompareItemPage)) {
            var pageItem = dojo.byId(saveCompareItemPage);
            dojo.toggleClass(pageItem, "saveCompare_saved");
        }
       if(dojo.byId(saveCompareItemNav)) {
            var navItem = dojo.byId(saveCompareItemNav);
            dojo.toggleClass(navItem, "saveCompare_saved");
        }
		if(dojo.byId(saveCompareItemNavPA)) {
            var navPAItem = dojo.byId(saveCompareItemNavPA);
            dojo.toggleClass(navPAItem, "saveCompare_saved");
        }
		if(dojo.byId(saveCompareItemTabs)) { 
            var tabsItem = dojo.byId(saveCompareItemTabs);
            dojo.toggleClass(tabsItem, "saveCompare_saved");
        }
		if(dojo.byId(saveCompareItemPerkTool)) { 
            var perktoolItem = dojo.byId(saveCompareItemPerkTool);
            dojo.toggleClass(perktoolItem, "saveCompare_saved");
        }
    }
};
var SJTBSCT = SJourney.TaskBar.SaveCompareTriggers;

//for communicating with flash pieces like the quiz/hub and spoke
SJourney.TaskBar.Flash = {	
	addCard: function(id) {
		var cardObj = SJourney.TaskBar.CardMenu.getCardByID(id);
		SJTCM.updateRemove(cardObj);
	},
	
	removeCard: function(id) { console.log(id);
		var cardObj = SJourney.TaskBar.CardTray.getCardByID(id);
		console.log("card: "+cardObj);
		SJTCM.updateAdd(cardObj);
	}
};
var SJTBFlash = SJourney.TaskBar.Flash;

SJourney.TaskBar.CompareButton = {
	compareBtnURL: "/getthecard/compare-cards?p=ctray&pmccodes=",
	compareBtnSecureURL: "/secure/compare-cards?p=ctray&pmccodes=",

    // if two or more cards in tray, create query string value of comma-delimited keys to pass to compare page
    init: function(){
        this.buttonEl= dojo.query("#compareButton a")[0];
        this.handleState();
        dojo.subscribe("/CardTray/updateSelfRemove", this, this.handleState);
        dojo.subscribe("/CardMenu/updateRemove", this, this.handleState);
        dojo.subscribe("/CardMenu/updateAdd", this, this.handleState);
        dojo.query("#compareButton a").onclick(function(e) {
            SJourney.TaskBar.CompareButton.cancelCompareLink(e);
        });
    },

    // compare link should only be active if there are two or more cards
    handleState: function() {
        var cNodes = SJourney.TaskBar.CardTray.cards;
        var str = "";
        var button = this.buttonEl;
        var SJTBCB = SJourney.TaskBar.CompareButton;

        if(cNodes.length >= 2){
            for(var i=0,ln=cNodes.length; i < ln; i++){
                str += cNodes[i].pmc + ",";
            }
            str = str.slice(0, str.length -1);
            str = encodeURIComponent(str);
            if(window.location.pathname.match("secure")) {
                button.setAttribute("href", SJTBCB.compareBtnSecureURL + str);
            } else {
                button.setAttribute("href", SJTBCB.compareBtnURL + str);
            }
            dojo.removeClass(button, "disabled");
        }
        else{
            SJourney.TaskBar.CompareButton.buttonEl.setAttribute("href", "");
            dojo.addClass(button, "disabled");
        }
    },
    // cancel compare button default link action if it is in disabled mode
    cancelCompareLink: function(e){ 
        if(SJourney.TaskBar.CardTray.cards.length < 2){
            dojo.stopEvent(e);
        }
    }
};

/*** 
ITEM = Object to handle all Modal operations
***/
SJourney.Modal = {
    width: "0px",
    height: "0px",
    
    init: function() { console.log('modal init');
        //subscriptions, (triggers) ???
		var cancels = dojo.query(".sj_modal_cancel");
		console.log(cancels);
		if(cancels.length>1) {
			cancels.forEach(function(item,index,array) {
				dojo.connect(item,"onclick",function(e) { console.log("click");
					var parentWidgetID = e.target.parentNode.parentNode.parentNode.id;
					SJourney.Modal.hide(parentWidgetID);
				});
			});
		} else if(cancels.length>0) {
			dojo.connect(cancels[0],"onclick",function(e) { console.log("click");
				var parentWidgetID = e.target.parentNode.parentNode.parentNode.id;
				SJourney.Modal.hide(parentWidgetID);
			});
		}
    },
    
    setContent: function(contentReference) {
        var modalContentParent = dojo.query(".sj_modalWindowBody")[0];
        //check for existing content; if there is any, dump it
        if(modalContentParent.hasChildNodes()) {
            var contentChild = modalContentParent.childNodes[0];
            var contentStoreParent = dojo.query("#modalContentPieces")[0];
            
            var removedContent = modalContentParent.removeChild(contentChild);
            contentStoreParent.appendChild(removedContent);
        }
        //grab content piece and append it
        content = contentReference.parentNode.removeChild(contentReference);
        modalContentParent.appendChild(content);
    },
    
    show: function(modalDivName) { console.log("div name: "+modalDivName);
		var modalWinMask = dojo.query('.sj_modalPageMask')[0];
        var maxHeight = document.body.scrollHeight + "px";
        modalWinMask.style.height = maxHeight;
        modalWinMask.style.display = "block";
		
		//hide the taskbar too, zindex won't do it
		var modalWinMaskTaskbar = dojo.query('#taskbar .sj_modalPageMask')[0];
		modalWinMaskTaskbar.style.display="block";
		
		dijit.byId(modalDivName).show();
		if(modalDivName=="modal_tooManyCardsError") {
			//reset overflow to none to prevent 'auto' setting which causes scrollbars
			dojo.query(".dijitDialogPaneContent")[0].style.height="auto";
			dojo.query(".dijitDialogPaneContent")[0].style.width="663px";
		}
    },
    
    hide: function(modalDivName) {
		dijit.byId(modalDivName).hide();
        dojo.query('.sj_modalPageMask')[0].style.display = "none";
		dojo.query('#taskbar .sj_modalPageMask')[0].style.display = "none";
    }
};
var SJM = SJourney.Modal;

//method must be added to omniture object to evaluate ajax calls, i think, to make it self-sufficient
SJourney.Omniture = {
	marketCode: "",
	pageName: "",
	omnCustomArray: [],
	
    init: function() {
		//provide alias
		SJO = SJourney.Omniture;
		
		//get the right map based on our page, if it's not compare page
		var src = (SJINFO.context=="cardmember") ? "sjOmn"+SJU.pageType+"_cm.js" : "sjOmn"+SJU.pageType+".js";
		var map = document.createElement("script");
		map.setAttribute("src",jsContextPath+src);
		dojo.query("head")[0].appendChild(map);

			dojo.connect(document.body,'onclick',function(e){ 
			//below preventDefault for use during configuration only.
			//e.preventDefault(); 
			//console.log(e.target);
			SJourney.Omniture.omniListener(e); 
		});
		
		try { this.pageName=omn_pagename; } catch(e) { console.log("ERROR: couldn't set omniture pagename value!"); }
		this.marketCode = (SJINFO.context=="prospect") ? "US:CCSGApply:" : "US:CCSGApply:CMsinglejourney:";
		
		setTimeout("SJO.attrbAssigner();",2000);
		setTimeout("SJO.customTracking();",2000);
	},
	customTracking: function() {
		//init custom tracking using array built by page-specific js files
		for(i=0;i<SJO.omnCustomArray.length;i++) {
			SJO.omnCustomArray[i]();
		}
	},
	attrbAssigner: function() {
		var globalMap = SJourney.Omniture.globalTrackedItems;
		var pageMap = SJourney.Omniture.pageTrackedItems;
		//iterate through trackedItems, assign attrb
		for(var i in globalMap) {
			var nodeList = dojo.query(i);
			if(nodeList!="" && nodeList.length==1) {
				nodeList[0].setAttribute("omnValue",globalMap[i]);
			} else {
				dojo.forEach(nodeList,function(current,index,array) {
					//console.log("current: "+current);
					current.setAttribute("omnValue",globalMap[i][index]);
				});
			}
		}
		if(SJU.pageType!="compare") { console.log(pageMap);
			for(var i in pageMap) {
				var nodeList = dojo.query(i); console.log(nodeList);
				if(nodeList!="" && nodeList.length==1) {
					nodeList[0].setAttribute("omnValue",pageMap[i]);
				} else {
					dojo.forEach(nodeList,function(current,index,array) {
						console.log("current: "+current);
						current.setAttribute("omnValue",pageMap[i]);
					});
				}
			}
		}
	},
    omniListener: function(e) {
		//console.log("omni item: "+e.target+" id:"+e.target.id);
		//check for attrb
		if(e.target.getAttribute("omnvalue")) {
			omn_rmaction(SJO.marketCode+SJO.pageName,e.target.getAttribute("omnvalue"));
			console.log(SJO.marketCode+SJO.pageName+":"+e.target.getAttribute("omnvalue"));
		}
	},
	//used to add tracking to elements created on the fly. Public method.
	addTracking: function(selector,value,index /* in case of ID-less element that is part of a group of nodes */) {
	
		if(typeof(index)=="undefined") { index = 0; }
		//console.log("selector: "+selector+" value: "+value+" index: "+index);
		dojo.query(selector)[index].setAttribute("omnValue",value);
	}
    
};
var SJO = SJourney.Omniture;
