/*
 * Filename.....: xmClickTrack.js
 * Description..: HTML page click tracking reporting mechanisms for Rebus.
 * Copyright....: Copyright (c) 2006, XModus Software Inc., all rights reserved.
 * Version......: 0.90a
 * Date.........: 03-Oct-06 - ck
 *
 * NOTE: the following two variables are defined on the client page and used within this script (only the siteID is required)
 * var xm_clientSiteID = 28373; (client's site ID for tracking multiple clients)
 * var xm_clientPageID = '<pageName>' (optional: if defined you can track by named page, otherwise takes the HTML title/browser combination)
 *
 * Usage: include xmClickTrack.js and define the variables within your script call
 *
 */

// debugging
var xm_isDebugging = false;
var xm_drawRedBox  = false;

// click tracking version
var xm_trackVer = 200610031339;

// browser hints
var xm_isOldIE     = (document.all) ? true : false;     // only old IE's use this
var xm_hasElements = (document.documentElement && document.documentElement.clientHeight > 0) ? true : false;
var xm_isSafari    = (navigator.appVersion.indexOf("Safari") != -1);

// identification elements
var xm_scriptLoadTime = (new Date()).getTime();
var xm_clickCount = 0;      // click count, if they click more than once on the same page then we count the clicks too
var xm_sessionID;           // the user's session ID (if we can find it)
var xm_clickScript = null;  // this click script as an object so we can append it to the source page
var xm_pageID = null;// current (html) page ID
var xm_pageBody;            // the body element of the current document/window
var xm_divHook;             // the div tag we plant to hook an element

/**************************************
 * page functions
 **************************************/
 
//
// xmfn_hookPage
// used to attach our new tracking javascript to this window/page
//
function xmfn_hookPage()
{
    var currentWindow = window.onload;
    
    if (xm_isDebugging)
    {
        alert("xmfn_hookHTMLPage() is hooking the window");
    }
    
    // check if the window onload already has a javascript fn
    if(typeof currentWindow != 'function')
    {
        // no fn, so add our fn as the starting fn
        window.onload = xmfn_clickInit;
    }
    else
    {
        // there is an existing function, so create a new one
        window.onload = function()
        {
            // call the old fn and then call our tracking fn
            currentWindow();
            xmfn_clickInit();
        }
    }
    
    return null;
};

//
// xmfn_clickInit
// this is hooked into window.onload to catch the mouse events
//
function xmfn_clickInit()
{
    // get some global values based on the doc/page
    xm_pageBody = document.getElementsByTagName("body").item(0);
    xm_sessionID = xmfn_getSessionCookieID();
    xmfn_setPageTrackURL();
    
    // TODO: why do we need to do this?
    /*
    xm_divHook = document.createElement("div");
    xm_divHook.style.display = "none";
    xm_divHook.style.position = "absolute";
    xm_pageBody.appendChild(xm_divHook);
    */
    
    // hook the document's OnMouseDown event with function xmfn_OnMouseEventHook()
    document.onmousedown = xmfn_OnMouseEventHook;
    
    return null;
};

//
// xmfn_setPageTrackURL
// set up the base page URL for tracking
//
function xmfn_setPageTrackURL()
{
    var QS = 'siteID=' + xm_clientSiteID + '&scrx=' + window.screen.width + '&scry=' + window.screen.height;

    if(xmfn_isValidSessionID(xm_sessionID) && xm_sessionID > -1)
    {
        // we have a session ID, so return it too
        QS += 'sessionID=' + xm_sessionID;
    }
    
    if(typeof(xm_clientPageID) == 'undefined')
    {
        QS += '&pageID=' + escape(window.location.pathname + window.location.search);
    }
    else
    {
        QS += '&pageID=' + xm_clientPageID;
    }
    
    return xmfn_AddTrackingString(QS);
};


