/**
* @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 self = this;
var _debug = {
level: 'DEBUG',
messageEnd: 'method ended'
};
/**
* Manage refresh values.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @param val {string} Refresh value to process
* @param min {number} 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;
};
/**
* Manage local Media Object.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @private
*/
var Media = function () {
this.media = function () {
this.type = undefined;
this.plyr = 0;
this.s2 = undefined;
this.clnk = undefined;
this.p = '';
this.a = undefined;
this.buf = undefined;
this.rfsh = undefined;
this.m1 = undefined;
this.m5 = undefined;
this.m6 = undefined;
this.m9 = undefined;
};
this.mediaAll = {};
this.setMediaValue = function (playerId, mediaLabel, param, value) {
if (typeof value !== 'undefined') {
this.mediaAll[playerId] = this.mediaAll[playerId] || {};
this.mediaAll[playerId][mediaLabel] = this.mediaAll[playerId][mediaLabel] || new this.media();
this.mediaAll[playerId][mediaLabel][param] = value;
}
};
this.getMediaValue = function (playerId, mediaLabel, param) {
if (this.mediaAll[playerId] && this.mediaAll[playerId][mediaLabel]) {
return (this.mediaAll[playerId][mediaLabel][param]);
}
return undefined;
};
this.removePlayer = function (playerId) {
this.mediaAll[playerId] = {};
};
this.removeAll = function () {
this.mediaAll = {};
};
};
// Local object to manage all media.
var mediaObject = new Media();
/**
* Manage Timeout Object.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @private
*/
var Timeout = function () {
this.timeout = {};
this.setTimeout = function (playerId, mediaLabel, refreshValue) {
this.timeout[playerId] = this.timeout[playerId] || {};
if (this.timeout[playerId][mediaLabel]) {
window.clearTimeout(this.timeout[playerId][mediaLabel]);
}
this.timeout[playerId][mediaLabel] = window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: playerId, mediaLabel: mediaLabel});
}, refreshValue * 1e3);
// Example of generated object
/* this.timeout[playerId][mediaLabel] = window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
}, 5 * 1e3); */
};
this.setTimeoutObject = function (playerId, mediaLabel, refreshObject) {
this.timeout[playerId] = this.timeout[playerId] || {};
if (typeof this.timeout[playerId][mediaLabel] === 'undefined') {
var refreshTab = [];
for (var val in refreshObject) {
if (refreshObject.hasOwnProperty(val)) {
refreshTab.push({
delay: _filterValue(val, 0),
refresh: _filterValue(refreshObject[val], 5)
});
}
}
refreshTab.sort(function (a, b) {
if (a.delay < b.delay) {
return -1;
}
if (a.delay > b.delay) {
return 1;
}
return 0;
});
this.timeout[playerId][mediaLabel] = {
refreshTab: refreshTab,
backupRefreshTab: ATInternet.Utils.cloneSimpleObject(refreshTab),
delayConfiguration: {}
};
}
// Process refresh objects
var timeout = this.timeout[playerId][mediaLabel];
if (timeout.refreshTab.length > 0) {
var delay = timeout.refreshTab[0].delay;
var refresh = timeout.refreshTab[0].refresh;
if ((typeof delay === 'number') && (typeof refresh === 'number') && (refresh > 0)) {
timeout.delayConfiguration[delay] = timeout.delayConfiguration[delay] || {};
// Get next delay
var nextDelay = undefined;
if (typeof timeout.refreshTab[1] !== 'undefined') {
nextDelay = timeout.refreshTab[1].delay;
}
//Get the number of remaining sendings for the current delay
var number = 0;
if (typeof nextDelay === 'undefined') {
number = 1;
}
else if (typeof timeout.delayConfiguration[delay].number === 'number') {
var action = mediaObject.getMediaValue(playerId, mediaLabel, 'a');
if (action === 'refresh') {
number = Math.max(timeout.delayConfiguration[delay].number - 1, 0);
}
else {
number = timeout.delayConfiguration[delay].number;
}
}
else if (typeof nextDelay === 'number') {
number = Math.floor((nextDelay - delay) * 60 / refresh) - 1;
}
timeout.delayConfiguration[delay].number = number;
//Send refresh hits and manage window timeout
if (timeout.delayConfiguration[delay].timeout) {
window.clearTimeout(timeout.delayConfiguration[delay].timeout);
}
if (number > 0) {
timeout.delayConfiguration[delay].timeout = window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: playerId, mediaLabel: mediaLabel});
}, refresh * 1e3);
}
else {
timeout.delayConfiguration[delay].number = undefined;
timeout.delayConfiguration[delay].timeout = undefined;
timeout.refreshTab.splice(0, 1);
window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: playerId, mediaLabel: mediaLabel});
}, refresh * 1e3);
}
this.timeout[playerId][mediaLabel] = timeout;
// Example of final generated object
/* this.timeout[playerId][mediaLabel] = {
refreshTab: [
{delay: 0, refresh: 5},
{delay: 1, refresh: 15},
{delay: 5, refresh: 60},
],
backupRefreshTab: [
{delay: 0, refresh: 5},
{delay: 1, refresh: 15},
{delay: 5, refresh: 60},
],
delayConfiguration: {
0: {
number: 11,
timeout: window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
}, 5 * 1e3)
}
}
}; */
}
}
};
this.clearTimeout = function (playerId, mediaLabel, resetDelay) {
this.timeout[playerId] = this.timeout[playerId] || {};
var timeout = this.timeout[playerId][mediaLabel];
if (typeof timeout === 'object') {
if (typeof timeout.delayConfiguration === 'object') {
var number;
for (var delay in timeout.delayConfiguration) {
if (timeout.delayConfiguration.hasOwnProperty(delay)) {
number = timeout.delayConfiguration[delay].number;
if (typeof number !== 'undefined' && number > 0) {
if (timeout.delayConfiguration[delay].timeout) {
window.clearTimeout(timeout.delayConfiguration[delay].timeout);
}
timeout.delayConfiguration[delay].timeout = undefined;
}
}
}
if (resetDelay) {
timeout.refreshTab = ATInternet.Utils.cloneSimpleObject(timeout.backupRefreshTab);
}
this.timeout[playerId][mediaLabel] = timeout;
}
}
else if (timeout) {
window.clearTimeout(timeout);
}
};
this.removePlayer = function (playerId) {
for (var mediaLabel in this.timeout[playerId]) {
if (this.timeout[playerId].hasOwnProperty(mediaLabel)) {
this.clearTimeout(playerId, mediaLabel, false);
var action = mediaObject.getMediaValue(playerId, mediaLabel, 'a');
if (typeof this.timeout[playerId][mediaLabel] !== 'undefined' && action !== 'stop') {
parent.richMedia.send({action: "stop", playerId: playerId, mediaLabel: mediaLabel});
}
}
}
this.timeout[playerId] = {};
};
this.removeAll = function () {
for (var playerId in this.timeout) {
if (this.timeout.hasOwnProperty(playerId)) {
this.removePlayer(playerId);
}
}
this.timeout = {};
};
};
// Local object to manage timers.
var timeoutObject = new Timeout();
/**
* 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) {
return parent.utils.manageChapters(tagObject, type, 3) + (tagObject[label] ? tagObject[label] : '');
};
/**
* 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 = tagObject[key];
if (typeof tagObject[key] === 'boolean') {
if (tagObject[key]) {
val = value;
}
else {
val = defaultValue;
}
}
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;
};
/**
* Set buffer value with media data.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @param buffer {object} object containing properties to use
* @param playerId {number} Player ID
* @param mediaLabel {string} media label
* @param param {string} Name of the parameter
* @param encode {boolean} Encode value if true
* @private
*/
var _setBufferParamFromMediaObject = function (buffer, playerId, mediaLabel, param, encode) {
var value = mediaObject.getMediaValue(playerId, mediaLabel, param);
if (typeof value !== 'undefined') {
buffer[param] = encode ? encodeURIComponent(value) : value;
}
};
/**
* Set buffer value with tag data.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @param buffer {object} object containing properties to use
* @param param {string} Name of the parameter
* @param value {string|number} Tag value
* @private
*/
var _setBufferParamFromTagObject = function (buffer, param, value) {
if (typeof value !== 'undefined') {
buffer[param] = value;
}
};
/**
* [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,
* linkedContent, refreshDuration, duration, isEmbedded, broadcastMode, webdomain
* @example
* <pre><code class="javascript">tag.richMedia.add({
* mediaType: "video",
* playerId: 333,
* mediaLevel2: "mediaLevel2",
* mediaLabel: "mediaLabel",
* linkedContent: "linkedContent",
* refreshDuration: 5,
* duration: 20,
* isEmbedded: true,
* broadcastMode: "clip",
* webdomain: "http://www.atinternet.com"
* });
* </code></pre>
* @public
*/
parent.richMedia.add = function (tagObject) {
tagObject = tagObject || {};
var playerId = _filterPlyrId(tagObject['playerId']);
var mediaLabel = _getFullName(tagObject, 'mediaTheme', 'mediaLabel');
var isEmbedded = _setBoolean(tagObject, 'isEmbedded', 'int', 'ext');
// Complete media object with tag data
mediaObject.setMediaValue(playerId, mediaLabel, 'plyr', playerId);
mediaObject.setMediaValue(playerId, mediaLabel, 'type', tagObject.mediaType);
mediaObject.setMediaValue(playerId, mediaLabel, 's2', tagObject.mediaLevel2);
mediaObject.setMediaValue(playerId, mediaLabel, 'p', mediaLabel);
// We keep 'previousMedia' property for legacy purpose
mediaObject.setMediaValue(playerId, mediaLabel, 'clnk', tagObject.linkedContent || tagObject.previousMedia);
mediaObject.setMediaValue(playerId, mediaLabel, 'a', tagObject.action);
mediaObject.setMediaValue(playerId, mediaLabel, 'rfsh', tagObject.refreshDuration);
mediaObject.setMediaValue(playerId, mediaLabel, 'm1', tagObject.duration);
mediaObject.setMediaValue(playerId, mediaLabel, 'm5', isEmbedded);
mediaObject.setMediaValue(playerId, mediaLabel, 'm6', tagObject.broadcastMode);
mediaObject.setMediaValue(playerId, mediaLabel, 'm9', tagObject.webdomain);
/* @if debug */
parent.debug('RichMedia:richMedia:add', _debug.level, _debug.messageEnd, {
player: playerId,
media: mediaObject,
tagData: tagObject
});
/* @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 = function (tagObject) {
tagObject = tagObject || {};
var playerId = _filterPlyrId(tagObject.playerId);
var mediaLabel = _getFullName(tagObject, 'mediaTheme', 'mediaLabel');
var action = tagObject.action;
// Update media action
mediaObject.setMediaValue(playerId, mediaLabel, 'a', action);
// Complete buffer object with tag data
var buffer = {
'plyr': playerId,
'p': mediaLabel
};
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 'a', false);
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 'type', false);
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 's2', false);
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 'm1', false);
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 'm5', false);
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 'm6', false);
// Manage additional parameters for actions 'play' or 'info'
if ((action === 'play') || (action === 'info')) {
var buf = _setBoolean(tagObject, 'isBuffering', '0', '1');
var contextPageObject = parent.getContext('page') || {};
var prich = _getFullName(contextPageObject, 'chapter', 'name') || undefined;
var s2rich = contextPageObject.level2 || undefined;
_setBufferParamFromTagObject(buffer, 'buf', buf);
_setBufferParamFromTagObject(buffer, 'prich', prich);
_setBufferParamFromTagObject(buffer, 's2rich', s2rich);
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 'clnk', false);
_setBufferParamFromMediaObject(buffer, playerId, mediaLabel, 'm9', true);
}
// Send hit
parent.sendHit(buffer, [['hitType', ['richmedia']]], null, null, null);
// Manage timeout clearing for actions 'pause' or 'stop'
if (action === 'pause') {
timeoutObject.clearTimeout(playerId, mediaLabel, false);
} else if (action === 'stop') {
timeoutObject.clearTimeout(playerId, mediaLabel, true);
}
// Manage refresh value
if ((action === 'play') || (action === 'refresh')) {
var refreshValue = mediaObject.getMediaValue(playerId, mediaLabel, 'rfsh');
if (typeof refreshValue === 'object' && refreshValue !== null) {
timeoutObject.setTimeoutObject(playerId, mediaLabel, refreshValue);
} else {
refreshValue = _filterValue(refreshValue, 5);
if (refreshValue !== 0) {
timeoutObject.setTimeout(playerId, mediaLabel, refreshValue);
}
}
}
/* @if debug */
if (action === 'info' && (typeof tagObject.isBuffering !== 'boolean')) {
parent.debug('RichMedia:richMedia:send:Error', 'WARNING', '"isBuffering" parameter is mandatory for "info"-type actions, please add it to "tag.richMedia.send()" method with correct format', {
action: action,
isBuffering: tagObject.isBuffering
});
}
var mediaType = mediaObject.getMediaValue(playerId, mediaLabel, 'type');
var broadcastMode = mediaObject.getMediaValue(playerId, mediaLabel, 'm6');
var duration = mediaObject.getMediaValue(playerId, mediaLabel, 'm1');
if ((typeof mediaType === 'undefined') || (typeof broadcastMode === 'undefined') || (broadcastMode === 'clip' && (typeof duration === 'undefined'))) {
parent.debug('RichMedia:richMedia:send:Error', 'WARNING', 'Some required parameters are missing, please use "tag.richMedia.add()" method to set', {
mediaType: mediaType,
broadcastMode: broadcastMode,
duration: duration
});
}
parent.debug('RichMedia:richMedia:send', _debug.level, _debug.messageEnd, {
player: playerId,
media: mediaObject,
buffer: buffer,
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 playerId {number} Player ID
* @example
* <pre><code class="javascript">tag.richMedia.remove(333);
* </code></pre>
* @public
*/
parent.richMedia.remove = function (playerId) {
timeoutObject.removePlayer(playerId);
mediaObject.removePlayer(playerId);
/* @if debug */
parent.debug('RichMedia:richMedia:remove', _debug.level, _debug.messageEnd, {playerId: playerId, 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 = function () {
timeoutObject.removeAll();
mediaObject.removeAll();
/* @if debug */
parent.debug('RichMedia:richMedia:removeAll', _debug.level, _debug.messageEnd, {media: mediaObject});
/* @endif */
};
/* @if test */
self._filterValue = _filterValue;
self.Timeout = Timeout;
self.Media = Media;
self._getFullName = _getFullName;
self._setBoolean = _setBoolean;
self._filterPlyrId = _filterPlyrId;
self._setBufferParamFromMediaObject = _setBufferParamFromMediaObject;
self._setBufferParamFromTagObject = _setBufferParamFromTagObject;
/* @endif */
};
window['ATInternet']['Tracker']['addPlugin']('RichMedia');