// $Id: engine.js,v 1.1 2006/10/10 15:19:16 elena Exp $
// ####################### CONSTANTS & GLOBAL VARS #############################
var crmZipCode = 'ZipCode';			// Cookie name for zipcode
var crmLeadId = 'LeadId';			// Cookie name for Lead Id
var crmReferralSite="Site";			// Cookie and query param name for referral site
var crmReferralArea="Area";			// Cookie and query param name for referral area
var crmReferralCreative="Creative";	// Cookie and query param name for referral creative
var crmUnknownSite = "UnknownSite";	// query param value for no referral site
var crmUnknownArea = "UnknownArea";	// query param value for no referral area
var crmUnknownCreative = "UnknownCreative";	// query param value for no referral creative
var crmVidCookieName = 'visitorID';	// Cookie name for visitor id
var crmPageLocale;					// pagelocale value from script tag attribute
var crmPageSite;					// pagesite value from script tag attribute
var crmPageId						// pageid value from the script tag attribute
var crmDebugIsOn;					// crmdebug state from the query string
var crmDebugCookie='crmDebugState';	// cookie name to track crmDebug state
var crmCondCallList=[];				// used to track conditional calls in the crmCondCall function
var crmUrl = location.pathname+location.search; // stores the the current page path + any querystring info
var crmJsURLPrefix;					// will store the full URL of engine.js (url up to, but not including the engine.js filename)
var crmTagBucketId="pageTags";		// id value of the div in which to place dynamic tags (ie images)
var crmCollageHost="collage.designory.com"	// Collage hostname/ip (used for preview trapping)
var crmCollageContribPage="as_contrib_edit.jsp" // Collage contribution page (used for preview trapping)
var crmOffer;						// Will contain an instance of CrmOfferClass on init
var crmCheckOfferFreq=250;			// frequency at which crmGetOffers checks the crmOffer obj (in ms)
var crmCheckOfferTimeOut=5000;		// how long to wait befor crmGetOffers gives up on crmOffer obj and shows defaults (in ms)
var crmPFALinkId='rtoPfaLink';		// id value for pfa link
var crmSMB1HeaderId='rtoSMB1Head';	// id value for smb1 link
var crmSMB1LinkId='rtoSMB1Link';	// id value for smb1 link
var crmSMB2LinkId='rtoSMB2Link';	// id value for smb2 link
var crmBuildNum;					// Will hold the build number for which the current page tag file was created
var crmBuildDate;					// Will hold the date (date object) for which the current page tag file was created

// ############################### CLASSES #####################################


// ###	CRM Offer Class
//		Holds dynamic offer information which is returned from providers
function CrmOfferClass () {
	var pfaSwf='', pfaSwfDefault='', pfaImg='', pfaImgDefault='', pfaText='', pfaTextDefault='', pfaLink='', pfaLinkDefault='', isLoaded=false;
	
	this.getPfaSwf = function () { return pfaSwf; }
	this.getPfaSwfDefault = function () { return pfaSwfDefault; }
	this.getPfaImg = function () { return pfaImg; }
	this.getPfaImgDefault = function () { return pfaImgDefault; }
	this.getPfaText = function () { return pfaText; }
	this.getPfaTextDefault = function () { return pfaTextDefault; }
	this.getPfaLink = function () { return pfaLink; }
	this.getPfaLinkDefault = function () { return pfaLinkDefault; }
	this.getLoaded = function () { return isLoaded; }
	
	this.setPfaSwf = function (value) { pfaSwf = value; }
	this.setPfaSwfDefault = function (value) { pfaSwfDefault = value; }
	this.setPfaImg = function (value) { pfaImg = value; }
	this.setPfaImgDefault = function (value) { pfaImgDefault = value; }
	this.setPfaText = function (value) { pfaText = value; }
	this.setPfaTextDefault = function (value) { pfaTextDefault = value; }
	this.setPfaLink = function (value) { pfaLink = value; }
	this.setPfaLinkDefault = function (value) { pfaLinkDefault = value; }
	this.setLoaded = function (value) { isLoaded = value; }
}

// ###	CRM Site Class
//		Associates nissan or infiniti with provider specific strings
//		Example: var localEnvObj = new CrmEnvironmentClass({
//					nissan:		'NissanUSA_',
//					infiniti:	'Infiniti_'});
function CrmSiteClass ( locSiteObj ) {
	var siteLocalObj = locSiteObj;
	this.isNissan = (crmPageSite=='nissan') ? true : false;
	this.isInfiniti = !this.isNissan;
	this.getSite = function () {
		if (crmPageSite=='nissan') return siteLocalObj.nissan;
		if (crmPageSite=='infiniti') return siteLocalObj.infiniti;
		return null;
	}
	this.getSiteName = function () { return crmPageSite }
}

