// Copyright (c) 2006 Spannerworks Ltd. All rights reserved
// aperture.js Ver 0.1.0 2007-01-03
// NOTES: 
// - This file is fully documented and formatted for readability only. 
//   *******************************
///  ***** DO NOT DEPLOY AS-IS *****
//   *******************************
// This file is intended to be run through a Javascript compressor, before deployment, to remove extraneous comments and whitespace 
// and create a much smaller client file. e.g. http://spannerworks.com/compressor
//
// TODO: Remove ap.ti & ApTitle (page title) as it is unused
//

// ------------------------------------------
// Constants - not subject to profile changes
var gApVersion = "0.1.0";                               // Script version
var gApDebug = false;                                   // Show debugging info
var gApCookieName = "apTag";                            // CookieName refers to a first party cookie and should be a persistent not session cookie.
var gApExpire = 3650;                                   // how many days should cookies last (10 years)

// ---------------------------------------------------------------------
// Profile config information (all in one place for ease of maintenance)
var gApProfile = "spannerworkstest";                           // Customer profile key (templated value)
var gApTagGif = "www.sptag.com/aperture.gif";       // Tag server image file to use (templated value)
var gApUrl = true;                                      // Send the source URL?
var gApConv = true;                                     // Record conversions from Meta data?
var gApTitle = true;                                    // Send the page title?
var gApSequence = false;                                // Create sequenced cookies?
var gApCookies = true;                                  // CookieCreate will determine if a first party cookie is created if absent.
var gApCookieDomain = null;                             // If using first party cookies across subdomains, set var gApCookieDomain = ".domain.com";
var gApCookieCheck = true;                              // Explicitly check for cookies?
var gApTagPrefix;

// ********************************************************************************************
// ********************************************************************************************
// Holder for any custom tag information to be passed on to the Aperture tagging system (e.g. PPC parameters).
// Uncomment and change the code below to implement specific pattern matching. 
// *Note: The ppc marker will be filled in by the script generator.
//
// Regular expression help: http://www.zytrax.com/tech/web/regex.htm
//var grep = new RegExp("source=([^&]+)\&keyword=([^&]+)");
//if (grep.test(location.href)) 
//{
//  matches = location.href.match(grep);
//  gApTagPrefix = "ap.cp=" + matches[1] + ",PPC," + matches[2];
//}
// ********************************************************************************************
                       // templated code insertion point
// ********************************************************************************************

// Create a new image object (used to trigger the tag server entry when URL is set)
var ApImage = new Image(1,1);

// ----------------------------------------------------------------
// apTag - Called by end user to generate log record on tag server.
function apTag( prefix )
{
	return apTagServer( apUrl( gApTagPrefix, prefix ));
}

// ----------------------------------------------------------------------------------------------------------------------
// apAddTag() - Creates an additonal tag for extra downloads, events etc. e.g. apAddTag('document.pdf','ap.cv=download').
// 1. apPage - Page name relative to the current folder e.g. "document.pdf"
// 2. apPage - is optional prefix strig to specify additional tag. e.g. "ap.cv=sale,electrical,dvd,39.99".
// Returns the URL requested from tagserver.
// Set protocol and tagserver gif. Add prefix and parameters. Add url with current path. Add title if required.
function apAddTag( apPage, apPage, apPageTitle ) 
{
	if (apIsStringNotEmpty(apPage))
	{
		var tagStr = apPrefixUrl( gApTagGif );
		tagStr = tagStr + "?" + apAddSuffix( apPage, "&" ) + apParameters();
		tagStr = tagStr + "&ap.ul=" + escape(location.href.substring(0, location.href.lastIndexOf("/")+1) + apPage) + "&ap.rf=" + escape(location.href);
		if ( apIsStringNotEmpty(apPageTitle ) && gApTitle)
		{
			tagStr = tagStr + "&ap.ti=" + escape(apPageTitle);
		}
		return apTagServer(tagStr);
	}
	return null;
}

