Source: suxess/loggers/eyeTrackerLogger.js

/**
 * Created by z on 16.4.2016.
 */

'use strict';
/**
 *
 * @constructor
 */
SUXESS.EyeTrackerLogger = function () {
    
    var intervalMS = 1000/SUXESS.EyeTrackerLogger.TRACK_FREQUENCY;

    var logger = this;
    $.ajax({
        type : 'GET',
        url : SUXESS.EyeTrackerLogger.GET_LAST_DATA_URL,
        crossDomain : true,
        dataType : 'json',
        success : function(response) {
            logger.intervalToken = setInterval(logger.parseTrackerData.bind(logger), intervalMS);
        },
        error : function(error) {
            console.log('Eyetracker not found');
        }
    });
    
};


SUXESS.EyeTrackerLogger.HOST = 'http://localhost:55555/api';
SUXESS.EyeTrackerLogger.TRACK_FREQUENCY = 20;
SUXESS.EyeTrackerLogger.SYSTEM_TOKEN = '12345-dynamic-aoi';

SUXESS.EyeTrackerLogger.POST_URL = SUXESS.EyeTrackerLogger.HOST +'/UXS/SendEvent';
SUXESS.EyeTrackerLogger.GET_LAST_DATA_URL =
    SUXESS.EyeTrackerLogger.HOST + '/Buffer/GetDeviceLastData?device=ET';
SUXESS.EyeTrackerLogger.GET_STATUS_URL = SUXESS.EyeTrackerLogger.HOST + '/Local/GetStatus';

/**
 *
 */
SUXESS.EyeTrackerLogger.prototype.parseTrackerData = function () {

    var logger = this;

    $.ajax({
        type : 'GET',
        url : SUXESS.EyeTrackerLogger.GET_LAST_DATA_URL,
        crossDomain : true,
        dataType : 'json',
        success : function(response) {
            console.log(response);
            var event = getElementXpathFromPosition(response.LastData);
            console.log(event);
            if (event !== null) {
                PubSub.publish( 'TEST_RUN_MOUSE_EVENT', event );
            }
        },
        error : function(error) {
            console.log(error.statusText);
        }
    });

};

/**
 *
 */
SUXESS.EyeTrackerLogger.prototype.destroy = function () {

    clearInterval(this.intervalToken);
    
};

/**
 *
 * @param trackerData
 * @returns {*}
 */
SUXESS.EyeTrackerLogger.prototype.getEventFromTrackerData = function (trackerData) {

    var leftEye = trackerData.LeftGazePoint2Dsmooth;
    var rightEye = trackerData.RightGazePoint2Dsmooth;

    var offx = window.screenX + (window.outerWidth - window.innerWidth);
    var offy = window.screenY + (window.outerHeight - window.innerHeight);

    var lx = leftEye.X - offx;
    var ly = leftEye.Y - offy;
    var rx = rightEye.X - offx;
    var ry = rightEye.Y - offy;

    var gd_lval = trackerData.LeftValidity;
    var gd_rval = trackerData.RightValidity;

    var centerx = null;
    var centery = null;

    if (gd_lval < 2 && gd_rval < 2) {
        centerx = (lx + rx) / 2;
        centery = (ly + ry) / 2;
    }
    else {
        if (gd_lval < 2) {
            centerx = lx;
            centery = ly;
        }
        else if (gd_rval < 2) {
            centerx = rx;
            centery = ry;
        }
        else
            return null;
    }

    //check if we're looking at the browser...shouldn't check xpath if we aren't
    var lookingAtBrowser = true;

    //normalize gaze point so we can check if it's in the range of 0 - 1
    var normalizedCenterX = centerx / window.innerWidth;
    var normalizedCenterY = centery / window.innerHeight;

    if(normalizedCenterX > 1 || normalizedCenterX < 0) lookingAtBrowser = false;
    if(normalizedCenterY > 1 || normalizedCenterY < 0) lookingAtBrowser = false;
    if(Number.isNaN(centerx) || Number.isNaN(centery)) lookingAtBrowser = false;

    if(lookingAtBrowser) {
        var elem = document.elementFromPoint(centerx, centery);

        var event = {
            elementId: $(elem).attr('id'),
            x: Math.floor(centerx - SUXESS.MockupEventLogger.OFFSET.left),
            y: Math.floor(centery - SUXESS.MockupEventLogger.OFFSET.top),
            type: 'eyetrack',
            time: trackerData.TimeStamp
    };
        console.log(event);
        return event;
    }

    return null;
};

/**
 *
 * @param trackerData
 * @returns {*}
 */
function getElementXpathFromPosition(trackerData) {
    var coords = getEyePosition(trackerData);

    if (coords === null)
        return null;

    var x = coords.centerx;
    var y = coords.centery;

    if(isLookingInBrowser(x,y)) {
        var elem = document.elementFromPoint(x, y);

        var event = {
            elementId: $(elem).attr('id'),
            x: x - SUXESS.MockupEventLogger.OFFSET.left,
            y: y - SUXESS.MockupEventLogger.OFFSET.top + SUXESS.MockupEventLogger.SCROLL_OFFSET_Y,
            type: 'eyetrack',
            time: Date.parse(trackerData.TimeStamp)
        };
        console.log(event);
        return event;
    }

    return null;
}

/**
 *
 * @param trackerData
 * @returns {*}
 */
function getEyePosition(trackerData) {
    var leftEye = getScreenCoordinates(trackerData.LeftGazePoint2D);
    var rightEye = getScreenCoordinates(trackerData.RightGazePoint2D);

    var lx = leftEye.x;
    var ly = leftEye.y;

    var rx = rightEye.x;
    var ry = rightEye.y;

    var gd_lval = trackerData.LeftValidity;
    var gd_rval = trackerData.RightValidity;

    var centerx = null;
    var centery = null;

    if (gd_lval < 2 && gd_rval < 2) {
        centerx = (lx + rx) / 2;
        centery = (ly + ry) / 2;
    }
    else {
        if (gd_lval < 2) {
            centerx = lx;
            centery = ly;
        }
        else if (gd_rval < 2) {
            centerx = rx;
            centery = ry;
        }
        else
            return null;
    }

    return {
        centerx: centerx,
        centery: centery
    }
}

/**
 *
 * @param eye
 * @returns {{x: number, y: number}}
 */
function getScreenCoordinates(eye) {
    var offx = screenX + (window.outerWidth - window.innerWidth);
    var offy = screenY + (window.outerHeight - window.innerHeight);

    var x = Math.round(screen.width * eye.X) - offx;
    var y = Math.round(screen.height * eye.Y) - offy;

    return {
        x: x,
        y: y
    }
}

/**
 *
 * @param x
 * @param y
 * @returns {boolean}
 */
function isLookingInBrowser(x, y) {
    var xnormal = x / window.innerWidth;
    var ynormal = y / window.innerHeight;

    return !(xnormal > 1 || xnormal < 0 || ynormal > 1 || ynormal < 0);
}

/**
 *
 * @param trackerData
 * @param xpath
 */
function sendElementXpathForPosition(trackerData, xpath) {
    port.postMessage({
        "message": "element_xpath",
        "timestamp": trackerData.TimeStamp,
        "tobii_ticks": trackerData.TobiiTicks,
        "xpath": xpath
    });
}