// ###	CRM Environment Class
//		Associates dev, qa, stage & prod with provider specific host and path names
//		Protocol should NOT be provided as it derived from the current page location
//		Example: var localEnvObj = new CrmEnvironmentClass({
//					dev:	'some.dev.domain.com/path/to/file.html',
//					qa:		'some.qa.domain.com/path/to/file.html',
//					stage:	'some.stage.domain.com/path/to/file.html',
//					prod:	'some.prod.domain.com/path/to/file.html'});
function CrmEnvironmentClass ( locEnvObj ) {
    var envHostName = location.hostname.toLowerCase();
	var envPort = location.port;
	var envLocalEnvObj = locEnvObj;
	var envProtocol = location.protocol + '//';
	this.getProtocol = function () { return envProtocol; }
	this.getEnv = function () {
		if (envPort == 9080 || envPort == 8080 || envPort == 9000 || envHostName.indexOf("collage.") > -1)
														return envLocalEnvObj.dev;
		if (envHostName.indexOf("www.qa.") > -1)		return envLocalEnvObj.qa;
		if (envHostName.indexOf("stage.") > -1)			return envLocalEnvObj.stage;
		if (envHostName.indexOf(".nissanusa.com") > -1 || envHostName.indexOf(".infiniti.com") > -1)	
														return envLocalEnvObj.prod;
		return envLocalEnvObj.prod;
	}
}

// ###	CRM Language Local Class
//		Associates en (english) & es (spanish) with provider specific strings
//		Example: var locLocalObj = new CrmLocalClass ({
//					es:		'parameter_string_for_spanish',
//					en:		'parameter_string_for_english'});
function CrmLocaleClass ( localObj ) {
	var locLocalObj = localObj;
	this.getLocale = function () {
		if (crmPageLocale=='en') return locLocalObj.en;
		if (crmPageLocale=='es') return locLocalObj.es;
		return null;
	}
}

// ########################## GENERAL FUNCTIONS ################################

// ###	Debugging alert box
function crmDebug ( msgObj ) {
	if ( !crmDebugIsOn ) return;
	var buildInfo = "BUILD: Not specified in page tag file\n\n";
	if (typeof crmBuildDate != 'undefined ' && typeof crmBuildDate != 'undefined')
		buildInfo = "BUILD: " + crmBuildNum + " (" + crmBuildDate.toLocaleString() + ")\n\n";
	var msgHeader = "___CRM DEBUG________________________________\n\n";
	if (typeof msgObj == 'function') { //assumes a crmEvent function object
		var funcName = "crmevent";
		var funcLine = msgObj.toString().substring(0,(msgObj.toString().indexOf('{')+1));
		var funcNameIndex = funcLine.toLowerCase().indexOf(funcName.toLowerCase());
		var funcOpenParensIndex = funcLine.indexOf('(');
		var funcCloseParensIndex = funcLine.indexOf(')');
		var eventID = funcLine.substring( (funcNameIndex + funcName.length),funcOpenParensIndex );
		var argsNameList = funcLine.substring(funcOpenParensIndex+1,funcCloseParensIndex).split(',');
		var argsDisplayText ='';
		for (n=0; n<argsNameList.length; n++)
			if (argsNameList[n].length > 0)
				argsDisplayText += (typeof msgObj.arguments[n] != 'undefined' ) ? argsNameList[n]+': '+msgObj.arguments[n]+'\n' : argsNameList[n]+': [no value passed in]\n';
		if ( !confirm( msgHeader + 'EVENT ID: ' + eventID + ' ................................. PAGE ID: '+crmPageId+'\n' + buildInfo + argsDisplayText ) )
			if( !confirm(msgHeader + msgObj,'Visitor ID: '+crmGetVID()) )
				prompt(msgHeader + 'Visitor ID:',crmGetVID());
	} else { // assumes a string
		if ( !confirm(msgHeader + msgObj) )
			prompt(msgHeader + 'Visitor ID:',crmGetVID());
	}
}

