Source: Event/event.js

/**
 * @class
 * @classdesc Plugin used to manage event sending.
 * @name Event
 * @memberof ATInternet.Tracker.Plugins
 * @type {function}
 * @param parent {object} Instance of the Tag used
 * @public
 */
window['ATInternet']['Tracker']['Plugins']['Event'] = function (parent) {
    "use strict";

    var self = this;
    var _config = {};

    // Set specific plugin configuration.
    // If global configuration already exists, set only undefined properties.
    parent.configPlugin('Event', dfltPluginCfg || {}, function (newConf) {
        _config = newConf;
    });

    /**
     * Get events data.
     * @memberof ATInternet.Tracker.Plugins.Event#
     * @function
     * @param eventObject {object} Object from tag or event context
     * @return {String}
     * @private
     */
    var _getEvents = function (eventObject) {

        // var contextEventObject = [{
        //     'product.display': {
        //         'a:product': [],
        //         'j:customer': {
        //             's:id': 2
        //         }
        //     },
        //
        // }];

        var events = [];
        for (var i = 0; i < eventObject.length; i++) {
            for (var key in eventObject[i]) {
                if (eventObject[i].hasOwnProperty(key)) {
                    events.push({'type': key, 'data': eventObject[i][key]});
                }
            }

        }
        return ATInternet.Utils.jsonSerialize(events);
    };

    /**
     * Set events data.
     * @memberof ATInternet.Tracker.Plugins.Event#
     * @function
     * @param eventObject {object} Object from tag or event context
     * @param origin {String} Type origin. Ex: 'salesTracker', 'click', etc.
     * @private
     */
    var _setEvents = function (eventObject, origin) {
        var _origin = origin || 'event';
        parent.setParam('events', _getEvents(eventObject), {
            hitType: [_origin],
            encode: true,
            truncate: true,
            separator: ','
        });
    };

    /**
     * Check if type of tag is object.
     * @memberof ATInternet.Tracker.Plugins.Event#
     * @function
     * @param tagObject {object} Object from tag
     * @return {boolean}
     * @private
     */
    var _isObject = function (tagObject) {
        return ((typeof tagObject === 'object') && !(tagObject instanceof Array));
    };

    /**
     * Merge context with tag object.
     * @memberof ATInternet.Tracker.Plugins.Event#
     * @function
     * @param tagContext {object} Object from event context
     * @param tagData {object} Object from tag
     * @private
     */
    var _mergeValues = function (tagContext, tagData) {
        if (tagContext instanceof Array && tagData instanceof Array) {
            tagContext = tagContext.concat(tagData);
        }
        else if (_isObject(tagContext) && _isObject(tagData)) {
            tagContext = ATInternet.Utils.completeFstLevelObj(tagContext, tagData, true);
        }
        else {
            tagContext = tagData;
        }
        return tagContext;
    };

    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.Event Event}] Tags to manage event sending.
     * @name event
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @property {function} reset Tag helper, see details here {@link ATInternet.Tracker.Tag#event.reset}
     * @property {function} send Tag helper, see details here {@link ATInternet.Tracker.Tag#event.send}
     * @property {function} set Tag helper, see details here {@link ATInternet.Tracker.Tag#event.set}
     * @public
     */
    parent.event = {};

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Event Event}] Reset event context.
     * @alias event.reset
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param origin {String} Type origin. Ex: 'salesTracker', 'click', etc.
     * @example
     * <pre><code class="javascript">tag.event.reset();
     * </code></pre>
     * @public
     */
    parent.event.reset = self.reset = function (origin) {

        var _origin = origin || 'event';

        var contextEventObject = parent.getContext(_origin) || [];
        /* @if debug */
        parent.debug('Event:event:reset', 'DEBUG', 'method called', {
            'context': contextEventObject,
            'origin': _origin
        });
        /* @endif */
        parent.setContext(_origin, undefined);
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Event Event}] Tagging method for event sending (helper).
     * @alias event.send
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagType {String} Event type
     * @param tagData {object} Event value
     * @param tagElem {object} (optional) Tagged DOM element
     * @param domEvent {object} (optional) JavaScript event (prevent event propagation)
     * @param tagCallback {object} (optional) function to execute
     * @param origin {String} Type origin. Ex: 'salesTracker', 'click', etc.
     * @param domain {String} Domain of the base URL if needed
     * @examples
     * <pre><code class="javascript">
            tag.event.send("product.display", {
                's:placement': 'homepage_slider',
                'a:product': [
                    {
                        's:id': 'id1',
                        's:name': 'name1',
                        's:brand': 'brand1',
                        'f:original_price': 16.50,
                        'f:price': 14.00,
                        's:currency': 'EUR',
                        'b:stock': 1,
                        's:category1': 'category1',
                        's:category2': 'category2',
                        's:category3': 'category3',
                        's:category4': 'category4',
                        's:category5': 'category5',
                        's:category6': 'category6',
                        'n:position': 1
                    }
                ]
            });
     * </code></pre>
     * @public
     */
    parent.event.send = self.send = function (tagType, tagData, tagElem, domEvent, tagCallback, origin, domain) {

        var _origin = origin || 'event';

        var resultCheck = true;

        var eventObject = {};
        eventObject[tagType] = tagData;

        var hitObject = {};

        // 1. Set &col=2 parameter
        hitObject[_config.hitParameter] = {value: _config.hitValue, options: {multihit: true}};

        // 2. Set events
        hitObject.events = {
            value: _getEvents([eventObject]),
            options: {
                encode: true,
                truncate: true,
                separator: ','
            }
        };

        //Safari preview.
        if (ATInternet.Utils.isPreview() && parent.getConfig('preview')) {
            hitObject.pvw = 1;
        }

        parent.exec('TechClicks', 'manageClick', [tagElem, domEvent], function (data) {
            resultCheck = data;
        });

        parent.manageSend(function () {
            parent.sendHit(hitObject, [['hitType', [_origin]]], tagCallback, domain, true);
        });

        /* @if debug */
        parent.debug('Event:event:send', 'DEBUG', 'method ended', {
            'type': tagType,
            'data': tagData,
            'origin': _origin
        });
        /* @endif */

        return resultCheck;
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Event Event}] Set events.
     * @alias event.set
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagType {String} Event type
     * @param tagData {object} Event value
     * @param tagKey {object} Event key
     * @param origin {String} Type origin. Ex: 'salesTracker', 'click', etc.
     * @examples
     * <pre><code class="javascript">
            tag.event.set("product.display", {
                's:placement': 'homepage_slider',
                'a:product': [
                    {
                        's:id': 'id1',
                        's:name': 'name1',
                        's:brand': 'brand1',
                        'f:original_price': 16.50,
                        'f:price': 14.00,
                        's:currency': 'EUR',
                        'b:stock': 1,
                        's:category1': 'category1',
                        's:category2': 'category2',
                        's:category3': 'category3',
                        's:category4': 'category4',
                        's:category5': 'category5',
                        's:category6': 'category6',
                        'n:position': 1
                    }
                ]
            });
     * </code></pre>
     * @public
     */
    parent.event.set = self.set = function (tagType, tagData, tagKey, origin) {

        var _origin = origin || 'event';

        // 1. Set &col=2 parameter
        parent.setParam(_config.hitParameter, _config.hitValue, {multihit: true, hitType: [_origin]});

        // Register helper to final call in order to send messages.
        parent.dispatchSubscribe(_origin);

        var contextEventObject = parent.getContext(_origin) || [];
        var foundType = false;

        for (var i = 0; i < contextEventObject.length; i++) {
            if (contextEventObject[i][tagType]) {
                foundType = true;
                if (tagKey) {
                    if (_isObject(contextEventObject[i][tagType])) {
                        contextEventObject[i][tagType][tagKey] = _mergeValues(contextEventObject[i][tagType][tagKey], tagData);
                    }
                }
                else {
                    contextEventObject[i][tagType] = _mergeValues(contextEventObject[i][tagType], tagData);
                }
            }
        }

        if (!foundType) {
            var defaultValue = {};
            if (tagKey) {
                defaultValue[tagType] = {};
                defaultValue[tagType][tagKey] = tagData;
            }
            else {
                defaultValue[tagType] = tagData;
            }
            contextEventObject.push(defaultValue);
        }

        parent.setContext(_origin, contextEventObject);

        /* @if debug */
        var data;
        if (tagKey) {
            data = {};
            data[tagKey] = tagData;
        }
        else {
            data = tagData;
        }
        parent.debug('Event:event:set', 'DEBUG', 'method ended', {
            'type': tagType,
            'data': data,
            'origin': _origin
        });
        /* @endif */

    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Event Event}] Add events.
     * @alias event.add
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagType {String} Event type
     * @param tagData {object} Event value
     * @param origin {String} Type origin. Ex: 'salesTracker', 'click', etc.
     * @examples
     * <pre><code class="javascript">
            tag.event.add("product.display", {
                's:placement': 'homepage_slider',
                'a:product': [
                    {
                        's:id': 'id1',
                        's:name': 'name1',
                        's:brand': 'brand1',
                        'f:original_price': 16.50,
                        'f:price': 14.00,
                        's:currency': 'EUR',
                        'b:stock': 1,
                        's:category1': 'category1',
                        's:category2': 'category2',
                        's:category3': 'category3',
                        's:category4': 'category4',
                        's:category5': 'category5',
                        's:category6': 'category6',
                        'n:position': 1
                    }
                ]
            });
     * </code></pre>
     * @public
     */
    parent.event.add = self.add = function (tagType, tagData, origin) {
        var _origin = origin || 'event';
        var contextEventObject = parent.getContext(_origin) || [];
        var defaultValue = {};
        defaultValue[tagType] = tagData;
        contextEventObject.push(defaultValue);
        parent.setContext(_origin, contextEventObject);
        /* @if debug */
        parent.debug('Event:event:add', 'DEBUG', 'method ended', {
            'type': tagType,
            'data': tagData,
            'origin': _origin
        });
        /* @endif */

    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.Event Event}] Will be called by tracker.dispatch if any event has been set.
     * @alias event.onDispatch
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param callback {function} Callback to execute
     * @param origin {String} Type origin. Ex: 'salesTracker', 'click', etc.
     * @param domain {String} Domain of the base URL if needed
     * @private
     */
    parent.event.onDispatch = self.onDispatch = function (callback, origin, domain) {

        // Get context
        var _origin = origin || 'event';
        var contextEventObject = parent.getContext(_origin);
        if (typeof contextEventObject !== 'undefined') {
            // 2. Set events
            _setEvents(contextEventObject, _origin);
        }
        parent.setContext(_origin, undefined);

        // Safari preview.
        if (ATInternet.Utils.isPreview() && parent.getConfig('preview')) {
            parent.setParam('pvw', 1, {hitType: [_origin]});
        }

        parent.manageSend(function () {
            parent.sendHit(null, [['hitType', [_origin]]], callback, domain);
        });
    };

    // For unit tests on private elements !!!
    /* @if test */
    var _this = this;
    _this._getEvents = _getEvents;
    _this._setEvents = _setEvents;
    _this._isObject = _isObject;
    _this._mergeValues = _mergeValues;
    /* @endif */
};
window['ATInternet']['Tracker']['addPlugin']('Event');