/************************************************************************************
	XDGAT - Gavin's unobstrusive Cross-Domain Google Analytics Tracking script
	version 1.2
************************************************************************************/
	/*
		describes an object that attempts to apply google analytics cross-domain behavior to all
		links on a page that reference external domains in a supplied whitelist.
		
		achieves desired behavior by:
			1) processing white-list of domains to apply behavior to
			2) detect the loading of the external google analytics javascript library
			3) scan current page for all <a> and <form> elements that reference domain white-list entry
			4) add listener to links matching domain criteria, callback executes google analytics cross-domain feature
		
		object
			crossDomainGoogleAnalyticsTracking
		methods
			initialize, returns Null
			removeDomainIfMatchesHost: returns Null
			whenAnalyticsLibraryLoaded: (Function f), returns Null, executes passed callback function when conditions met
			attachEventToLinks: (Array collection_of_links), returns Null
			attachEventToForms: (Array collection_of_forms), returns Null
			getCollectionOfDomainLinks, returns Array
			getCollectionOfDomainForms returns Array
			doesUrlContainDomain: (String url, String domain), returns Boolean
			propertyExists: (Object object, String required_data), returns Boolean
	*/
	
	function crossDomainGoogleAnalyticsTracking(options) {
		this.links = [];
		this.forms = [];
		this.domains = (this.propertyExists(options, 'domains')) ? options.domains : [];
		this.queue_object = (this.propertyExists(options, 'queue_object')) ? options.queue_object : [];
		this.tracking_object = (this.propertyExists(options, 'tracking_object')) ? options.tracking_object : [];
		this.initialize();
	};
	crossDomainGoogleAnalyticsTracking.prototype = {
		initialize: function() {
			this.removeDomainIfMatchesHost();
			this.whenAnalyticsLibraryLoaded(function() {
				this.attachEventToLinks(this.getCollectionOfDomainLinks());
				this.attachEventToForms(this.getCollectionOfDomainForms());
			});
		},
		removeDomainIfMatchesHost: function() {
			for (var item in this.domains) {
				if (this.doesUrlContainDomain(window.location.hostname, this.domains[item])) {
					this.domains.splice(item, 1);
				}
			};
		},
		whenAnalyticsLibraryLoaded: function(f) {
			var self = this;
			var loadCheck = window.setInterval(function() {
				if ( (window[self.queue_object] instanceof Array) == false) {
					window.clearInterval(loadCheck);
					f.call(self);
				}
			} , 1);
		},
		attachEventToLinks: function(collection_of_links) {
			for (i in collection_of_links) {
				var self = this;
				$(collection_of_links[i]).bind('click', function(event) {
					try {
						self.tracking_object._link(this.href);
						event.preventDefault();
					} catch(error) {}
				});
			}
		},
		attachEventToForms: function(collection_of_forms) {
			for (i in collection_of_forms) {
				var self = this;
				$(collection_of_forms[i]).bind('click', function(event) {
					try {
						self.tracking_object._linkByPost(this);
					} catch(error) {}
				});
			}
		},
		getCollectionOfDomainLinks: function() {
			var self = this;
			$("a").each(function() {
				var link_element = this;
				for (i in self.domains) {
					if (self.doesUrlContainDomain(link_element.href, self.domains[i])) {
						self.links.push(link_element);
					}
				}
			});
			return this.links;
		},
		getCollectionOfDomainForms: function() {
			var self = this;
			$("form").each(function() {
				var form_element = this;
				for (i in self.domains) {
					if (self.doesUrlContainDomain(form_element.action, self.domains[i])) {
						self.forms.push(form_element);
					}
				}
			});
			return this.forms;
		},
		doesUrlContainDomain: function(url, domain) {
			return (url.indexOf(domain) > 0) ? true : false;
		},
		propertyExists: function(object, required_data) {
			if (required_data instanceof Array) {
				var required_data_present = true;
				for (var item in required_data) { 
					required_data_present &= this.propertyExists(object, required_data[item]);
				};
				return required_data_present;
			} else {
				return (typeof object[required_data] != 'undefined') ? true : false;
			}
		}
	};