// ###	CRM cookie related functions
function crmSetCookie(name, value, expires, path, domain, secure) {
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}
function crmGetCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}
function crmDeleteCookie(name, path, domain) {
  if (crmGetCookie(name)) {
    document.cookie = name + "=" +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    "; expires=Thu, 01-Jan-70 00:00:01 GMT";
  }
}
function crmMakeExpDate(days, hours, minutes) {
    var expDate = new Date( );
    if (typeof days == "number" && typeof hours == "number" &&
        typeof hours == "number") {
        expDate.setDate(expDate.getDate( ) + parseInt(days));
        expDate.setHours(expDate.getHours( ) + parseInt(hours));
        expDate.setMinutes(expDate.getMinutes( ) + parseInt(minutes));
		return expDate;
    }
}// END CRM Cookie functions

// ###	Returns the string value of the param from the search/query string (location.search)
//		Returns empty string if null if no value is found
function crmGetQueryParam(paramName) {
	var qString = location.search.substring(1);
	if (qString.indexOf(paramName) == -1) return '';
	var pValueStart = qString.indexOf(paramName) + paramName.length + 1;
	var pValueEnd = qString.indexOf('&', pValueStart);
	if ( pValueEnd==-1 ) pValueEnd = qString.length;
	return unescape( qString.substring( pValueStart,pValueEnd ) );
}

// ###	Returns an array of name/value params from the query string (location.search)
//		Array is bothed named and index based. So values can be pulled by:
//			queryArray['paramName']
//		and
//			queryArray[n].name, queryArray[n].value 
function crmGetQueryStringArray () {
	var qArray = new Array();
	var qString = location.search.substring(1);
	var nameValues = qString.split('&');
	for (n=0; n<nameValues.length; n++) {
		nameValue = nameValues[n].split('=');
		qArray[ unescape(nameValue[0]) ] = unescape(nameValue[1]);
		qArray[n] = { name:unescape(nameValue[0]), value:unescape(nameValue[1])};
	}
	return qArray;
}

// ###	Dynamic HTML tag creation function
//		tagName:			type of tag to create
//		tagInsertPoint:		tag name to insert this tag inside of (ie html, head, body).
//							Will always insert new tag as the last item within the
//							Insert Point container. OR a tag element object can be
//							supplied (ie getElementById value can be passed in)
//		further arguments:	This function can be overloaded with further arguments.
//							They represent the attributes of the tag and should be
//							passed in as objects:
//							crmCreateTag( 'img', 'body', {attrName: 'attribute name',attrValue: 'attribute value'}, ... , ...);
function crmCreateTag ( tagName, tagInsertPoint ) {
	try {
		insertElm = (typeof tagInsertPoint == 'string') ? document.getElementsByTagName( tagInsertPoint ).item(0) : tagInsertPoint;
		attrObjs = crmCreateTag.arguments;
		newElm = document.createElement( tagName.toLowerCase() );
		for( n=2; n < attrObjs.length; n++ )
			newElm.setAttribute( attrObjs[n].attrName.toLowerCase(), attrObjs[n].attrValue );
		insertElm.appendChild( newElm );
		return true;
	} catch (err) {
		crmDebug('crmCreateTag failed with:\n\n' + err);
		return false;
	}
}

// ###	CRM Conditional Call
//		key:						A unique value that associates together all the calls to this function so that it can determine if its the first call or not
//		initialValue: 				The value to be returned on the first call
//		subsequentValue (optional): The value to be returned on all subsequent calls 
//									Will return an empty string if no value is provided
function crmCondCall (key, initialValue, subsequentValue) {
	if(crmCondCallList[key]) {
		return (typeof subsequentValue=='undefined') ? '' : subsequentValue;
	} else {
		crmCondCallList[key]=true;
		return initialValue
	}
}

// ###	Generates new random visitorIDs
//		calls: crmSha1Hash
function crmMakeNewVID() {
	var seed = navigator.userAgent;
	if (typeof screenX != 'undefined')
		seed += (screenX/screenY).toString();
	else if (typeof screenLeft != 'undefined')
		seed += (screenLeft/screenTop).toString();
	if (typeof document.body.clientHeight != 'undefined')
		seed += (document.body.clientHeight/document.body.clientWidth).toString();
	seed += (new Date()).getTime().toString();
	seed += Math.random().toString();
	substrIndex = Math.floor(Math.random()*21);
	newVid = crmSha1Hash(seed).substr(substrIndex,20);
	finalVid = '';
	for (n=0; n<newVid.length; n++)
		finalVid += (Math.floor(Math.random()*2)) ? newVid.charAt(n).toUpperCase() : newVid.charAt(n);
	return finalVid;
}