// ---------------------------------------------	
// apUrl - return the tag URL for HTTP or HTTPS.
function apUrl( apTagPrefix, prefix )
{
	var url = "";
	
    // Check for global parameter (comes before prefix), may be null if not setup.
	if (apIsStringNotEmpty( apTagPrefix )) 
	{
	    // Note can be empty string at this point if no matches
		url = apTagPrefix;
	}
	
    // Set prefix if necessary.
	if (apIsStringNotEmpty(prefix))
	{
		url = apAddSuffix( url, "&" ) + prefix;
	} 
    
    // Add profile cookie, cache-busting etcetera parameters.
	url = "?" + apAddSuffix( url, "&" ) + apParameters();
	
    // Protocol is http or https.
	url = apPrefixUrl( gApTagGif + url );
    
    // Add URL parameter if specified in setup options.
	if (gApUrl)
	{
		url = url + "&ap.ul=" + escape(location.href);	
	}
    
    // Add the referrer if specified in setup options.
	url = url + "&ap.rf=" + escape(window.document.referrer);
	
	// Add any meta-tags if specified in setup options.
	if (gApConv)
	{
        // No need for & seperator.
		url = url + apMetaTags();
	}	
	
	// Add the page title if specified in setup options
	if (gApTitle) 
	{
         // Optionally send the title as the last element (it may be truncated).
		url = url + "&ap.ti=" + escape(document.title);
	}
	return url;
}

// ------------------------------------------	
// apTagServer - Request URL from tag server.
function apTagServer( apURLString )
{
	var tagHTML = apURLString;
	
	// Limit to 2048 characters max
	if (tagHTML.length > 2048 && navigator.userAgent.indexOf( 'MSIE' ) >= 0)
	{
		tagHTML = tagHTML.substring( 0, 2040 ) + "&ap.en=1";
	}
	if (document.images)
	{
        // Get image into variable without displaying on form.
        // Make sure image variable is global.
		ApImage.src = tagHTML;
	} 
	else 
	{
        // Alternatively write an image request in HTML to the page.
        // Note that IMG string must be split to prevent browser problems.
		tagHTML = '<IM' + 'G BORDER=\"0\" NAME=\"aptag\" WIDTH=\"1\" HEIGHT=\"1\" SRC=\"' + tagHTML + ' \" >' ;
		document.write( tagHTML );
	}
	// Debug info
	if (gApDebug)
	{
		document.write( "<br/><b>" + tagHTML + "</b>" );
	}
	return tagHTML;
}	

// ------------------------------------------------------
// apCookieAsTag - Returns cookie string value as ap.ck tag
// gApCookies and gApExpire determine whether a cookie is created if absent.
function apCookieAsTag(cookieName)
{
	var cookieString = "";
	
    // System uses third party cookies only.
	if (!apIsStringNotEmpty( cookieName.length ))
	{
		return "";
	}
    
    // Get first party cookie value.
    // Use least specific if there are multiple cookies as path will be /.
	cookieString = apGetCookieValue( cookieName );
	if (isStringLen( cookieString ))
	{
        // Cookie OK so return tag value.
		return "ap.ck=" + cookieString; 
	}
	
	if (gApCookies)
	{
        // Create new cookie with a random cookie value.
		var now = apNow();
		var cookieString = "apTag." + location.href.length + "." + navigator.userAgent.length + "." + now;
		apCreateCookie( cookieName, cookieString, gApExpire, gApCookieDomain );

        // Check that cookie has been created.
		cookieString = apGetCookieValue(cookieName);
		if (apIsString( cookieString ))
		{
			return "ap.ck=" + cookieString + "&ap.cd=" +  now;
		}
//		else
//		{
//            // Cannot create new cookie.
//            // Note that cookie disabled status is set in the apParameters function.
//			return "ap.ck=";
//		}
	}
    // Cookie should be there but is absent and creation not specified.
	return "ap.ck=";
}

// --------------------------------------------------------------------------------------------
// Concatenate all meta tags prefixed with ap. into the form "name1=content1&name2=content2..."
function apMetaTags()
{
    var metaElements = document.all ? document.all.tags('META') : document.getElementsByTagName ? document.getElementsByTagName ('META') : new Array();
    var metaKeywords = "";
    for (var i = 0; i < metaElements.length; i++)
    {
        // if the meta tag name starts with our prefix, add it
        if (metaElements[i].name.indexOf('ap.') == 0)
        {
            metaKeywords = metaKeywords + "&" + metaElements[i].name + "=" + escape(metaElements[i].content);
        }
    }
    return metaKeywords;
}

