Source: RichMedia/richmedia.js

/**
 * @class
 * @classdesc Plugin to measure media.
 * @name RichMedia
 * @memberof ATInternet.Tracker.Plugins
 * @type {function}
 * @param parent {object} Instance of the Tag used
 * @public
 */
window['ATInternet']['Tracker']['Plugins']['RichMedia'] = function (parent) {
    "use strict";
    var _this = this;

    /**
     * Manage timeout Object.
     * @memberof ATInternet.Tracker.Plugins.RichMedia#
     * @function
     * @private
     */
    var _timeoutObject = function () {
        this._timeout = {};
        this.setTimeout = function (plyr, key, rfsh) {
            this._timeout[plyr] = this._timeout[plyr] || {};
            this._timeout[plyr][key] = window.setTimeout(function () {
                parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
            }, rfsh * 1e3);
        };
        this.setTimeoutObject = function (plyr, key, rfshObj) {

            this._timeout[plyr] = this._timeout[plyr] || {};
            if (typeof this._timeout[plyr][key] === 'undefined') {
                var arrObj = [];
                for (var val in rfshObj) {
                    if (rfshObj.hasOwnProperty(val)) {
                        arrObj.push({
                            delay: _filterValue(val, 0),
                            refresh: _filterValue(rfshObj[val], 5)
                        });
                    }
                }
                arrObj.sort(function (a, b) {
                    if (a.delay < b.delay) {
                        return -1;
                    }
                    if (a.delay > b.delay) {
                        return 1;
                    }
                    return 0;
                });
                this._timeout[plyr][key] = {
                    arrObj: arrObj
                };
            }

            var currentTimeout = this._timeout[plyr][key];
            if (currentTimeout.arrObj.length > 0) {

                var currentDelay = currentTimeout.arrObj[0].delay;
                var currentRfsh = currentTimeout.arrObj[0].refresh;

                if ((typeof currentDelay === 'number') && (typeof currentRfsh === 'number') && (currentRfsh > 0)) {

                    currentTimeout[currentDelay] = currentTimeout[currentDelay] || {};

                    var nextDelay = undefined;
                    if (typeof currentTimeout.arrObj[1] !== 'undefined') {
                        nextDelay = currentTimeout.arrObj[1].delay;
                    }

                    var num = 0;
                    if (typeof nextDelay === 'undefined') {
                        num = 1;
                    }
                    else if (typeof currentTimeout[currentDelay].num === 'number') {
                        num = Math.max(currentTimeout[currentDelay].num - 1, 0);
                    }
                    else if (typeof nextDelay === 'number') {
                        num = Math.floor((nextDelay - currentDelay) * 60 / currentRfsh);
                    }
                    currentTimeout[currentDelay].num = num;

                    if (num > 0) {
                        currentTimeout[currentDelay].timeout = window.setTimeout(function () {
                            parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
                        }, currentRfsh * 1e3);
                    }
                    else if (typeof currentTimeout[currentDelay].timeout !== 'undefined') {
                        window.clearTimeout(currentTimeout[currentDelay].timeout);
                        currentTimeout[currentDelay].timeout = undefined;
                        currentTimeout.arrObj.splice(0, 1);
                        window.setTimeout(function () {
                            parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
                        }, currentRfsh * 1e3);
                    }

                    this._timeout[plyr][key] = currentTimeout;
                }
            }

        };
        this.clearTimeout = function (plyr, key) {
            this._timeout[plyr] = this._timeout[plyr] || {};
            if (typeof this._timeout[plyr][key] === 'object') {
                for (var delay in this._timeout[plyr][key]) {
                    if (this._timeout[plyr][key].hasOwnProperty(delay)) {
                        var num = this._timeout[plyr][key][delay].num;
                        if (typeof num !== 'undefined' && num > 0) {
                            window.clearTimeout(this._timeout[plyr][key][delay].timeout);
                            this._timeout[plyr][key][delay].timeout = undefined;
                        }
                    }
                }
            }
            else {
                window.clearTimeout(this._timeout[plyr][key]);
            }

        };
        this.removePlayer = function (plyr) {
            for (var key in this._timeout[plyr]) {
                if (this._timeout[plyr].hasOwnProperty(key)) {
                    this.clearTimeout(plyr, key);
                    parent.richMedia.send({action: "stop", playerId: plyr, mediaLabel: key});
                }
            }
            this._timeout[plyr] = {};
        };
        this.removeAll = function () {
            for (var plyr in this._timeout) {
                if (this._timeout.hasOwnProperty(plyr)) {
                    this.removePlayer(plyr);
                }
            }
            this._timeout = {};
        };
    };

    /**
     * Manage local Media Object.
     * @memberof ATInternet.Tracker.Plugins.RichMedia#
     * @function
     * @private
     */
    var _mediaObject = function () {
        this._media = function () {
            this.type = "";
            this.plyr = "";
            this.s2 = "";
            this.clnk = "";
            this.p = "";
            this.a = "";
            this.buf = "";
            this.rfsh = "";
            this.m1 = "";
            this.m5 = "";
            this.m6 = "";
            this.m9 = "";
        };
        this._mediaAll = {};
        this.setMediaProperty = function (plyr, media, key, value) {
            this._mediaAll[plyr] = this._mediaAll[plyr] || {};
            this._mediaAll[plyr][media] = this._mediaAll[plyr][media] || new this._media();
            this._mediaAll[plyr][media][key] = value;
        };
        this.getMediaProperty = function (plyr, media, key) {
            if (this._mediaAll[plyr] && this._mediaAll[plyr][media]) {
                return (this._mediaAll[plyr][media][key]);
            }
            return '';
        };
        this.removePlayer = function (plyr) {
            this._mediaAll[plyr] = {};
        };
        this.removeAll = function () {
            this._mediaAll = {};
        };
    };

    // Local object to manage timers.
    var timeoutObject = new _timeoutObject();

    // Local object to manage all media.
    var mediaObject = new _mediaObject();

    /**
     * Get "prich" label with chapters from page context.
     * @memberof ATInternet.Tracker.Plugins.RichMedia#
     * @function
     * @param tagObject {object} object containing properties to use
     * @param type {string} property to use for chapters/mediathemes
     * @param label {string} property to use for page/media label
     * @return {string}
     * @private
     */
    var _getFullName = function (tagObject, type, label) {
        var name = tagObject[label] || '';
        parent['exec']('Utils', 'manageChapters', [tagObject, type, 3], function (data) {
            name = data + name;
        });
        return name;
    };

    /**
     * Set default hit values for boolean parameters (isBuffering & isEmbedded).
     * @memberof ATInternet.Tracker.Plugins.RichMedia#
     * @function
     * @param tagObject {object} Madia object containing properties to use
     * @param key {string} Name of the tag property to test
     * @param defaultValue {string} Default value to set
     * @param value {string} Value to set when property is true
     * @return {string}
     * @private
     */
    var _setBoolean = function (tagObject, key, defaultValue, value) {
        var val = defaultValue;
        if (typeof tagObject[key] === 'boolean') {
            if (tagObject[key]) {
                val = value;
            }
        }
        else if (tagObject[key]) {
            /* @if debug */
            parent.debug('RichMedia:richmedia:' + key + ':Error', 'ERROR', 'Not a boolean', {'value': tagObject[key]});
            /* @endif */
        }
        return val;
    };

    /**
     * Filter player ID value.
     * @memberof ATInternet.Tracker.Plugins.RichMedia#
     * @function
     * @param value {string} Value of "playerId" property from tag
     * @return {number}
     * @private
     */
    var _filterPlyrId = function (value) {
        var val = 0;
        if (/^(\-|\+)?([0-9]+)$/.test(value)) {
            val = Number(value);
        }
        else if (value) {
            /* @if debug */
            parent.debug('RichMedia:richMedia:playerId:Error', 'ERROR', 'Not an integer', {value: value});
            /* @endif */
        }
        return val;
    };

    /**
     * Manage refresh values.
     * @memberof ATInternet.Tracker.Plugins.RichMedia#
     * @function
     * @param val {string} Refresh value to process
     * @param min {string} Minimum value to set
     * @return {number}
     * @private
     */
    var _filterValue = function (val, min) {
        var _val = parseInt(val, 10);
        if (!!_val)
            return Math.max(_val, min);
        return 0;
    };

    /**
     * [Object added by plugin {@link ATInternet.Tracker.Plugins.RichMedia RichMedia}] Tags to manage media measurement.
     * @name richMedia
     * @memberof ATInternet.Tracker.Tag
     * @inner
     * @type {object}
     * @property {function} add Tag helper, see details here {@link ATInternet.Tracker.Tag#richMedia.add}
     * @property {function} remove Tag helper, see details here {@link ATInternet.Tracker.Tag#richMedia.remove}
     * @property {function} removeAll Tag helper, see details here {@link ATInternet.Tracker.Tag#richMedia.removeAll}
     * @property {function} send Tag helper, see details here {@link ATInternet.Tracker.Tag#richMedia.send}
     * @public
     */
    parent['richMedia'] = {};

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.RichMedia RichMedia}] Add media object.
     * @alias richMedia.add
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} 10 properties : mediaType, playerId, mediaLevel2, mediaLabel,
     * previousMedia, refreshDuration, duration, isEmbedded, broadcastMode, webdomain
     * @example
     * <pre><code class="javascript">tag.richMedia.add({
     *      mediaType: "video",
     *      playerId: 333,
     *      mediaLevel2: "mediaLevel2",
     *      mediaLabel: "mediaLabel",
     *      previousMedia: "previousMedia",
     *      refreshDuration: 5,
     *      duration: 20,
     *      isEmbedded: true,
     *      broadcastMode: "clip",
     *      webdomain: "http://www.atinternet.com"
     *  });
     * </code></pre>
     * @public
     */
    parent['richMedia']['add'] = _this['add'] = function (tagObject) {
        tagObject = tagObject || {};
        var plyr = _filterPlyrId(tagObject['playerId']);
        var media = _getFullName(tagObject, 'mediaTheme', 'mediaLabel');
        var isBuf = _setBoolean(tagObject, 'isBuffering', '0', '1');
        var isEmb = _setBoolean(tagObject, 'isEmbedded', 'int', 'ext');

        mediaObject.setMediaProperty(plyr, media, 'plyr', plyr);
        mediaObject.setMediaProperty(plyr, media, 'type', tagObject['mediaType'] || '');
        mediaObject.setMediaProperty(plyr, media, 's2', tagObject['mediaLevel2'] || '');
        mediaObject.setMediaProperty(plyr, media, 'p', media);
        mediaObject.setMediaProperty(plyr, media, 'clnk', tagObject['previousMedia'] || '');
        mediaObject.setMediaProperty(plyr, media, 'a', tagObject['action'] || '');
        mediaObject.setMediaProperty(plyr, media, 'buf', isBuf);
        mediaObject.setMediaProperty(plyr, media, 'rfsh', tagObject['refreshDuration'] || '');
        mediaObject.setMediaProperty(plyr, media, 'm1', tagObject['duration'] || '');
        mediaObject.setMediaProperty(plyr, media, 'm5', isEmb);
        mediaObject.setMediaProperty(plyr, media, 'm6', tagObject['broadcastMode'] || '');
        mediaObject.setMediaProperty(plyr, media, 'm9', tagObject['webdomain'] || '');

        /* @if debug */
        parent.debug('RichMedia:richMedia:add', 'DEBUG', 'method ended', {
            player: plyr,
            media: mediaObject,
            tagData: tagObject
        });
        /* @endif */
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.RichMedia RichMedia}] Remove a player with all associated media.
     * @alias richMedia.remove
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param plyr {number} Player ID
     * @example
     * <pre><code class="javascript">tag.richMedia.remove(333);
     * </code></pre>
     * @public
     */
    parent['richMedia']['remove'] = _this['remove'] = function (plyr) {
        timeoutObject.removePlayer(plyr);
        mediaObject.removePlayer(plyr);
        /* @if debug */
        parent.debug('RichMedia:richMedia:remove', 'DEBUG', 'method ended', {playerId: plyr, media: mediaObject});
        /* @endif */
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.RichMedia RichMedia}] Remove all players and media.
     * @alias richMedia.removeAll
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @example
     * <pre><code class="javascript">tag.richMedia.removeAll();
     * </code></pre>
     * @public
     */
    parent['richMedia']['removeAll'] = _this['removeAll'] = function () {
        timeoutObject.removeAll();
        mediaObject.removeAll();
        /* @if debug */
        parent.debug('RichMedia:richMedia:removeAll', 'DEBUG', 'method ended', {media: mediaObject});
        /* @endif */
    };

    /**
     * [Helper added by plugin {@link ATInternet.Tracker.Plugins.RichMedia RichMedia}] Send a media action ("play", "pause", "stop", "info").
     * @alias richMedia.send
     * @memberof! ATInternet.Tracker.Tag#
     * @function
     * @param tagObject {object} 4 properties : action, playerId, mediaLabel, isBuffering
     * @example
     * <pre><code class="javascript">tag.richMedia.send({
     *      action: "info",
     *      playerId: 333,
     *      mediaLabel: "mediaLabel",
     *      isBuffering: true
     *  });
     * </code></pre>
     * @public
     */
    parent['richMedia']['send'] = _this['send'] = function (tagObject) {
        tagObject = tagObject || {};

        var plyr = _filterPlyrId(tagObject['playerId']);
        var media = _getFullName(tagObject, 'mediaTheme', 'mediaLabel');
        var buffer = {};
        var isBuf = _setBoolean(tagObject, 'isBuffering', '0', '1');

        buffer['type'] = mediaObject.getMediaProperty(plyr, media, 'type');
        buffer['plyr'] = plyr;
        buffer['p'] = media;
        buffer['a'] = tagObject['action'] || '';
        buffer['s2'] = mediaObject.getMediaProperty(plyr, media, 's2');
        buffer['m1'] = mediaObject.getMediaProperty(plyr, media, 'm1');
        buffer['m5'] = mediaObject.getMediaProperty(plyr, media, 'm5');
        buffer['m6'] = mediaObject.getMediaProperty(plyr, media, 'm6');

        if ((buffer['type'] === '') || (buffer['m6'] === '') || (buffer['m6'] === 'clip' && buffer['m1'] === '')) {
            var _obj = {
                mediaType: buffer['type'],
                broadcastMode: buffer['m6'],
                duration: buffer['m1']
            };
            /* @if debug */
            parent.debug('RichMedia:richMedia:send:Error', 'WARNING', 'Some required parameters are missing, please use "tag.richMedia.add()" method to set', _obj);
            /* @endif */
        }

        if ((buffer.a === 'play') || (buffer.a === 'info')) {
            buffer['buf'] = isBuf;
            var contextPageObject = parent['getContext']('page') || {};
            buffer['prich'] = _getFullName(contextPageObject, 'chapter', 'name');
            buffer['s2rich'] = contextPageObject['level2'] || '';
            buffer['clnk'] = mediaObject.getMediaProperty(plyr, media, 'clnk');
            buffer['m9'] = encodeURIComponent(mediaObject.getMediaProperty(plyr, media, 'm9'));
        }

        parent.sendHit(buffer, [['hitType', ['richmedia']]]);

        if (buffer.a === 'pause' || buffer.a === 'stop') {
            timeoutObject.clearTimeout(plyr, media);
        }

        if ((buffer.a === 'play') || (buffer.a === 'refresh')) {
            var refreshValue = mediaObject.getMediaProperty(plyr, media, 'rfsh');
            if (typeof refreshValue === 'object') {
                timeoutObject.setTimeoutObject(plyr, media, refreshValue);
            } else {
                var rfsh = _filterValue(refreshValue, 5);
                if (rfsh !== 0) {
                    timeoutObject.setTimeout(plyr, media, rfsh);
                }
            }
        }

        /* @if debug */
        parent.debug('RichMedia:richMedia:send', 'DEBUG', 'method ended', {
            player: plyr,
            media: mediaObject,
            buffer: buffer,
            tagData: tagObject
        });
        /* @endif */
    };

    /* @if test */
    _this['_timeoutObject'] = _timeoutObject;
    _this['_mediaObject'] = _mediaObject;
    _this['_getFullName'] = _getFullName;
    _this['_setBoolean'] = _setBoolean;
    _this['_filterPlyrId'] = _filterPlyrId;
    _this['_filterValue'] = _filterValue;
    /* @endif */

};

window['ATInternet']['Tracker']['addPlugin']('RichMedia');