// ###	Gets new VID and sets cookie
//		uses: crmVidCookieName
//		calls: crmGetCookie, crmMakeNewVID, crmDeleteCookie, crmSetCookie, crmMakeExpDate
function crmGetVID() {
	var vid = crmGetCookie(crmVidCookieName);
	if (vid==null) vid = crmMakeNewVID();
	var hostName;
	var arrHostName=document.location.hostname.split(".");	
	if (arrHostName[arrHostName.length-1] == "com" || arrHostName[arrHostName.length-1] == "nna")
        hostName="."+arrHostName[arrHostName.length-2]+"."+arrHostName[arrHostName.length-1];
    else
		hostName=document.location.hostname;
	crmDeleteCookie(crmVidCookieName,"/",hostName);
	crmSetCookie( crmVidCookieName, vid, crmMakeExpDate(365,0,0), "/", hostName);
	return vid;
}

// ###	Sets Referral Cookies (session) if they are found in the query string
function crmSetReferralCookies () {
	var hostName;
	var arrHostName=document.location.hostname.split(".");	
	if (arrHostName[arrHostName.length-1] == "com" || arrHostName[arrHostName.length-1] == "nna")
        hostName="."+arrHostName[arrHostName.length-2]+"."+arrHostName[arrHostName.length-1];
    else
		hostName=document.location.hostname;
	var queryList = crmGetQueryStringArray();
	for(n=0; n<queryList.length; n++) {
		if ( queryList[n].name.toLowerCase() == crmReferralSite.toLowerCase() ) {
			crmDeleteCookie(crmReferralSite, '/', hostName);
			crmSetCookie(crmReferralSite, queryList[n].value, '', '/', hostName);
		} else if ( queryList[n].name.toLowerCase() == crmReferralArea.toLowerCase() ) {
			crmDeleteCookie(crmReferralArea, '/', hostName);
			crmSetCookie(crmReferralArea, queryList[n].value, '', '/', hostName);
		} else if ( queryList[n].name.toLowerCase() == crmReferralCreative.toLowerCase() ) {
			crmDeleteCookie(crmReferralCreative, '/', hostName);
			crmSetCookie(crmReferralCreative, queryList[n].value, '', '/', hostName);
		}
	}
}

// ###	Checks query string and cookie info to see how crmDebugIsOn should be set
function crmSetDebug() {
	if ( location.search.toLowerCase().indexOf("crmdebug=on") != -1 ) {
		crmDeleteCookie(crmDebugCookie,'/',location.hostname);
		crmSetCookie(crmDebugCookie,1,'','/',location.hostname);
		crmDebugIsOn=true;
	} else if ( location.search.toLowerCase().indexOf("crmdebug=off") != -1 ) {
		crmDeleteCookie(crmDebugCookie,'/',location.hostname);
		crmDebugIsOn=false;
	} else {
		if ( crmGetCookie(crmDebugCookie)==1 )
			crmDebugIsOn=true;
		else
			crmDebugIsOn=false;
	}
}

// ###	Checks to see if the page is loaded in collage contribution
//		uses: crmCollageHost, crmCollageContribPage
function crmInContribMode() {
	if ( location.hostname.indexOf(crmCollageHost) != -1 && location.pathname.indexOf(crmCollageContribPage) != -1 )
		return true;
	return false;
}

// ###	Returns a named array of offer values. Will wait until crmOffer is loaded 
//		and return the results. If crmOffer dosent return within a given amount
//		of time, function will timeout and return defaults
//		uses: crmOffer
function crmGetOffers(callBackFunc,callBackStartTime) {
	//if this is the first time called, time stamp this
	callBackStartTime = (typeof callBackStartTime == 'undefined') ? (new Date()).getTime() : callBackStartTime;

	//setup restults var in case we have results to return
	var result = [];
	
	// Check to see if offers have loaded
	if ( crmOffer.getLoaded() ) {
		//got offers back, return the values and fire the callback
		result['pfaSwf'] = crmOffer.getPfaSwf();
		result['pfaText'] = crmOffer.getPfaText();
		result['pfaImg'] = crmOffer.getPfaImg();
		result['pfaLink'] = crmOffer.getPfaLink();
		eval(callBackFunc+'(result)');
	} else {
		//check to see if we still have time to try again
		if ( ((new Date()).getTime() - callBackStartTime) < crmCheckOfferTimeOut ) {
			//still have time, try again
			setTimeout('crmGetOffers(\'' + callBackFunc + '\','+callBackStartTime+')',crmCheckOfferFreq);
		} else {
			//out of time, return default values and fire the callback;
			result['pfaSwf'] = crmOffer.getPfaSwfDefault();
			result['pfaText'] = crmOffer.getPfaTextDefault();
			result['pfaImg'] = crmOffer.getPfaImgDefault();
			result['pfaLink'] = crmOffer.getPfaLinkDefault();
			eval(callBackFunc+'(result)');
		}
	}
}