// ----------------------------------------------------------------------------------------------------------
// apParameters - return parameters for profile tag, cache busting, first party cookie, cookie disabled flag.
function apParameters()
{
    // Profilename + Nowstring
	var tagStr = "ap.pf=" + gApProfile + "&ap.nw="+ apNow();
	// + cookie if present
	if (apIsStringNotEmpty( gApCookieName ))
	{
		tagStr = tagStr + "&" + apCookieAsTag(gApCookieName);
	}			
	// if we want to check cookies and they are disabled, report as "disabled"
	if (gApCookieCheck && !apAreCookiesEnabed()) 
	{
		tagStr = tagStr + "&ap.cs=disabled";
	}	
	// Add a sequential cookie if required
	if (gApSequence)
	{
        // Add a sequence.
		var ApSequence = apGetCookieValue("ApSequence");
		if (apIsStringNotEmpty( ApSequence ))
		{
            // Add 1 and convert back to a string.
			ApSequence = "" + (parseInt(ApSequence)+1);
		}
		else 
		{
		    // Else start at 1
			ApSequence = "1";
		}
		apCreateCookie( "ApSequence", ApSequence, null, gApCookieDomain );
		// return sequence number as a parameter
		tagStr = tagStr + "&ap.sq=" + ApSequence;
	}
	return tagStr;	
}

// ----------------------------------------------------------
// apAreCookiesEnabed - returns false if cookies are disabled.
function apAreCookiesEnabed() 
{
	var enabled = (apIsStringNotEmpty( document.cookie ) ? true : false);
	if ( !enabled && apIsString( document.cookie ))
	{
		document.cookie = "ApCheckCookie=test";
		enabled = (document.cookie.indexOf("ApCheckCookie") >= 0);
	}
	return enabled;	
}

// ---------------------------------------------------------
// Return the last matching cookie value for the given name.
// Note: parameter Cookie name is case-sensitive.
function apGetCookieValue( cookieName ) 
{
    // If the search cookie name is valid...
	if (apIsStringNotEmpty( cookieName ))
	{
		// Surround the cookies string with ";" characters to simplify matching substrings
		var tempCookie = "; " + document.cookie + ";";

		// Surround the cookie string with ";" characters to simply matching substrings
		var startPos = tempCookie.lastIndexOf( "; " + cookieName + "=" );
		if (startPos > -1)
		{
		    // Start after the matching string to get the value
			startPos = startPos + cookieName + 3;
            // Substring out the value up to the next ";"
			return unescape(tempCookie.substring( startPos, tempCookie.indexOf( ";", startPos ) ));
		}
	}
	return "";
}

// Create a cookie to expire after a specified date
function apCreateCookie(name, value, days, domain)
{
    var expires = "";
	if (days)
	{
		date.setTime( apNow()+(days*24*60*60*1000) );
		expires = "; expires="+date.toGMTString();
	}
	document.cookie = name + "=" + escape(value) + expires + "; path=/";
}

// -----------------------
// Is the object a string?
function apIsString(a)
{
    return typeof a == 'string';
}

// -------------------------------------------------------
// Is this a string, with a length (at least 1 character)?
function apIsStringNotEmpty(a)
{
    return (apIsString( a ) && a.length > 0)
}

// ------------------------
// Is the object a boolean?
function apIsBoolean(a) 
{
    return typeof a == 'boolean';
}

// --------------------------------------
// Add a suffix if the string is non-null
function apAddSuffix( s, c )
{
    return apIsStringNotEmpty(s) ? s + c : "";
}

// -------------------------------------------------------------------
// Add a http:// or https:// prefix to a url based on current protocol
function apPrefixUrl( u )
{
    return "http" + (window.location.protocol.indexOf('https:') == 0 ? 's' : '') + "://" + u;
}

// -------------------------------------------------------------------------------------------------------
// return "apNow" as an integer value representing the number of milliseconds since midnight January 1, 1970
function apNow()
{
	var d = new Date();
	return d.getTime()
}

// End of file aperture.js

