/**
* @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 () {
//Default timeout object
this._timeout = {};
//Set timeout for single refresh value
/*tag.richMedia.add({
...
refreshDuration: 5,
...
});*/
this.setTimeout = function (plyr, key, rfsh) {
this._timeout[plyr] = this._timeout[plyr] || {};
window.clearTimeout(this._timeout[plyr][key]);
this._timeout[plyr][key] = window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
}, rfsh * 1e3);
};
//Set timeout for refresh object
/*tag.richMedia.add({
...
refreshDuration: {
0: 5,
1: 15,
5: 60
},
...
});*/
this.setTimeoutObject = function (plyr, key, rfshObj, action) {
// Init timeout object
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,
arrObjSave: ATInternet.Utils.cloneSimpleObject(arrObj)
};
}
//Example of generated object
/*this._timeout[plyr][key] = {
arrObj: [
{delay: 0, refresh: 5},
{delay: 1, refresh: 15},
{delay: 5, refresh: 60},
],
arrObjSave: [
{delay: 0, refresh: 5},
{delay: 1, refresh: 15},
{delay: 5, refresh: 60},
]
}; */
// Process delay objects
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;
}
//Get the number of remaining sends for the current delay
var num = 0;
if (typeof nextDelay === 'undefined') {
num = 1;
}
else if (typeof currentTimeout[currentDelay].num === 'number') {
if (action === 'refresh') {
num = Math.max(currentTimeout[currentDelay].num - 1, 0);
}
else {
num = currentTimeout[currentDelay].num;
}
}
else if (typeof nextDelay === 'number') {
num = Math.floor((nextDelay - currentDelay) * 60 / currentRfsh) - 1;
}
currentTimeout[currentDelay].num = num;
//Send refresh hits and manage window timeout
window.clearTimeout(currentTimeout[currentDelay].timeout);
if (num > 0) {
currentTimeout[currentDelay].timeout = window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
}, currentRfsh * 1e3);
}
else {
currentTimeout[currentDelay].num = undefined;
currentTimeout[currentDelay].timeout = undefined;
currentTimeout.arrObj.splice(0, 1);
window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
}, currentRfsh * 1e3);
}
//Example of final generated currentTimeout object
/*currentTimeout = {
arrObj: [
{delay: 0, refresh: 5},
{delay: 1, refresh: 15},
{delay: 5, refresh: 60},
],
arrObjSave: [
{delay: 0, refresh: 5},
{delay: 1, refresh: 15},
{delay: 5, refresh: 60},
]
0: {
num: 11,
timeout: window.setTimeout(function () {
parent.richMedia.send({action: 'refresh', playerId: plyr, mediaLabel: key});
}, 5 * 1e3)
}
}; */
this._timeout[plyr][key] = currentTimeout;
}
}
};
this.clearTimeout = function (plyr, key, reinitDelay) {
this._timeout[plyr] = this._timeout[plyr] || {};
//For refresh object
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;
}
}
}
if (reinitDelay) {
this._timeout[plyr][key].arrObj = ATInternet.Utils.cloneSimpleObject(this._timeout[plyr][key].arrObjSave);
}
}
//For single refresh value
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, false);
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 = 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.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 undefined;
};
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 = 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;
};
/**
* 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;
};
/**
* Set buffer value with media data.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @param buffer {object} object containing properties to use
* @param plyr {number} Player ID
* @param media {string} media label
* @param key {string} Name of the tag property
* @param encode {boolean} Encode value if true
* @private
*/
var _setBufferPropertyFromMedia = function (buffer, plyr, media, key, encode) {
var property = mediaObject.getMediaProperty(plyr, media, key);
if (typeof property !== 'undefined') {
buffer[key] = encode ? encodeURIComponent(property) : property;
}
};
/**
* Set buffer value with tag data.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @param buffer {object} object containing properties to use
* @param key {string} Name of the tag property
* @param value {string|number} Tag value
* @private
*/
var _setBufferPropertyFromTag = function (buffer, key, value) {
if (typeof value !== 'undefined') {
buffer[key] = value;
}
};
/**
* Set media properties.
* @memberof ATInternet.Tracker.Plugins.RichMedia#
* @function
* @param plyr {number} Player ID
* @param media {string} media label
* @param key {string} Name of the tag property
* @param value {string|object|number} Tag value
* @private
*/
var _setMediaProperty = function (plyr, media, key, value) {
if (typeof value !== 'undefined') {
mediaObject.setMediaProperty(plyr, media, key, 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'] = _this['add'] = function (tagObject) {
tagObject = tagObject || {};
var plyr = _filterPlyrId(tagObject['playerId']);
var media = _getFullName(tagObject, 'mediaTheme', 'mediaLabel');
var isEmb = _setBoolean(tagObject, 'isEmbedded', 'int', 'ext');
_setMediaProperty(plyr, media, 'plyr', plyr);
_setMediaProperty(plyr, media, 'type', tagObject['mediaType']);
_setMediaProperty(plyr, media, 's2', tagObject['mediaLevel2']);
_setMediaProperty(plyr, media, 'p', media);
// We keep 'previousMedia' property for legacy purpose
_setMediaProperty(plyr, media, 'clnk', tagObject['linkedContent'] || tagObject['previousMedia']);
_setMediaProperty(plyr, media, 'a', tagObject['action']);
_setMediaProperty(plyr, media, 'rfsh', tagObject['refreshDuration']);
_setMediaProperty(plyr, media, 'm1', tagObject['duration']);
_setMediaProperty(plyr, media, 'm5', isEmb);
_setMediaProperty(plyr, media, 'm6', tagObject['broadcastMode']);
_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 = {};
buffer['plyr'] = plyr;
buffer['p'] = media;
if (tagObject['action']) {
buffer['a'] = tagObject['action'];
}
_setBufferPropertyFromMedia(buffer, plyr, media, 'type', false);
_setBufferPropertyFromMedia(buffer, plyr, media, 's2', false);
_setBufferPropertyFromMedia(buffer, plyr, media, 'm1', false);
_setBufferPropertyFromMedia(buffer, plyr, media, 'm5', false);
_setBufferPropertyFromMedia(buffer, plyr, media, 'm6', false);
if ((buffer.a === 'play') || (buffer.a === 'info')) {
var _isBuffering = _setBoolean(tagObject, 'isBuffering', '0', '1');
_setBufferPropertyFromTag(buffer, 'buf', _isBuffering);
var contextPageObject = parent['getContext']('page') || {};
var _prich = _getFullName(contextPageObject, 'chapter', 'name') || undefined;
_setBufferPropertyFromTag(buffer, 'prich', _prich);
var _s2rich = contextPageObject['level2'] || undefined;
_setBufferPropertyFromTag(buffer, 's2rich', _s2rich);
_setBufferPropertyFromMedia(buffer, plyr, media, 'clnk', false);
_setBufferPropertyFromMedia(buffer, plyr, media, 'm9', true);
}
parent.sendHit(buffer, [['hitType', ['richmedia']]]);
if (buffer.a === 'pause') {
timeoutObject.clearTimeout(plyr, media, false);
} else if (buffer.a === 'stop') {
timeoutObject.clearTimeout(plyr, media, true);
}
if ((buffer.a === 'play') || (buffer.a === 'refresh')) {
var refreshValue = mediaObject.getMediaProperty(plyr, media, 'rfsh');
if (typeof refreshValue === 'object') {
timeoutObject.setTimeoutObject(plyr, media, refreshValue, buffer.a);
} else {
var rfsh = _filterValue(refreshValue, 5);
if (rfsh !== 0) {
timeoutObject.setTimeout(plyr, media, rfsh);
}
}
}
/* @if debug */
if (buffer.a === 'info' && !buffer['buf']) {
parent.debug('RichMedia:richMedia:send:Error', 'WARNING', '"isBuffering" parameter is mandatory for "info"-type actions, please add it to "tag.richMedia.send()" method', {
action: buffer.a,
isBuffering: buffer['buf']
});
}
if (!buffer['type'] || !buffer['m6'] || (buffer['m6'] === 'clip' && !buffer['m1'])) {
parent.debug('RichMedia:richMedia:send:Error', 'WARNING', 'Some required parameters are missing, please use "tag.richMedia.add()" method to set', {
mediaType: buffer['type'],
broadcastMode: buffer['m6'],
duration: buffer['m1']
});
}
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');