// ###	Updates an RTO link by changing the link url and swapping the img source
//		Optionally an image source for the rto header can be passed. If its passed
//		and the header id exists in the page, it will be swapped as well
//		Assumes the following HTML structure for links: <a href="" id='[linkId]'><img .../></a>
//		Assumes the following HTML structure for header: <div id="[crmSMB1HeaderId]"><img .../></div>
function crmUpdateRtoLink(linkId, linkUrl, imgSrc, imgHeadSrc) {
	var linkElm = $(linkId);
	if ( linkElm ) {
		linkElm.setAttribute('href',linkUrl,0);
		linkElm.getElementsByTagName('img').item(0).src = imgSrc;
	}
	if ( imgHeadSrc && $(crmSMB1HeaderId) )
		$(crmSMB1HeaderId).getElementsByTagName('img').item(0).src = imgHeadSrc;
}

// ###	Checks to see if the value is null, undefined or empty string. If any of
//		these are true, it returns the safe value. Otherwise passes the value
//		back.
function crmGetSafeValue(initValue, safeValue) {
	if (typeof initValue == 'undefined' || initValue == null || initValue == '')
		return safeValue;
	return initValue;
}

// ###	Sets the the global vars crmBuildNum and crmBuildDate with provided values
function crmBuildInfo (buildNum, buildTime) {
	crmBuildNum = buildNum;
	crmBuildDate = new Date(buildTime);	
}

// ###	SHA1 hashing functions
function crmSha1Hash(msg) {
    var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
    msg += String.fromCharCode(0x80);
    var l = Math.ceil(msg.length/4) + 2;  
    var N = Math.ceil(l/16);
    var M = new Array(N);
    for (var i=0; i<N; i++) {
        M[i] = new Array(16);
        for (var j=0; j<16; j++) {
            M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) | 
                      (msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3));
        }
    }
    M[N-1][14] = ((msg.length-1) >>> 30) * 8;
    M[N-1][15] = ((msg.length-1)*8) & 0xffffffff;
    var H0 = 0x67452301;
    var H1 = 0xefcdab89;
    var H2 = 0x98badcfe;
    var H3 = 0x10325476;
    var H4 = 0xc3d2e1f0;
    var W = new Array(80); var a, b, c, d, e;
    for (var i=0; i<N; i++) {
        for (var t=0;  t<16; t++) W[t] = M[i][t];
        for (var t=16; t<80; t++) W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
        a = H0; b = H1; c = H2; d = H3; e = H4;
        for (var t=0; t<80; t++) {
            var s = Math.floor(t/20);
            var T = (ROTL(a,5) + f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff;
            e = d;
            d = c;
            c = ROTL(b, 30);
            b = a;
            a = T;
        }
        H0 = (H0+a) & 0xffffffff;
        H1 = (H1+b) & 0xffffffff; 
        H2 = (H2+c) & 0xffffffff; 
        H3 = (H3+d) & 0xffffffff; 
        H4 = (H4+e) & 0xffffffff;
    }
    return H0.toHexStr() + H1.toHexStr() + H2.toHexStr() + H3.toHexStr() + H4.toHexStr();
}
function f(s, x, y, z) {
    switch (s) {
    case 0: return (x & y) ^ (~x & z);
    case 1: return x ^ y ^ z;
    case 2: return (x & y) ^ (x & z) ^ (y & z);
    case 3: return x ^ y ^ z;
    }
}
function ROTL(x, n) {
    return (x<<n) | (x>>>(32-n));
}
Number.prototype.toHexStr = function() {
    var s="", v;
    for (var i=7; i>=0; i--) { v = (this>>>(i*4)) & 0xf; s += v.toString(16); }
    return s;
}// END SHA1

