UNPKG

videojs-contrib-ads

Version:

A framework that provides common functionality needed by video advertisement libraries working with video.js.

112 lines (91 loc) 3.88 kB
/* This feature provides an optional method for ad integrations to insert run-time values into an ad server URL or configuration. */ import videojs from 'video.js'; // Return URI encoded version of value if uriEncode is true const uriEncodeIfNeeded = function(value, uriEncode) { if (uriEncode) { return encodeURIComponent(value); } return value; } // Add custom field macros to macros object // based on given name for custom fields property of mediainfo object. const customFields = function(mediainfo, macros, customFieldsName) { if (mediainfo && mediainfo[customFieldsName]) { let customFields = mediainfo[customFieldsName]; let fieldNames = Object.keys(customFields); for (let i = 0; i < fieldNames.length; i++) { const tag = '{mediainfo.' + customFieldsName + '.' + fieldNames[i] + '}'; macros[tag] = customFields[fieldNames[i]]; } } } // Public method that integrations use for ad macros. // "string" is any string with macros to be replaced // "uriEncode" if true will uri encode macro values when replaced // "customMacros" is a object with custom macros and values to map them to // - For example: {'{five}': 5} // Return value is is "string" with macros replaced // - For example: adMacroReplacement('{player.id}') returns a string of the player id const adMacroReplacement = function(string, uriEncode, customMacros) { if (uriEncode === undefined) { uriEncode = false; } let macros = {}; if (customMacros !== undefined) { macros = customMacros; } // Static macros macros['{player.id}'] = this.options_['data-player']; macros['{mediainfo.id}'] = this.mediainfo ? this.mediainfo.id : ''; macros['{mediainfo.name}'] = this.mediainfo ? this.mediainfo.name : ''; macros['{mediainfo.description}'] = this.mediainfo ? this.mediainfo.description : ''; macros['{mediainfo.tags}'] = this.mediainfo ? this.mediainfo.tags : ''; macros['{mediainfo.reference_id}'] = this.mediainfo ? this.mediainfo.reference_id : ''; macros['{mediainfo.duration}'] = this.mediainfo ? this.mediainfo.duration : ''; macros['{mediainfo.ad_keys}'] = this.mediainfo ? this.mediainfo.ad_keys : ''; macros['{player.duration}'] = this.duration(); macros['{timestamp}'] = new Date().getTime(); macros['{document.referrer}'] = document.referrer; macros['{window.location.href}'] = window.location.href; macros['{random}'] = Math.floor(Math.random() * 1000000000000); // Custom fields in mediainfo customFields(this.mediainfo, macros, 'custom_fields'); customFields(this.mediainfo, macros, 'customFields'); // Go through all the replacement macros and apply them to the string. // This will replace all occurrences of the replacement macros. for (let i in macros) { string = string.split(i).join(uriEncodeIfNeeded(macros[i], uriEncode)); } // Page variables string = string.replace(/{pageVariable\.([^}]+)}/g, function(match, name) { let value; let context = window; let names = name.split('.'); // Iterate down multiple levels of selector without using eval // This makes things like pageVariable.foo.bar work for (let i = 0; i < names.length; i++) { if (i === names.length - 1) { value = context[names[i]]; } else { context = context[names[i]]; } } const type = typeof value; // Only allow certain types of values. Anything else is probably a mistake. if (value === null) { return 'null'; } else if (value === undefined) { videojs.log.warn(`Page variable "${name}" not found`); return ''; } else if (type !== 'string' && type !== 'number' && type !== 'boolean') { videojs.log.warn(`Page variable "${name}" is not a supported type`); return ''; } return uriEncodeIfNeeded(String(value), uriEncode); }); return string; } module.exports = adMacroReplacement;