/*! Echospin API Loader 2.0
   Copyright (c) 2011 Echospin LLC (echospin.com)
*/

function importIFrameXHR(jQueryLocal) {
	/**
	 * windowName transport plugin 1.0.0 for jQuery
	 *
	 * Thanks to Kris Zyp <http://www.sitepen.com/blog/2008/07/22/windowname-transport/>
	 * for the original idea and some code. Original BSD license below.
	 *
	 * Licensed under GPLv3: http://www.gnu.org/licenses/gpl-3.0.txt
	 * @author Marko Mrdjenovic <jquery@friedcellcollective.net>
	 *
	**/
	/*
	 Copyright (c) 2004-2008, The Dojo Foundation
	 All Rights Reserved.
	
	 Licensed under the Academic Free License version 2.1 or above OR the
	 modified BSD license. For more information on Dojo licensing, see:
	
	 http://dojotoolkit.org/license
	*/
	(function ($) {
		var origAjax = $.ajax, idx = 0, doc = document,
			rurl = /^(\w+:)?\/\/([^\/?#]+)/,
			xhr_wnJSON = function (s) {
				return function () {
					var url = '',
						type = (s.type || '').toUpperCase(),
						frameName = '',
						defaultName = 'jQuery.windowName.transport.frame',
						frame = null, form = null, cleantmr = null,
						u = {};
					function cleanup() {
						try {
							clearTimeout(cleantmr);
						} catch(e) {}
						try {
							delete window.jQueryWindowName[frameName];
						} catch (er) {
							window.jQueryWindowName[frameName] = function () {};
						}
						setTimeout(function () {
							try {
								$(frame).remove();
								$(form).remove();
								doc = null;
								CollectGarbage();
							} catch(e) {}
						}, 100);
					}
					function setData() {
						try {
							var data = frame.contentWindow.name;
							if (typeof data === 'string') {
								if (data === defaultName) {
									u.status = 501;
									u.statusText = 'Not Implemented';
								} else {
									u.status = 200;
									u.statusText = 'OK';
									u.responseText = data;
								}
								u.readyState = 4; // we are done now
								u.onreadystatechange();
								cleanup();
							}
						} catch (er) {}
					}
					function queryToObject(q) {
						var r = {},
							d = decodeURIComponent;
						$.each(q.split("&"), function (k, v) {
							if (v.length) {
								var parts = v.split('='),
									n = d(parts.shift()),
									curr = r[n];
								v = d(parts.join('='));
								if (typeof curr === 'undefined') {
									r[n] = v;
								} else {
									if (curr.constructor === Array) {
										r[n].push(v);
									} else {
										r[n] = [curr].concat(v);
									}
								}
							}
						});
						return r;
					}
					u = {
						abort: function () {
							cleanup();
						},
						getAllResponseHeaders: function () {
							return '';
						},
						getResponseHeader: function (key) {
							return '';
						},
						open: function (m, u) {
							url = u;
							this.readyState = 1;
							this.onreadystatechange();
						},
						send: function (data) {
							data = data || '';
							if (data.indexOf('windowname=') < 0) { // tell the server we want windowname transport
								data += (data === ''? '' : '&') + 'windowname=' + (s.windowname || 'true');
							}
							// prepare frame
							frameName = "jQueryWindowName" + ('' + Math.random()).substr(2, 8);
							window.jQueryWindowName = window.jQueryWindowName || {};
							window.jQueryWindowName[frameName] = function () {};
							var fmethod = null, faction = null, ftarget = null, fsubmit = null,
								local = window.location.href.substr(0, window.location.href.indexOf('/', 8)),
								locallist = ['/robots.txt', '/crossdomain.xml'];
							//= frame.onload
							window.jQueryWindowName[frameName] = function (interval) {
								//alert('onload: ' + u.readyState);
								function get_local(next) {
									var file = '';
									if (next) {
										idx += 1;
									}
									file = s.localfile? s.localfile : locallist[idx]? local + locallist[idx] : null;
									if (!file) {
										file = window.location.href;
									}
									return file;
								}
								function is_local() {
									var c = false;
									try {
										c = !!frame.contentWindow.location.href;
										// try to get location - if we can we're still local and have to wait some more...
									} catch (er) {
										// if we're at foreign location we're sure we can proceed
									}
									return c;
								}
								try {
									if (frame.contentWindow.location.href === 'about:blank') {
										return;
									}
								} catch (er) {}
								if (u.readyState === 3) {
									if (is_local()) {
										//alert('local');
										setData();
										if (u.status === 200) {
											$.ajaxSettings.wnJSONsupported[s.url] = true;
										}
									} else { // if not local try other local
										frame.contentWindow.location = get_local(true);
									}
								}
								if (u.readyState === 2 && (s.windowname || !is_local())) {
									u.readyState = 3;
									u.onreadystatechange();
									try {
										frame.contentWindow.location = get_local();
									} catch (e) {
										//alert(e.message);
									}
								}
							};
							if ($.browser.msie) {
								try {
									doc = null; //new ActiveXObject("htmlfile");
								} catch(e) {}
								try {
									if (doc &&
											typeof doc === "object") {
								    doc.open();
								    doc.write('<html><body><iframe name="' + frameName + '" onload="jQueryWindowName[\'' + frameName + '\']()" src="javascript:false"></iframe></body></html>');
								    doc.close();
								    frame = doc.getElementsByName(frameName)[0];
										frame.onload = window.jQueryWindowName[frameName];
								    //setInterval(function() {}, 10000);
									} else {
										doc = document;
										frame = doc.createElement('<iframe name="' + frameName + '" onload="jQueryWindowName[\'' + frameName + '\']()" src="javascript:false">');
										$('body', doc)[0].appendChild(frame);
										frame.onload = window.jQueryWindowName[frameName];
									}
								} catch (er) {
									alert(er.message);
								}
							}
							if (!frame) {
								frame = doc.createElement('iframe');
							}
							frame.style.display = 'none';
							cleantmr = setTimeout(function () { // stop after 2 mins
								cleanup();
							}, 120000);
							frame.name = frameName;
							frame.id = frameName;
							if (!frame.parentNode) {
								$('body', doc)[0].appendChild(frame);
							}
							if (type === 'GET') {
								frame.contentWindow.location.href = url + (url.indexOf('?') >= 0? '&' : '?') + data;
							} else {
								// prepare form
								try {
									form = doc.createElement('form');
									$('body', doc)[0].appendChild(form);
								} catch(e) {
									alert(e.message);
								}
								form.style.display = 'none';
								// make references to the proper stuff
								fmethod = form.method;
								faction = form.action;
								ftarget = form.target;
								fsubmit = form.submit;
								form.method = 'POST';
								form.action = url;
								form.target = frameName;
								$.each(queryToObject(data.replace(/\+/g, '%20')), function (k, v) {
									function setVal(k, v) {
										var input = doc.createElement("input");
										input.type = 'hidden';
										input.name = k;
										input.value = v;
										form.appendChild(input);
									}
									if (v.constuctor === Array) {
										$.each(v, function (i, v) {
											setVal(k, v);
										});
									} else {
										setVal(k, v);
									}
								});
								try {
									fmethod = form.method = 'POST';
									faction = form.action = url;
									ftarget = form.target = frameName;
								} catch (er2) {}
								if (navigator.userAgent.toLowerCase().match(/opera/i)) frame.contentWindow.location = 'about:blank'; // opera likes this
								try {
									fsubmit();
								} catch (er3) {
									fsubmit.call(form);
								}
							}
							this.readyState = 2;
							this.onreadystatechange();
							if (frame.contentWindow) {
								frame.contentWindow.name = defaultName;
							}
						},
						setRequestHeader: function (key, value) {},
						onreadystatechange: function () {},
						readyState: 0,
						responseText: '',
						responseXML: null,
						status: null,
						statusText: null
					};
					return u;
				};
			},
			xhr_CORS = false ? // window.XDomainRequest ? use XDomainRequest if available (ie) or default XMLHttpRequest
				function () {
					var xhr = new window.XDomainRequest();
					// need to fake stuff that XDomainRequest doesn't provide (http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx)
					xhr.onreadystatechange = function () {};
					xhr.setRequestHeader = function (key, value) {};
					xhr.getAllResponseHeaders = function () {
						return {'content-type': xhr.contentType};
					};
					xhr.getResponseHeader = function (key) {
						if (key === 'content-type') {
							return this.contentType;
						}
					};
					xhr.onload = function () {
						$.extend(xhr, {readyState: 4, status: 200, statusText: 'OK'});
						xhr.onreadystatechange.call(xhr, {});
					};
					xhr.onprogress = function () {
						$.extend(xhr, {readyState: 3, status: 200, statusText: 'OK'});
						xhr.onreadystatechange.call(xhr, {});
					};
					xhr.onerror = function (ev) {
						$.extend(xhr, {readyState: 4, status: 0, statusText: ''});
						xhr.onreadystatechange.call(xhr, {});
					};
					return xhr;
				} : 
				$.ajaxSettings.xhr;
		$.ajaxSettings.wnJSONsupported = {};
		$.ajaxSettings.CORSsupported = {};
		/*
		try {
			$.support.CORS = !!window.XDomainRequest || (function () {
				var xhr = $.ajaxSettings.xhr();
				xhr.open('GET', 'http://domain.fake/', true);
				xhr.send(); // this will throw an error on browers that don't support Allow-Origin on XMLHttpRequest
				xhr.abort();
				return true;
			}());
		} catch (er) {
			$.support.CORS = false;
		}
		*/
		$.extend({
			ajax: function (s) {
				var parts = rurl.exec(s.url || ''),
					remote = parts && (parts[1] && parts[1] !== window.location.protocol || parts[2] !== window.location.host),
					type = (s.type || '').toUpperCase(),
					origSuccess = s.success || function () {};
				if (s.windowname) {
					s.xhr = xhr_wnJSON(s);
				} else if (type === 'POST' && remote && (($.browser.msie && $.param(s.data).length < 2000 - s.url.length) || (!$.browser.msie && $.param(s.data).length < 4100 - s.url.length))) {
					s.type = "GET";
					s.dataType = "jsonp";
					s.jsonp = "jsoncallback";
					return origAjax.call(this, s);
				} else if (type === 'POST' && remote) {
					if (!$.browser.msie && $.support.cors && $.ajaxSettings.CORSsupported[s.url] !== false) {
						s.xhr = xhr_CORS;
						s.success = function (data, status, xhr) {
							if (xhr.status === 0) {
								status = 'error';
								$.ajaxSettings.CORSsupported[s.url] = false;
								if (this.error) {
									this.error.call(this, s, xhr, status, {name: 'Unsupported', message: 'CORS not supported.'});
								}
							} else {
								$.ajaxSettings.CORSsupported[s.url] = true;
								return origSuccess.apply(this, arguments);
							}
						};
					} else if ($.ajaxSettings.wnJSONsupported[s.url] !== false) {
						s.xhr = xhr_wnJSON(s);
					}
				}
				return origAjax.call(this, s);
			}
		});
	})(jQueryLocal);
}
	
var echospin = new function() {
	this.version = "2.0";
	this.initialized = true;
	this.loadArgs = {};
	//this.xhrCORS = false;
	this.$ = window.jQuery;
	
	this.visitor = {
		domainScope: "global",
		sessionTimeout: 1800,
		cookiePath: "/"
	};
	
	this.tracking = {
		webTrends: false,
		googleAnalytics: true,
		siteCatalyst: false
	};

	var	m_sAPIKey = '90b5ae9320f04e8699ae1fe493291740',
			m_sAPIMode = 'dev',
			m_sRootDomain = (location.protocol == "file:" ? "http:" : location.protocol) + "//api.echospin.com/",
			m_sAjaxURL = m_sRootDomain + (m_sAPIMode ? m_sAPIMode + "/" : "") + m_sAPIKey + "/ajax/",
			
			m_arrAPIList = [
				"preview", 
				"cart", 
				"checkout", 
				"orders", 
				"promo"
			],
																	
			m_objEchospin = this,
			m_objConsole = window.console,
			m_objDocument = document,
			m_objLocation = m_objDocument.location,
			
			m_jQuery = m_objEchospin.$,
			$ = m_jQuery,
			
			m_sCookieDomain = m_objLocation.hostname.toLowerCase(),
			
			m_bDisabled,
			//m_dtInitialized = new Date(),
			
			m_objVisitor = {
				id: (Math.round(Math.random() * 2147483647) * (Math.random() * 2147483647)).toString(),
				created: null
			},
			m_nVisitorTimeout = 631138519,
			
			m_objSession = {
				id: (Math.round(Math.random() * 2147483647) * (Math.random() * 2147483647)).toString(),
				created: null,
				pageCount: 1,
				landing: "",
				referrer: ""
			},

			m_sJQueryURL = "ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js",
			//m_sGoogleAjaxURL = "www.google.com/jsapi",

			m_objCompatibleAgents = {
				opera: 9,
				msie: 6,
				applewebkit: 522.11,
				firefox: 2
			},

			m_bBrowserIsCompatible,
			m_bLoadJQuery = true,
			m_bJQueryLoaded,
			m_bXHRLoaded,
			
			m_i,
			
			m_sErrorAjax = "Ajax Error",
			//m_sErrorAjaxProcessing = "Ajax Processing Error",

			m_sConstantJSPath = "/js/",
			m_sConstantEchospin = "echospin",
			
			m_sConstantUndefined = "undefined",
			m_sConstantFunction = "function",
			m_sConstantNumber = "number",
			m_sConstantString = "string",
			m_sConstantObject = "object",
			
			m_sConstantUTMForm = "utmform",
			m_sConstantUTMTrans = "utmtrans",
			
			m_sConstantForwardSlash = "/",
			m_sConstantDot = ".",
			m_sConstantPipe = m_sConstantPipe,
			
			ajaxResponseCode = {
				processingError: -100,
				success: 0
			},

			API = function(sName) {
				this.load = function(args) {
					return loadAPI(sName, args);
				};
			};
			
	this.trace = function() {
		if (!m_sAPIMode ||
				!arguments.length) return;
				
		try {
			if (m_objConsole) {
				var args = (new Array()).slice.call(arguments, 0);
				
				if (typeof args[0] == m_sConstantString &&
						args[0].indexOf(m_sConstantEchospin) != 0) args[0] = m_sConstantEchospin + m_sConstantDot + args[0];
					
				if (m_objConsole.firebug) m_objConsole.log(m_sConstantEchospin + " trace", args); 
				else m_objConsole.log(m_sConstantEchospin + " trace " + args.join(", ")); 
			}
		} catch(e) {}
	};
	
	this.log = function() {
		if (!m_sAPIMode ||
				!arguments.length) return;
				
		try {
			if (m_objConsole) {
				var args = (new Array()).slice.call(arguments, 0);

				if (m_objConsole.firebug) m_objConsole.log(m_sConstantEchospin + " log", args);
				else m_objConsole.log(m_sConstantEchospin + " log " + args.join(", "));
			}
		} catch(e) {}
	};

	this.log("API Loader", this.version, m_sAPIKey);
	
	this.itemTypes = new function() {
		var m_objTypes = {
			typeCD: {
				value: 0,
				label: "CD"
			},
			typeMP3s: {
				value: 1,
				label: "MP3s"
			},
			typeMP3: {
				value: 2,
				label: "MP3"
			},
			typeMP4: {
				value: 3,
				label: "MP4"
			},
			typeDVD: {
				value: 4,
				label: "DVD"
			},
			typeRingtone: {
				value: 5,
				label: "Ringtone"
			},
			typeApparel: {
				value: 6,
				label: "Apparel"
			},
			typeVinyl: {
				value: 7,
				label: "Vinyl"
			},
			typeMerchandise: {
				value: 8,
				label: "Merchandise"
			},
			typeTicket: {
				value: 9,
				label: "Ticket"
			},
			typeBundle: {
				value: 10,
				label: "Bundle"
			},
			typeDigitalBooklet: {
				value: 11,
				label: "Digital Booklet"
			},
			typeSubscription: {
				value: 12,
				label: "Subscription"
			},
			typeUserPlaylist: {
				value: 13,
				label: "User Playlist"
			},
			typeFLACs: {
				value: 14,
				label: "FLACs"
			},
			typeFLAC: {
				value: 15,
				label: "FLAC"
			}
		};
		
		this.labels = {};
		this.types = {};
			
		for (m_i in m_objTypes) {
			this[m_i] = m_objTypes[m_i].value;
			this.labels[m_i] = m_objTypes[m_i].label;
			this.labels[m_objTypes[m_i].value] = m_objTypes[m_i].label;
			this.types[m_objTypes[m_i].value] = m_i.toString();
		}
	};
	
	this.getSession = function() {
		return [
			encodeURIComponent(m_sCookieDomain),
			m_objVisitor.id,
			m_objVisitor.created.getTime() / 1000,
			m_objSession.id,
			m_objSession.pageCount,
			m_objSession.landing.substring(0, 55),
			encodeURIComponent(m_objLocation.href),
			encodeURIComponent("REDACTED"), //m_objSession.referrer.substring(0, 50)
			(new Date()).getTimezoneOffset() / 60 * -1,
			m_objSession.created.getTime() / 1000,
			(new Date()).getTime() / 1000
		].join("&");
	};
	
	this.trim = function(str) {
		str = str.replace(/^\s+/, '');
		
		for (var i = str.length - 1; i >= 0; i--)
			if (/\S/.test(str.charAt(i))) {
				str = str.substring(0, i + 1);
				break;
			}

		return str;
	};

	this.lengthOf = function(objArray) {
		var nLength = 0,
				i;
		
		for (i in objArray) nLength++;
		
		return nLength;
	};

	this.lzwEncode = function (string) {
		return string;
		if (!string) return string;
			
    var dict = {},
    		data = (string + "").split(""),
    		out = [],
    		currChar,
    		phrase = data[0],
    		code = 256,
    		i;
    		
    for (i = 1; i < data.length; i++) {
      currChar = data[i];
      
      if (dict[phrase + currChar] != null) phrase += currChar;
      else {
        out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));
        dict[phrase + currChar] = code;
        code++;
        phrase = currChar;
      }
    }
    out.push(phrase.length > 1 ? dict[phrase] : phrase.charCodeAt(0));

    for (i = 0; i < out.length; i++) 
    	out[i] = String.fromCharCode(out[i]);

    return out.join("");
	};

	this.lzwDecode = function(string) {
		return string;
		if (!string) return string;

    var dict = {},
    		data = (string + "").split(""),
    		currChar = data[0],
    		oldPhrase = currChar,
    		out = [currChar],
    		code = 256,
    		phrase,
    		i,
    		currCode;
    		
    for (i = 1; i < data.length; i++) {
      currCode = data[i].charCodeAt(0);
      if (currCode < 256) phrase = data[i];
      else phrase = dict[currCode] ? dict[currCode] : (oldPhrase + currChar);

      out.push(phrase);
      currChar = phrase.charAt(0);
      dict[code] = oldPhrase + currChar;
      code++;
      oldPhrase = phrase;
    }
    
    return out.join("");
	};

	this.cookie = new function() {
		var sVisitorCookie = m_sConstantEchospin + ".visitor",
				sInstanceCookie = m_sConstantEchospin + ".instance",
				sSessionCookie = m_sConstantEchospin + ".session",
				sCartCookie = m_sConstantEchospin + ".cart",
				sFormCookie = m_sConstantEchospin + ".form",
				sTestCookie = m_sConstantEchospin + ".test",
				sDomainHash,
				arrVisitor = [],
				arrSession = [],
				bCookiesAllowed = false;
										
		this.initialize = function() {
			if (m_objLocation.hostname.toLowerCase() == "127.0.0.1" ||
					m_objLocation.hostname.toLowerCase() == "localhost") m_sCookieDomain = m_objLocation.hostname.toLowerCase();
			else if (m_objEchospin.visitor.domainScope.toLowerCase() == "global") {
				m_sCookieDomain = m_objLocation.hostname.toLowerCase();
				while (m_sCookieDomain.indexOf(m_sConstantDot) != m_sCookieDomain.lastIndexOf(m_sConstantDot)) m_sCookieDomain = m_sCookieDomain.substring(m_sCookieDomain.indexOf(m_sConstantDot) + 1);
				m_sCookieDomain = m_sConstantDot + m_sCookieDomain;
			} else if (m_objEchospin.visitor.domainScope &&
								 m_objEchospin.visitor.domainScope.toLowerCase() != "local") m_sCookieDomain = m_objEchospin.visitor.domainScope.toLowerCase();
				
			sDomainHash = hash(m_sCookieDomain);
			sVisitorCookie += sDomainHash;
			sInstanceCookie += sDomainHash;
			sSessionCookie += sDomainHash;
			sCartCookie += sDomainHash;
			
			if (!navigator.userAgent.match(/MSIE/i)) {
				setCookie(sTestCookie, sTestCookie);
				if (getCookie(sTestCookie) === sTestCookie) {
					bCookiesAllowed = true;
					clearCookie(sTestCookie);
				}
			}
						
			m_objEchospin.trace(m_sConstantEchospin + ".cookie.initialize", {
				permitted: bCookiesAllowed,
				domain: m_sCookieDomain
			});
		}; 
		
		this.load = function() {
			m_objEchospin.trace(m_sConstantEchospin + ".cookie.load");

			m_objVisitor.created = new Date();
			m_objSession.created = new Date();

			arrVisitor = getCookie(sVisitorCookie).split("&");
		  if (arrVisitor.length == 2) {
		  	m_objVisitor.id = arrVisitor[0];
		  	m_objVisitor.created.setTime(parseInt(arrVisitor[1]) * 1000);
			} else {
				arrVisitor[0] = m_objVisitor.id;
				arrVisitor[1] = Date.parse(m_objVisitor.created) / 1000;
			}
	  	setCookie(sVisitorCookie, arrVisitor.join("&"), m_nVisitorTimeout);
			m_objEchospin.log(sVisitorCookie, m_objVisitor.id, m_objVisitor.created);
	
	  	if (getCookie(sInstanceCookie).length > 0) arrSession = getCookie(sSessionCookie).split("&");
	  	else setCookie(sInstanceCookie, Date.parse(m_objSession.created) / 1000);
	  		
		  if (arrSession.length == 5) {
		  	m_objSession.id = arrSession[0];
		  	m_objSession.created.setTime(parseInt(arrSession[1]) * 1000);
		  	m_objSession.pageCount = arrSession[2] = parseInt(arrSession[2]) + 1;
		  	m_objSession.landing = decodeURIComponent(arrSession[3]);
		  	m_objSession.referrer = decodeURIComponent(arrSession[4]);	  	
			} else {
				arrSession[0] = m_objSession.id;
				arrSession[1] = Date.parse(m_objSession.created) / 1000;
				arrSession[2] = m_objSession.pageCount;
				arrSession[3] = m_objSession.landing = encodeURIComponent(m_objLocation.href);
				arrSession[4] = m_objSession.referrer = encodeURIComponent(m_objDocument.referrer);
			}
	  	setCookie(sSessionCookie, arrSession.join("&"), m_objEchospin.visitor.sessionTimeout);
			m_objEchospin.log(sSessionCookie, m_objSession.id, m_objSession.created, m_objSession.pageCount, m_objSession.landing, m_objSession.referrer);
			
			m_bCookieLoaded = true;
		};

		this.getCart = function(param1, param2) {
			if (bCookiesAllowed) return getCookie(sCartCookie);
			/*
			else return sCartCookie;
			*/
			else return ajaxProcess("get", {
				name: sCartCookie
			}, arguments.callee.caller, param1, param2);
		};
	
		this.setCart = function(value) {
			if (bCookiesAllowed) setCookie(sCartCookie, value);
			else ajaxProcess("set", {
				name: sCartCookie,
				value: value
			});
		};
	
		this.clearCart = function() {
			if (bCookiesAllowed) clearCookie(sCartCookie);
			else ajaxProcess("clear", {
				name: sCartCookie
			});
		};
		
		this.getForm = function(param1, param2) {
			if (bCookiesAllowed) return getCookie(sFormCookie);
			else return ajaxProcess("get", {
				name: sFormCookie
			}, arguments.callee.caller, param1, param2);
		};
		
		this.setForm = function(value) {
			if (bCookiesAllowed) setCookie(sFormCookie, value);
			else ajaxProcess("set", {
				name: sFormCookie,
				value: value
			});
		};
		
		this.clearForm = function() {
			if (bCookiesAllowed) clearCookie(sFormCookie);
			else ajaxProcess("clear", {
				name: sFormCookie
			});
		};
		
		function ajaxProcess(sCommand, objData, fCalback, vParam1, vParam2) {
			if (!sCommand ||
					!objData) return;

			m_objEchospin.trace(m_sConstantEchospin + ".cookie.onAjaxProcess", {
				command: sCommand,
				data: objData
			});

			$.ajax({
				//transport: "xhr",
				data: objData,
				success: function(data) {
					if (!data) m_objEchospin.trace(m_sConstantEchospin + ".cookie.onAjaxError", {
							error: m_sErrorAjax
						});
					else if (data.resultcode <= ajaxResponseCode.processingError) m_objEchospin.trace(m_sConstantEchospin + ".cookie.onAjaxError", {
							error: m_sErrorAjax
						});
					else if (data.value !== undefined) {
						m_objEchospin.trace(m_sConstantEchospin + ".cookie.onAjaxSuccess", {
							value: data.value
						});
						setTimeout(function() {
							if (vParam2 !== undefined) fCalback(vParam1, vParam2, data.value);
							else if (vParam1 !== undefined) fCalback(vParam1, data.value);
							else fCalback(data.value);
						}, 10);
					} else m_objEchospin.trace(m_sConstantEchospin + ".cookie.onAjaxSuccess");
				},
				type: "POST",
				dataType: "json",
				//jsonp: "jsoncallback",
				url: m_sAjaxURL + "cookie/" + sCommand + "/",
				cache: false,
				timeout: 30000,
				error: function(XMLHttpRequest, textStatus, errorThrown) {
					m_objEchospin.trace(m_sConstantEchospin + ".cookie.onAjaxError", {
						error: m_sErrorAjax,
						details: textStatus + " [" + errorThrown + "]"
					});
				}
			});
			
			if (sCommand === "get") return "ASYNC";
		}
			
		function getCookie(name) {
			if (!name) return;
			
			return m_objEchospin.lzwDecode(cookie(name)) || "";
		}

		function setCookie(name, value, expires, path) {
			if (!name) return;
			
			if (!value) clearCookie(name);
			else cookie(name, m_objEchospin.lzwEncode(value), {
				expires: expires,
				path: m_objEchospin.visitor.cookiePath.toLowerCase(),
				domain: m_sCookieDomain, 
				secure: false
			});
		}
		
		function clearCookie(name) {
			if (!name) return;
			
			cookie(name, "", {
				expires: -1, 
				path: m_objEchospin.visitor.cookiePath.toLowerCase(), 
				domain: m_sCookieDomain, 
				secure: false
			});
		}

		function cookie(name, value, options) {
			var expires,
					date,
					path,
					domain,
					secure,
					cookieValue,
					cookies,
					cookie;
					
	    if (typeof value != m_sConstantUndefined) { // name and value given, set cookie
	      options = options || {};
	      expires = "";
	      if (options.expires && (typeof options.expires == m_sConstantNumber || options.expires.toGMTString)) {
	        if (typeof options.expires == m_sConstantNumber) {
	          date = new Date();
	          date.setTime(date.getTime() + (options.expires * 1000)); // * 24 * 60 * 60 * 1000
	        } else date = options.expires;
	        expires = "; expires=" + date.toGMTString(); // use expires attribute, max-age is not supported by IE
	      }
	      path = options.path ? "; path=" + options.path : "";
	      domain = options.domain ? "; domain=" + options.domain : "";
	      secure = options.secure ? "; secure" : "";
	      m_objDocument.cookie = [name, "=", encodeURIComponent(value), expires, path, domain, secure].join("");
	    } else { // only name given, get cookie
	      cookieValue = null;
	      if (m_objDocument.cookie && m_objDocument.cookie != "") {
	        cookies = m_objDocument.cookie.split(";");
	        for (m_i = 0; m_i < cookies.length; m_i++) {
	          cookie = m_objEchospin.trim(cookies[m_i]);
	          // Does this cookie string begin with the name we want?
	          if (cookie.substring(0, name.length + 1) == (name + "=")) {
	            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
	            break;
	          }
	        }
	      }
	      return cookieValue;
	    }
		}

		function hash(sString) {
		  if (!sString ||
		  		sString == "") return "";
		
		  var h = 0,
		  		g = 0,
		  		i,
		  		c;
		
		  for (i = sString.length-1; i >= 0; i--) {
		    c = parseInt(sString.charCodeAt(i));
		    h = ((h << 6) & 0xfffffff) + c + (c << 14);
		    if ((g = h & 0xfe00000) != 0) h = (h ^ (g >> 21));
		  }
		  
		  return m_sConstantDot + h;
		}
	};

	this.track = function() {
		if ((!this.tracking.webTrands &&
				 !this.tracking.googleAnalytics &&
				 !this.tracking.siteCatalyst) ||
				!arguments.length) return;

		var args,
				tmp,
				sBaseUrl = ((m_objLocation.pathname.substring(m_objLocation.pathname.length - 1) != m_sConstantForwardSlash) ? m_objLocation.pathname + m_sConstantForwardSlash : m_objLocation.pathname).toLowerCase();

		try {
			if (this.tracking.webTrends &&
					typeof dcsMultiTrack == m_sConstantFunction) {
				args = (new Array()).slice.call(arguments, 0);
				this.log("Tracking WebTrends", args);
				
				if (typeof args[0] == m_sConstantString) {
					args[0] = sBaseUrl + m_sConstantEchospin + args[0];
					args[0] = encodeURIComponent(args[0]);
					if (typeof args[1] == m_sConstantString) args[1] = m_objDocument.title + " [" + args[1] + "]";
					else args[1] = m_objDocument.title;
					args[1] = encodeURIComponent(args[1]);
				}
				
				if (typeof args[2] == m_sConstantObject) {
					/*
					WT.si_n="Shoppingcart";
					WT.si_x="4";
					WT.tx_it="hh:mm:ss";
					WT.tx_id="mm/dd/yy";
					
					WT.pn_fa="Desktop and PC Workstation;Be Seen On The Road";
					WT.pn_gr="3M Select;3M Select";
					WT.pn_sc="3M Precise™ Mouse Mats;null";
					*/
					tmp = new Array(5);
					for (m_i = 0; m_i < args[2].items.length; m_i++) {
						if (tmp[0]) tmp[0] += ";"
						else tmp[0] = "";
						tmp[0] += args[2].items[m_i].id;

						if (tmp[1]) tmp[1] += ";"
						else tmp[1] = "";
						tmp[1] += encodeURIComponent(args[2].items[m_i].artist + " - " + args[2].items[m_i].title);

						if (tmp[2]) tmp[2] += ";"
						else tmp[2] = "";
						tmp[2] += args[2].items[m_i].category;

						if (tmp[3]) tmp[3] += ";"
						else tmp[3] = "";
						tmp[3] += args[2].items[m_i].price;

						if (tmp[4]) tmp[4] += ";"
						else tmp[4] = "";
						tmp[4] += args[2].items[m_i].quantity;
					}
									
					this.log("dcsMultiTrack()", "DCS.dcsuri=" + args[0], "WT.ti=" + args[1], "WT.tx_i=" + args[2].orderId, "WT.tx_cartid=" + m_objSession.id, "WT.tx_e=p", "WT.pn_sku=" + tmp[0], "WT.pn=" + tmp[1], "WT.pc=" + tmp[2], "WT.tx_s=" + tmp[3], "WT.tx_u=" + tmp[4]);
					dcsMultiTrack("DCS.dcsuri", args[0], "WT.ti", args[1], "WT.tx_i", args[2].orderId, "WT.tx_cartid", m_objSession.id, "WT.tx_e", "p", "WT.pn_sku", tmp[0], "WT.pn", tmp[1], "WT.pc", tmp[2], "WT.tx_s", tmp[3], "WT.tx_u", tmp[4]);
				} else if (typeof args[0] == m_sConstantString) {
					this.log("dcsMultiTrack()", "DCS.dcsuri=" + args[0], "WT.ti=" + args[1]);
					dcsMultiTrack("DCS.dcsuri", args[0], "WT.ti", args[1]);
				}				
			}
		} catch(e) {}
		
		try {
			if (this.tracking.googleAnalytics &&
					typeof urchinTracker == m_sConstantFunction) {
				this.log("Tracking Google Analytics (urchin.js)", args);
				args = (new Array()).slice.call(arguments, 0);
				
				if (typeof args[0] == m_sConstantString) {
					args[0] = sBaseUrl + m_sConstantEchospin + args[0];
					if (typeof args[1] == m_sConstantString) {
						tmp = m_objDocument.title;
						args[1] = tmp + " [" + args[1] + "]";
						m_objDocument.title = args[1];
					}
					this.log("urchinTracker()", args[0], args[1]);
					urchinTracker(args[0]);
					if (tmp) m_objDocument.title = tmp;
				}
				
				if (typeof args[2] == m_sConstantObject) {
					$("body").append(this.ml(["form", { "id": m_sConstantUTMForm, "name": m_sConstantUTMForm, "style": "display: none;" }]).append(this.ml(["textarea", { "id": m_sConstantUTMTrans, "name": m_sConstantUTMTrans }])));
					this.log("UTM:T", args[2].orderId, args[2].affiliation, args[2].total, args[2].tax, args[2].shipping, args[2].city, args[2].region, args[2].country);
					tmp = " UTM:T|" & args[2].orderId + m_sConstantPipe + args[2].affiliation + m_sConstantPipe + args[2].total + m_sConstantPipe + args[2].tax + m_sConstantPipe + args[2].shipping + m_sConstantPipe + args[2].city + m_sConstantPipe + args[2].region + m_sConstantPipe + args[2].country + " \n";
					
					for (m_i = 0; m_i < args[2].items.length; m_i++) {
						this.log("UTM:I", args[2].orderId, args[2].items[m_i].id, args[2].items[m_i].artist + " - " + args[2].items[m_i].title, args[2].items[m_i].category, args[2].items[m_i].price, args[2].items[m_i].quantity);
						tmp += " UTM:I|" + args[2].orderId + m_sConstantPipe + args[2].items[m_i].id + m_sConstantPipe + args[2].items[m_i].artist + " - " + args[2].items[m_i].title + m_sConstantPipe + args[2].items[m_i].category + m_sConstantPipe + args[2].items[m_i].price + m_sConstantPipe + args[2].items[m_i].quantity + " \n";
					}
					$("#utmtrans").val(tmp);
					
					this.log("__utmSetTrans()");
					__utmSetTrans();
				}
			}
		} catch(e) {}

		try {
			if (this.tracking.googleAnalytics &&
					typeof pageTracker == m_sConstantObject) {
				args = (new Array()).slice.call(arguments, 0);
				this.log("Tracking Google Analytics (Traditional ga.js)", args);
				
				if (typeof args[0] == m_sConstantString) {
					args[0] = sBaseUrl + m_sConstantEchospin + args[0];
					if (typeof args[1] == m_sConstantString) {
						tmp = m_objDocument.title;
						args[1] = tmp + " [" + args[1] + "]";
						m_objDocument.title = args[1];
					}
					this.log("_trackPageview()", args[0], args[1]);
					pageTracker._trackPageview(args[0]);
					if (tmp) m_objDocument.title = tmp;
				}
				
				if (typeof args[2] == m_sConstantObject) {
					this.log("_addTrans()", args[2].orderId, args[2].affiliation, args[2].total, args[2].tax, args[2].shipping, args[2].city, args[2].region, args[2].country);
					pageTracker._addTrans(args[2].orderId, args[2].affiliation, args[2].total, args[2].tax, args[2].shipping, args[2].city, args[2].region, args[2].country);
					
					for (m_i = 0; m_i < args[2].items.length; m_i++) {
						this.log("_addItem()", args[2].orderId, args[2].items[m_i].id, args[2].items[m_i].artist + " - " + args[2].items[m_i].title, args[2].items[m_i].category, args[2].items[m_i].price, args[2].items[m_i].quantity);
						pageTracker._addItem(args[2].orderId, args[2].items[m_i].id, args[2].items[m_i].artist + " - " + args[2].items[m_i].title, args[2].items[m_i].category, args[2].items[m_i].price, args[2].items[m_i].quantity);
					}
						
					this.log("_trackTrans()");
					pageTracker._trackTrans();
				}
			} else if (this.tracking.googleAnalytics &&
					typeof _gaq.push == m_sConstantFunction) {
				args = (new Array()).slice.call(arguments, 0);
				this.log("Tracking Google Analytics (Async ga.js)", args);
				
				if (typeof args[0] == m_sConstantString) {
					args[0] = sBaseUrl + m_sConstantEchospin + args[0];
					if (typeof args[1] == m_sConstantString) {
						tmp = m_objDocument.title;
						args[1] = tmp + " [" + args[1] + "]";
						m_objDocument.title = args[1];
					}
					this.log("_gaq.push([\"_trackPageview\"])", args[0], args[1]);
					_gaq.push(["_trackPageview", args[0]]);
					if (tmp) m_objDocument.title = tmp;
				}
				
				if (typeof args[2] == m_sConstantObject) {
					this.log("_gaq.push([\"_addTrans\"])", args[2].orderId, args[2].affiliation, args[2].total, args[2].tax, args[2].shipping, args[2].city, args[2].region, args[2].country);
					_gaq.push(["_addTrans", args[2].orderId, args[2].affiliation, args[2].total, args[2].tax, args[2].shipping, args[2].city, args[2].region, args[2].country]);
					
					for (m_i = 0; m_i < args[2].items.length; m_i++) {
						this.log("_gaq.push([\"_addItem\"])", args[2].orderId, args[2].items[m_i].id, args[2].items[m_i].artist + " - " + args[2].items[m_i].title, args[2].items[m_i].category, args[2].items[m_i].price, args[2].items[m_i].quantity);
						_gaq.push(["_addItem", args[2].orderId, args[2].items[m_i].id, args[2].items[m_i].artist + " - " + args[2].items[m_i].title, args[2].items[m_i].category, args[2].items[m_i].price, args[2].items[m_i].quantity]);
					}
						
					this.log("_gaq.push([\"_trackTrans\"])");
					_gaq.push(["_trackTrans"]);
				}
			}
		} catch(e) {}
	};
	
	this.browserIsCompatible = function() {
		if (m_bBrowserIsCompatible) return true;
		else if (m_bBrowserIsCompatible === false) return false;
			
		var sAgent = navigator.userAgent,
				i;
		
		this.cookie.initialize();

		this.trace(m_sConstantEchospin + ".browserIsCompatible", {
			userAgent: sAgent
		});

		for (i in m_objCompatibleAgents)
			if (sAgent.toLowerCase().indexOf(i) != -1) {
				if (RegExp(i + "[ \/]?([0-9]+(\.[0-9]+)?)").exec(sAgent.toLowerCase()) != null) {
					if (parseFloat(RegExp.$1) >= m_objCompatibleAgents[i]) return m_bBrowserIsCompatible = true;
				}
			}
		
		return m_bBrowserIsCompatible = false;
	};
			
	this.prepareXHR = function() {
		m_objEchospin.trace(m_sConstantEchospin + ".prepareXHR");

		if (m_bXHRLoaded) return;
		else m_bXHRLoaded = true;

		m_objEchospin.log("Loading XHR");

		importIFrameXHR(m_objEchospin.$);

		m_objEchospin.log("XHR Loaded");

		try {
			m_objEchospin.$.ajaxSetup({
				crossDomain: true
			});
			m_objEchospin.$.support.cors = true;
		} catch(e) {}
	};

	function jQueryLoaded(noConflict) {		
		try {
			if (noConflict) {
				m_objEchospin.$ = window.jQuery.noConflict();
				if (m_objEchospin.$.fn.jquery != window.$.fn.jquery) m_objEchospin.$.noConflict(true);
			} else m_objEchospin.$ = window.jQuery;
	
			m_jQuery = m_objEchospin.$;
			$ = m_jQuery;
		
			m_objEchospin.log("jQuery v" + $.fn.jquery + (noConflict ? " (noConflict)" : ""));

			m_objEchospin.prepareXHR();	
			m_bJQueryLoaded = true;

			//$(function() {
				//m_objEchospin.log("DOM Ready");
				m_objEchospin.cookie.load();
			//});
		} catch(e) {		
			if (e === "error") m_bDisabled = true;
		}
	}

	try {
		if (typeof this.$ === m_sConstantFunction &&
				typeof this.$.fn.jquery === m_sConstantString &&
				parseFloat(this.$.fn.jquery.substr(2)) >= 4.3) m_bLoadJQuery = false;
	} catch(e) { }

	if (!m_bLoadJQuery) jQueryLoaded();
	else {
		m_bLoadJQuery = (typeof this.$ === m_sConstantFunction && typeof this.$.fn.jquery === m_sConstantString);
		try {
			loadScript((m_objLocation.protocol == "file:" ? "http:" : m_objLocation.protocol) + "//" + m_sJQueryURL, function() {
				jQueryLoaded(m_bLoadJQuery);
			});
		} catch(e) {
			if (e === "error") m_bDisabled = true;		
		}
	}
	
	for (m_i = 0; m_i < m_arrAPIList.length; m_i++) this[m_arrAPIList[m_i]] = new API(m_arrAPIList[m_i]);

	function loadAPI(sName, objArgs) {
		if (m_bDisabled) return false;
		if (m_bBrowserIsCompatible == null) m_objEchospin.browserIsCompatible();
		
		if (!sName ||
				m_bBrowserIsCompatible === false) return false;
		
		if (!m_bJQueryLoaded) {
			setTimeout(function() {
				loadAPI(sName, objArgs);
			}, 10);
			
			return true;
		}

		//m_objEchospin.trace(sName + ".load", objArgs);

		var sScript = m_sRootDomain + (m_sAPIMode ? m_sAPIMode + m_sConstantForwardSlash : "") + m_sAPIKey + m_sConstantJSPath + sName + m_sConstantForwardSlash,
				ptrFunc;

		try {						
			if (objArgs) m_objEchospin.loadArgs[sName] = objArgs;
			if (!loadScript(sScript)) return false;
		} catch(e) {		
			return false;
		}
		
		return true;
	}
		
	function loadScript(sScript, ptrFunc) {
		if (m_bDisabled) return false;
		if (!sScript) return false;
		else if (m_objDocument.getElementById(sScript)) return true;

	  try {
	  	var sConstantHead = "head",
	  			objScript = m_objDocument.createElement("script"),
	  			objHead = m_objDocument.getElementsByTagName(sConstantHead)[0],
	  			ptrNewFunc;
	  		  
			objScript.id = sScript;
		  objScript.src = sScript;
		  objScript.type = "text/javascript";
		  		  
		  ptrNewFunc = function(event) {
				m_objEchospin.log("Script Loaded", sScript);
				if (typeof ptrFunc == m_sConstantFunction) ptrFunc.call();
			}
			
			if (objScript.addEventListener) objScript.addEventListener("load", ptrNewFunc, false);
			else if (objScript.attachEvent) objScript.attachEvent("onreadystatechange", function() {
				if (objScript.readyState == "loaded" ||
						objScript.readyState == "complete") {
					if (ptrNewFunc) {
						ptrNewFunc.call();
						ptrNewFunc = null;
					}
				}
			});

			if (!objHead) objHead = m_objDocument.body.parentNode.appendChild(m_objDocument.createElement(sConstantHead));
			objHead.appendChild(objScript);

			m_objEchospin.log("Loading Script", sScript);
		} catch(e) {
			return false;
		}
		
		return true;
	}

	/*
	function queueLoadEvent(func) {
		if (m_objWindow.addEventListener) m_objWindow.addEventListener("load", func, false);
		else if (m_objWindow.attachEvent) m_objWindow.attachEvent("onload", func);
		else if (m_objWindow.onload) {
		  var onload = m_objWindow.onload;
		  
		  m_objWindow.onload = function() {
		    func();
		    onload();
		  }
		}
	}
	*/

	//queueLoadEvent(m_objEchospin.cookie.load);

	/** JSONML Array to DOM - quick DOM creation
	 * @author  Andrea Giammarchi
	 * @since   07/07/2008
	 * @specs   JSONML http://jsonml.org/
	 * @extra   events assignment
	 */ 
	
	this.ml = new function(multi) {
		return function(a) {
			var length,
					node,
					value,
					key;
					
		  for (m_i = 1, length = a.length, node = $(m_objDocument.createElement(a[0])), value; m_i < length; m_i++) {
		    switch (typeof(value = a[m_i])) {
		      case m_sConstantString:
		        node.append(value);
		        break;
		      
		      case m_sConstantObject:
		        if (value instanceof Array) node.append(echospin.ml(value));
		        else
		          for (key in value)
		            switch (typeof value[key]) {
		              case m_sConstantString:
		                node.attr(key, value[key]);
		                break;
		              
		              case m_sConstantNumber:
		                node.attr(key, value[key].toString());
		                break;
		              
		              case "boolean":
		                node.attr(key, (value[key]) ? "true" : "false");
		                break;
		              
		              case m_sConstantFunction:
		                value[key] = [value[key], undefined];
		              
		              case m_sConstantObject:
		                node.bind(key.replace(multi, " "), value[key][0], value[key][1]);
		                break;
		            }
		         break;
		    }
		  }
	  	return node;
		};
	};
};

echospin.Eval = function(script) {
	return eval(script);
};