// ############################## INITIALIZE ###################################
// ###	Validate script tag attributes. Check that the crmEngine
if	(	$('crmEngine') &&									// ensure that the crmEngine ID exists
		$('crmEngine').tagName.toLowerCase()=='script' && 	// ensure that crmEngine ID is assigned to a SCRIPT tag
		$('crmEngine').getAttribute('pageid') &&			// ensures that the pageid attribute is set
		$('crmEngine').getAttribute('pagelocale') &&		// ensures that the pagelocal attribute is set
		( $('crmEngine').getAttribute('pagelocale')=='es' || $('crmEngine').getAttribute('pagelocale')=='en' ) &&
															// ensures that the pagelocal attribute is set to either en or es
		$('crmEngine').getAttribute('pagesite') &&			// ensures that the pagesite attribute is set
		( $('crmEngine').getAttribute('pagesite')=='nissan' || $('crmEngine').getAttribute('pagesite')=='infiniti' )
															// ensures that the pagesite attribute is set to either nissan or infiniti
	) {
	
	// Check crmDebug settings and set accordingly
	crmSetDebug();
	
	// Set global vars from tag attributes
	crmPageLocale = $('crmEngine').getAttribute('pagelocale');	// en, es
	crmPageSite = $('crmEngine').getAttribute('pagesite');		// nissan, infiniti
	crmPageId = $('crmEngine').getAttribute('pageid');
	
	// Setup base crmEvent# functions which will be redefined by tagging file
	for (n = 1; n <=50; n++) eval('crmEvent'+n+'= function(){ crmDebug("Event '+n+' Failed.\\n\\nThere is either no crmEvent'+n+' function in the '+crmPageId+'.js tagging file, \\nor this tagging file failed to load."); }');
	
	// verify that we are not loading in a collage contribution window
	if ( !crmInContribMode() ) {

		//Create our offer object to hold real time offer info
		crmOffer = new CrmOfferClass();
		
		// Check for any referral params
		crmSetReferralCookies();
		
		// Determine URL prefix from current script
		crmJsURLPrefix =  $('crmEngine').src.substring( 0,$('crmEngine').src.indexOf('/engine.js')+1 ); // the '/' in '/engine.js' seems to be required for collage preview to work
		
		// Include provider specific js files
		document.write('\n<scr'+'ipt src="' + crmJsURLPrefix +	'providers/atlas.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');
		document.write('<scr'+'ipt src="' + crmJsURLPrefix +	'providers/eloyalty.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');
		document.write('<scr'+'ipt src="' + crmJsURLPrefix +	'providers/omniture.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');
		document.write('<scr'+'ipt src="' + crmJsURLPrefix +	'providers/legacy.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');
		document.write('<scr'+'ipt src="' + crmJsURLPrefix +	'providers/factortg.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');
	
		// Include page specific tagging file ('page_tags\/' seems to be required for to make collage preview work)
		document.write('<scr'+'ipt src="' + crmJsURLPrefix + 'page_tags\/' + crmPageId + '.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');
		
	} else { crmDebug('Loaded in Collage contribution window. Tagging has been disabled.'); }
	
} else { // Create crmEngine failure debug message
	crmErrorMsg = "crmEngine FAILED\n";
	if ( !$('crmEngine') )
		crmErrorMsg += '"crmEngine" ID not found';
	else if ( $('crmEngine').tagName.toLowerCase() != 'script' )
		crmErrorMsg += '"crmEngine" ID not assigned to SCRIPT tag';
	else if ( !$('crmEngine').getAttribute('pageid') )
		crmErrorMsg += '"pageid" attribute not found in the crmEngine SCRIPT tag';
	else if ( !$('crmEngine').getAttribute('pagesite') )
		crmErrorMsg += '"pagesite" attribute not found in the crmEngine SCRIPT tag';
	else if ( $('crmEngine').getAttribute('pagesite')!='nissan' && $('crmEngine').getAttribute('pagesite')!='infiniti' )
		crmErrorMsg += '"pagesite" attribute must be set to either "nissan" or "infiniti" in the crmEngine SCRIPT tag';
	else if ( !$('crmEngine').getAttribute('pagelocale') )
		crmErrorMsg += '"pagelocale" attribute not found in the crmEngine SCRIPT tag';
	else if ( $('crmEngine').getAttribute('pagelocale')!='es' && $('crmEngine').getAttribute('pagelocale')!='en' )
		crmErrorMsg += '"pagelocale" attribute must be set to either "en" or "es" in the crmEngine SCRIPT tag';
	else
		crmErrorMsg += 'unkown error with the CRM Engine script tag structure';
	crmDebug(crmErrorMsg);
}

