﻿/**
** Browser Detect
** A useful but often overrated JavaScript function is the browser detect. 
** Sometimes you want to give specific instructions or load a new page in case the viewer uses, for instance, Safari.
**  
**  http://www.quirksmode.org/js/detect.html
**-----------------------------------------------------------*/
var fxmBrowserDetect = {
    init: function() {
        this.browser = this.searchString(this.dataBrowser) || '';
        this.version = this.searchVersion(navigator.userAgent) || this.searchVersion(navigator.appVersion) || '';
        this.OS = this.searchString(this.dataOS) || '';
    },
    searchString: function(data) {
        for (var i = 0; i < data.length; i++) {
            var dataString = data[i].string;
            var dataProp = data[i].prop;
            this.versionSearchString = data[i].versionSearch || data[i].identity;
            if (dataString) {
                if (dataString.indexOf(data[i].subString) != -1) {
                    return data[i].identity;
                }
            }
            else if (dataProp) {
                return data[i].identity;
            }
        }
    },
    searchVersion: function(dataString) {
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) return;
        return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
    },
    dataBrowser: [
        { string: navigator.userAgent, subString: "Chrome", identity: "Chrome" },
        { string: navigator.userAgent, subString: "OmniWeb", versionSearch: "OmniWeb/", identity: "OmniWeb" },
        { string: navigator.vendor, subString: "Apple", identity: "Safari", versionSearch: "Version" },
        { prop: window.opera, identity: "Opera" },
        { string: navigator.vendor, subString: "iCab", identity: "iCab" },
        { string: navigator.vendor, subString: "KDE", identity: "Konqueror" },
        { string: navigator.userAgent, subString: "Firefox", identity: "Firefox" },
        { string: navigator.vendor, subString: "Camino", identity: "Camino" },
        { string: navigator.userAgent, subString: "Netscape", identity: "Netscape" },
        { string: navigator.userAgent, subString: "MSIE", identity: "Explorer", versionSearch: "MSIE" },
        { string: navigator.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" },
        { string: navigator.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla"}],
    dataOS: [
        { string: navigator.platform, subString: "Win", identity: "Windows" },
        { string: navigator.platform, subString: "Mac", identity: "Mac" },
        { string: navigator.userAgent, subString: "iPhone", identity: "iPhone/iPod" },
        { string: navigator.platform, subString: "Linux", identity: "Linux"}]
};


/* Copyright @Rawsoft, Inc.
** Developer: Rydal Williams
**
**
** Note: If you start having event issues, try using this method
**  - http://dean.edwards.name/weblog/2005/10/add-event2/
**----------------------------------------------------------------------------*/
// FoxMetrics Variable function
var fxm = function() {
    // private variables
    var sessionId;
    var visitorId;
    var initialized = false;
    var debugMode = (document.location.host == 'localhost') ? true : false;
    var idCookieName = 'fxmv';
    var sessionIdCookieName = 'fxms';
    var pingInterval = 15000;
    var userActivityCode = "i"; // i= idle, r=reading, w=writing
    var customHost;

    // returns the host url that it should use
    //==========================================================================================
    function Host() {
        var protocol = (("https:" == document.location.protocol) ? "https://" : "http://");
        return protocol + (document.location.host == 'localhost' ? 'localhost/foxmetrics.static/' : 'fxm1.foxmetrics.com/');
    }

    // returns the website id that will be used to uniquely identify these entries
    //==========================================================================================
    function Id() {
        if (typeof (customHost) !== 'undefined')
            return customHost;
        return (window.location.host || window.location.hostname);
    }

    // Make sure we have the neccesary requirements
    //==========================================================================================
    function HasRequirements() {
        if (typeof (sessionId) != 'undefined'
            && typeof (visitorId) != 'undefined'
            && sessionId.length > 0
            && visitorId.length > 0) {
            return true;
        }
        return false;
    }

    // An action that we want to record has fired. Record the action.
    // This is the heart of Foxmetrics, each event has one or more properties or params
    // Reserved names are {pageview, download, exit, funnel, event}
    //==========================================================================================
    function RecordAction(name, params) {
        log('Action: ' + name);

        // ensure
        if (!HasRequirements())
            return;

        // begin preparing the url
        var url = Host() + 'fxm.ashx?a=' + name + '&h=' + Id() + '&sid=' + sessionId + '&vid=' + visitorId;
        var unixtime = parseInt(new Date().getTime().toString().substring(0, 10), 10);

        // handles page view, if the user doesn't specify anything then build it automatically
        if (name == 'pageview' && (typeof (params) == 'undefined' || params == null)) {
            params = {
                "href": window.location.pathname,
                "pt": document.title,
                "rf": document.referrer,
                "ltzo": new Date().getTimezoneOffset(),
                "time": unixtime,
                "scrw": screen.width,
                "scrh": screen.height,
                "lng": (navigator.browserLanguage || navigator.userLanguage || navigator.language || ""),
                "plt": (typeof (fxmPageStartTime) == 'undefined') ? "0" : (new Date().getTime() - fxmPageStartTime.getTime()),
                "bn": (fxmBrowserDetect != 'undefined' ? fxmBrowserDetect.browser : ''),
                "bv": (fxmBrowserDetect != 'undefined' ? fxmBrowserDetect.version : ''),
                "osn": (fxmBrowserDetect != 'undefined' ? fxmBrowserDetect.OS : '')
            };
        } else if (name == 'ping' && (typeof (params) == 'undefined' || params == null)) {
            params = {
                "href": window.location.pathname,
                "pt": document.title,
                "ac": userActivityCode
            };
        } else { }

        // for each property in the param that the user passes
        if (typeof (params) != 'undefined' && params != null) {
            // make sure we have an href
            if (params.href == 'undefined' || params.href == null) params.href = encodeURIComponent(window.location.pathname);

            // build the url query string parameters
            for (prop in params) {
                url = url + '&' + prop + '=' + encodeURIComponent(params[prop]);
            }
        }

        //
        RequestURL(url);
        WaitFor(300);

        //
        log('URL: ' + url);
    }

    /**
    * Logs a message.
    *
    * @param  message @type mixed Log message.
    * @param  priority @type String Message priority (log, debug, info, warning, error).
    * ==========================================================================================*/
    function log(message, priority) {
        try {
            debugMode && typeof (console) != 'undefined' && console[priority || 'debug']('[fxm] %s: %s', arguments.callee.caller.name || 'main', message);
        } catch (e) { }
    }

    // Something was clicked, record the event by first trying to determine what was clicked
    //==========================================================================================
    function ClickEvent(e) {
        var el = (e.srcElement) ? e.srcElement : e.target;
        // for now we are only tracking hyperlinks, maybe we can track some other stuff in the future.
        if (el.tagName.toUpperCase() == 'A') {
            var dwn = el.pathname.match(/(?:doc|eps|jpg|png|svg|xls|ppt|pdf|xls|zip|txt|vsd|vxd|js|css|rar|exe|wma|mov|avi|wmv|mp3)($|\&)/);
            if (dwn) {
                // is the user trying to download a file?
                RecordAction('download', { "dhref": el.href });
            } else {
                // otherwise, if the hostname is not ours then the user is exiting
                if ((!dwn || dwn == null) && el.hostname != location.host && el.hostname.indexOf('javascript') == -1 && el.hostname != '') {
                    RecordAction('exit', { "ehref": el.href });
                }
            }
        }
    }

    // adds an event
    //==========================================================================================
    function AddEvent(obj, evType, fn) {
        if (obj.addEventListener) {
            obj.addEventListener(evType, fn, false);
            return true;
        } else if (obj.attachEvent) {
            var r = obj.attachEvent("on" + evType, fn);
            return r;
        } else {
            return false;
        }
    }

    // removes and event
    //==========================================================================================
    function RemoveEvent(obj, evType, fn, useCapture) {
        if (obj.removeEventListener) {
            obj.removeEventListener(evType, fn, useCapture);
            return true;
        } else if (obj.detachEvent) {
            var r = obj.detachEvent("on" + evType, fn);
            return r;
        } else {
            //alert("Handler could not be removed");
        }
    }

    // Generates a random string
    //==========================================================================================
    function RandomString() {
        var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
        var string_length = 32;
        var randomstring = '';
        for (var i = 0; i < string_length; i++) {
            var rnum = Math.floor(Math.random() * chars.length);
            randomstring += chars.substring(rnum, rnum + 1);
        }
        return randomstring;
    }

    // save cookie to client computer
    //==========================================================================================
    function SaveCookie(name, value, days, minutes, domain) {
        if (days) {
            var date = new Date();
            if (minutes == null) minutes = 0;

            if (minutes > 0) {
                date.setTime(date.getTime() + (60 * 1000 * minutes));
            } else {
                date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            }
            var expires = "; expires=" + date.toGMTString();
        }
        else {
            var expires = "";
        }

        // do we need to specify a domain?
        var dmn = '';
        if (typeof domain != 'undefined') dmn = '; domain=' + domain;

        // create the cookie
        document.cookie = name + "=" + value + expires + "; path=/" + dmn;
        return value;
    }

    // create a cookie or get the value of a cookie
    //==========================================================================================
    function GetCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
        }
        return null;
    }

    // Gets a cookie and sets it if its null with the null params passed
    //==========================================================================================
    function GetSetCookie(cookieName, nullValue, nullExpiration, nullDomain) {
        var cookieValue = GetCookie(cookieName);
        if (!cookieValue) {
            SaveCookie(cookieName, nullValue, nullExpiration, null, nullDomain);
            return nullValue;
        }
        return cookieValue;
    }

    // A call to this method will automatically/seamlessly append a required js file to the head of this page.
    //==========================================================================================
    function RequestURL(url) {
        var script = document.createElement('script');
        script.type = "text/javascript";
        try {
            script.defer = "defer";
        } catch (e) { }
        script.src = url;
        document.getElementsByTagName('head')[0].appendChild(script);
    }

    // Delay for a certain number of milliseconds (delay)
    //==========================================================================================
    function WaitFor(delay) {
        var date = new Date();
        var curDate = null;
        do { curDate = new Date(); }
        while (curDate - date < delay);
    }

    // begin ping the fxm servers and let us know that this session is still active
    //==========================================================================================
    function PingAlive(interval) {
        setInterval(function() { RecordAction('ping', null); }, interval);
    }

    // public methods
    return {
        //==========================================================================================
        // Global values that are used accross the page
        //==========================================================================================
        host: function() {
            // returns the host url that it should use
            return Host();
        },
        setHost: function(host) {
            customHost = host;
        },
        websiteId: function() {
            // returns the website id
            return websiteId;
        },
        //==========================================================================================
        // Utilities portion of things
        //==========================================================================================
        insertScript: function(url) {
            // inject the following javascript url into the page
            RequestURL(url);
        },
        wait: function(ms) {
            // delays for the number of milliseconds specified
            WaitFor(ms);
        },
        getElement: function(id) {
            // get the element from a document and return
            return document.getElementById(id);
        },
        addEvent: function(obj, evType, fn) {
            return AddEvent(obj, evType, fn);
        },
        getCookie: function(name) {
            return GetCookie(name);
        },
        //==========================================================================================
        // Analytics portion of things
        //==========================================================================================
        Init: function() {
            // this variable is used to track page load time
            // to really log in accurate page load times, the "pageview" log should not be called until
            // onload event
            startTime = new Date();

            // detect browsers if need be
            if (fxmBrowserDetect) fxmBrowserDetect.init();

            // if this user has not been marked then do so. cookie that will last for 10 years
            // this is a permanent id that is unique to this pc/browser.
            visitorId = GetSetCookie(idCookieName, RandomString(), (365 * 10));

            // keep track of this session id, this cookie only last for this session
            // so that we can track sessions.
            sessionId = GetSetCookie(sessionIdCookieName, RandomString(), null);

            // starting listening to crap like mouse down events
            AddEvent(document, 'mousedown', ClickEvent);

            // Activity Code
            AddEvent(document, 'keyup', function() { userActivityCode = 'w'; });
            AddEvent(document, 'mousemove', function() { userActivityCode = 'r'; });
            setInterval(function() { userActivityCode = 'i'; }, 5000);

            // begin pinging the fxm, they let us know that you are active
            if (typeof (fxmEnablePinging) == 'undefined' || (typeof (fxmEnablePinging) != 'undefined' && fxmEnablePinging == true))
                PingAlive(pingInterval);

            // we are set
            initialized = true;
        },

        //==========================================================================================
        // Logs an event and its properties
        //==========================================================================================
        Log: function(name, properties) {
            if (!initialized) this.Init();
            if (typeof (name) != 'undefined' && name.length > 0) {
                RecordAction(name, properties);
            }
        }
    };
} ();