//
// xmfn_getSessionCookieID
// parse the cookie to get the user's session ID, if there is one
//
function xmfn_getSessionCookieID()
{
    var docCookie = document.cookie;
    var startStr = docCookie.indexOf("XMCLICKSESSION=");
    var sessionID = null;
    var colonSep = 0;

    // if we have an existing cookie then get it so we can use it
    if(startStr != -1)
    {
        startStr += 15;    // 15 = len("XMCLICKSESSION=")
        
        colonSep = docCookie.indexOf(";", startStr);
        colonSep = (colonSep == -1) ? docCookie.length : colonSep;
        
        // grab the current session ID
        sessionID = docCookie.substring(startStr, colonSep).replace(/\s+/, "");
    }
    
    return sessionID;
}

//
// xmfn_isValidSessionID
//
function xmfn_isValidSessionID(sessionID)
{
    if((sessionID == null) || (typeof(sessionID) == 'undefined'))
    {
        return false;
    }
    
    return true;
};


//
// xmfn_OnMouseEventHook
// called by the browser for an OnMouseEvent from within the current document
//
function xmfn_OnMouseEventHook(eventHandler)
{
    // we need a session ID, otherwise we can't report it
    if(!xmfn_isValidSessionID(xm_sessionID) || xm_sessionID == -1)
    {
        // so if we don't have one then exit
        if (xm_isDebugging)
        {
            alert("ERROR: no session ID, aborting");
        }
        return true;
    }
     
    // browser-specific adjustments   
    var clickedItem = null;
    var docWin = null;
    var safWin = null;
    
    if(xm_isOldIE)
    {
        // older IE, with JScript
        eventHandler = window.event;
        clickedItem = eventHandler.button;
        docWin = (xm_hasElements) ? document.documentElement : document.body;
        safWin = docWin;
    }
    else
    {
        // compliant browser with Javascript
        clickedItem = eventHandler.which;
        docWin = document.body;
        safWin = (xm_hasElements) ? docWin.parentNode : docWin;
    }
    
    // we didn't get the correct parent item, so exit
    if (clickedItem != 1)
        return true;

    // window area
    var w = new Array();
    w['cx'] = eventHandler.clientX;
    w['cy'] = eventHandler.clientY;
    w['wx'] = ((typeof(docWin.clientWidth) == 'undefined')  || xm_isSafari) ? window.innerWidth  : safWin.clientWidth;
    w['wy'] = ((typeof(docWin.clientHeight) == 'undefined') || xm_isSafari) ? window.innerHeight : safWin.clientHeight;
    
    if (xm_drawRedBox)
    {
        // lets show a red box when you click (for debugging)
        var redBox = document.getElementById("redBox");
        
        // -2 because the box is 5x5, so we want to center it around the click area
        // you need the page offsets to account for being off the page due to scrolling
        redBox.style.left = (eventHandler.clientX + window.pageXOffset) - 2;
        redBox.style.top = (eventHandler.clientY + window.pageYOffset) - 2;
    }
    
    // verify minimum client and window size info, otherwise exit
    if((w['cx'] > w['wx'])||(w['cy'] > w['wy']))
        return true;
        
    // adjust the sizing to accommodate scroll bars
    if(xm_isOldIE)
    {
        w['cx'] += docWin.scrollLeft;
        w['cy'] += docWin.scrollTop;
        w['sx'] = docWin.scrollLeft;
        w['sy'] = docWin.scrollTop;
    }
    else
    {
        w['cx'] += window.pageXOffset;
        w['cy'] += window.pageYOffset;
        w['sx'] = window.pageXOffset;
        w['sy'] = window.pageYOffset;
    }
    
    // record the time delay (in seconds) between when the page loaded and the click occurs
    var currentTime =(new Date()).getTime();
    w['dt'] = (currentTime - xm_scriptLoadTime) / 1000;
    xm_scriptLoadTime = currentTime;        // reset the script time incase they click again...
    
    // record the click count
    w['cc'] = xm_clickCount++;
    
    var targetElement = (xm_isOldIE) ? eventHandler.srcElement : eventHandler.target;
    var targetXY = xmfn_getElementXY(targetElement, true);
    
    // if J is a hyperlinked image then set J to the parent, which would be the link
    if((targetElement.nodeName.toLowerCase() == "img") && (targetElement.parentNode.nodeName.toLowerCase() == "a"))
        targetElement = targetElement.parentNode;

    // if we have a clickable item then record it's name
    // tn = target node name
    switch (targetElement.nodeName.toLowerCase())
    {
        case "a":
        case "img":
        case "input":
        case "button":
        case "textarea":
        case "select":
            w['tn'] = targetElement.nodeName.toLowerCase();
            break;
    }

    // record the position of the click, adjusted to the window
    w['tx'] = targetXY['x'];
    w['ty'] = targetXY['y'];
    
    // record the site & client info
    w['siteID'] = xm_clientSiteID;
    w['sessionID'] = xm_sessionID;
    
    // if the client page has supplied a page ID then we'll use that instead
    if(typeof xm_clientPageID != 'undefined')
    {
        xm_pageID = xm_clientPageID;
    }
    
    if(xm_pageID != null)
    {
        w['pageID'] = xm_pageID;
    }
    else
    {
        w['page'] = window.location.pathname + window.location.search;
    }

    // build the submission query string using the 'w' variables defined above    
    var qs = '';

    for(W in w)
    {
        qs += W + "=" + escape(w[W]) + "&";
    }
    
    xmfn_AddTrackingString(qs);
    
    return true;
};

// 
// xmfn_AddTrackingString
// builds the full URL and adds it as the script to the element that is being clicked
//
function xmfn_AddTrackingString(trackingStr)
{
    // NOTE: I added the 'file:' protocol to support localhost testing
    if((window.location.protocol == "http:") || (window.location.protocol == "https:") || (window.location.protocol == "file:"))
    {
        if(xm_clickScript != null)
        {
            // if we already exist, remove us
            try
            {
                xm_clickScript.parentNode.removeChild(xm_clickScript);
            }
            catch(e)
            {}
            
            xm_clickScript = null;
        }
        
        xm_clickScript = document.createElement("script");
        xm_clickScript.setAttribute("type", "text/javascript");
        
        // TODO: we check the protocol version because we might send the results to different servers for HTTP (dev/test) vs HTTPS (prod)
        if(window.location.protocol == "https:")
        {
            if (xm_isDebugging)
            {
                alert("clickTracker.htm?version=" + xm_trackVer + "&" + trackingStr);
            }
            xm_clickScript.setAttribute("src", "clickTracker.htm?version=" + xm_trackVer + "&" + trackingStr);
        }
        else
        {
            if (xm_isDebugging)
            {
                alert("clickTracker.htm?version=" + xm_trackVer + "&" + trackingStr);
            }
            xm_clickScript.setAttribute("src", "clickTracker.htm?version=" + xm_trackVer + "&" + trackingStr);
        }
        
        // append the new script to the HTML page's HEAD
        document.getElementsByTagName("head")[0].appendChild(xm_clickScript);
        
        return true;
    }
    else
    {
        return false;
    }
};

//
// xmfn_getElementXY
// return an array (x/y) for the element
// if isNullZero and the element is NULL then return x & y as zero
//
function xmfn_getElementXY(e, isNullZero)
{
    var A = new Array();
    A['x'] = 0;
    A['y'] = 0;
    
    if(null == e)
    {
        if(isNullZero)
            return A;
            
        var pageBody = document.getElementsByTagName("body");
        
        if(pageBody.length == 0)
        {
            return A;
        }
        
        e = pageBody[0];
    }
    
    if((e.nodeName.toLowerCase() == "a") && (e.innerHTML.match(/<img/i)))
    {
        e = e.getElementsByTagName("img")[0];
    }
    
    while(e != null)
    {
        if(isNaN(e.offsetLeft) && isNaN(e.offsetTop))
        {
            break;
        }
        else if(isNaN(e.offsetLeft))
        {
            A['y'] += e.offsetTop;
        }
        else if(isNaN(e.offsetTop))
        {
            A['y'] += e.offsetTop;
        }
        else
        {
            A['x'] += e.offsetLeft;
            A['y'] += e.offsetTop;
        }
        
        e = e.offsetParent;
    }
    
    return A;
};


//
// xmfn_setSession
//
function xmfn_setSession(sessionID)
{
    xm_sessionID = sessionID;
    document.cookie = "XMCLICKSESSION=" + sessionID + ";";
    return null;
};


 /**************************************
 * hook the page!
 **************************************/
 xmfn_hookPage();
 