(function() {
/**
* Meta object for GreenView.
* @typedef {Object} Meta
* @property {Object} device
* @property {string} device.userAgent? The web browser User agent string.
* @property {string} device.manufacturer? Manufacturer of the device, e.g. `Sony`.
* @property {string} device.model? Model name of the device.
* @property {string} device.type? Type of device, i.e. `tv`, `desktop`, `mobile`, `stb`.
* @property {Object} device.screen? Describes the screen of the device.
* @property {string} device.screen.size? Size in inches.
* @property {string} device.screen.resolution? Used resolution, e.g. `1920x1280`.
* @property {string} device.screen.type? Type of display, i.e. `amoled`, `lcd`, `lcdled`, `qled`.
*/
/**
* Content object for GreenView.
* @typedef {Object} Content
* @property {string} title? Title for given content.
* @property {string} url? URL for given content.
* @property {string} type? Type of content, e.g. `sports` or `movie`.
* @property {number} duration? Duration in seconds.
* @property {string} characteristics? Comma separated "tags", e.g. `dark, slow` or `bright, action`.
* @property {string} playback? Set as `vod` or `live`.
*/
/**
* GreenView constructor.
* @typedef {Object} GreenView
* @class
* @classdesc GreenView class.
* @param {Object} player? Reference to video HTML object or JavaScript player object.
* @param {Meta} meta? Device related details.
*/
function GreenView(player, meta) {
var PLAYER_HTML5 = 1;
var PLAYER_BITMOVIN = 2;
var PLAYER_DASH = 3;
var CSS_ID = 'greenviewcss';
var LAYER_ID = 'greenviewLayer';
var __playerType = PLAYER_HTML5;
var __opacity;
var __opacityManual;
var __callbackUseGreenView;
var __opacityEco;
var __callbackUseGreenViewEco;
var __content;
var __useExternalDiv = false;
var __externalDiv;
var __internal_setOpacity = function(isEco) {
var opacity = isEco ? __opacityEco : __opacity;
if (__opacityManual !== undefined) {
opacity = __opacityManual;
}
if (__useExternalDiv) {
__internal_setOpacity_external(__externalDiv, opacity);
return;
}
switch(__playerType) {
case PLAYER_BITMOVIN:
__internal_setOpacity_bitmovin(opacity);
break;
case PLAYER_DASH:
__internal_setOpacity_common(document.querySelector('video').parentElement, opacity);
break;
case PLAYER_HTML5:
__internal_setOpacity_common(document.body, opacity);
break;
}
};
var __internal_setOpacity_bitmovin = function(opacity) {
var styles = '.bmpui-ui-uicontainer { background: #000000 !important; opacity: ' + opacity + ' !important; }';
var old = document.getElementById(CSS_ID);
if (old) {
old.parentNode.removeChild(old);
}
var css = document.createElement('style');
css.type = 'text/css';
css.id = CSS_ID;
if (css.styleSheet) {
css.styleSheet.cssText = styles;
} else {
css.appendChild(document.createTextNode(styles));
}
document.getElementsByTagName('head')[0].appendChild(css);
};
var __internal_setOpacity_external = function(layer, opacity) {
if (!layer) return;
layer.setAttribute('style', 'display: block; background: #000000; opacity: ' + opacity + ';');
};
var __internal_setOpacity_common = function(parentElement, opacity) {
var layer = document.getElementById(LAYER_ID);
var isNewLayer = false;
if (!layer) {
layer = document.createElement('div');
layer.id = LAYER_ID;
isNewLayer = true;
}
layer.setAttribute('style', 'display: block; position: absolute; width: 100%; height: 100%; top: 0; left: 0; margin: 0px; background: #000000; z-index: 1000; opacity: ' + opacity + '; pointer-events: none;');
if (isNewLayer) {
parentElement.appendChild(layer);
}
};
var __internal_removeOpacity = function() {
var style = document.getElementById(CSS_ID);
if (style) {
style.parentNode.removeChild(style);
}
var layer = document.getElementById(LAYER_ID);
if (layer) {
layer.setAttribute('style', 'display: none');
}
if (__useExternalDiv) {
__externalDiv.setAttribute('style', 'display: none');
}
};
var __internal_send = function(isEco) {
var query = '';
if (__content) {
var keys = Object.keys(__content);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
query += key + '=' + encodeURIComponent(__content[key]);
if (i - 1 == keys.length) continue;
query += '&';
}
}
var protocol = document.location.protocol || 'http:';
var req = new XMLHttpRequest();
req.addEventListener('load', listener.bind(req, isEco));
req.open('GET', protocol + '//<%= host %>/v1/api/brightness?' + query);
req.send();
};
var listener = function(isEco) {
var resp = JSON.parse(this.responseText);
__opacity = parseInt(resp.opacity, 10) / 100;
__opacityEco = parseInt(resp.opacityEco, 10) / 100;
__internal_setOpacity(isEco);
if (__callbackUseGreenView) {
if (__callbackUseGreenView.call) __callbackUseGreenView();
__callbackUseGreenView = undefined;
return;
}
if (__callbackUseGreenViewEco) {
if (__callbackUseGreenViewEco.call) __callbackUseGreenViewEco();
__callbackUseGreenViewEco = undefined;
return;
}
};
/**
* Allows to provide a custom DOM `<div>` node element that brightness will be set on.
*
* This `<div>` should be positioned in responsability outside of GreenView. GreenView
* will apply brightness settings to this element only.
*
* Calling this function as `setElementLayer(null)` will tell GreenView to set
* brightness internally again instead. GreenView will not remove the element itself.
*
* @param div {Node} The div node element that GreenView will use.
* @name setElementLayer
* @function
* @memberof GreenView.prototype
*/
this.setElementLayer = function(div) {
if (div) {
__useExternalDiv = true;
__externalDiv = div;
} else {
__useExternalDiv = false;
__externalDiv = undefined;
}
};
/**
* Controls status of GreenView mode.
*
* Will apply a fullscreen layer with default opacity.
* @param enable {boolean} Enable or disable GreenView mode.
* @param [cb] {Function} Callback.
* @name useGreenView
* @function
* @memberof GreenView.prototype
*/
this.useGreenView = function(enable, cb) {
if (typeof enable === 'boolean' && !enable) {
__internal_removeOpacity();
if (cb && cb.call) {
cb();
}
return;
}
if (__opacity !== undefined) {
__internal_setOpacity();
if (cb && cb.call) {
cb();
}
return;
}
__callbackUseGreenView = cb;
__internal_send('');
};
/**
* Controls status of GreenView "Eco" mode.
*
* Will apply a fullscreen layer with opacity for "Eco" mode.
* @param enable {boolean} Enable or disable GreenView "Eco" mode.
* @param [cb] {Function} Callback.
* @name useGreenViewEco
* @function
* @memberof GreenView.prototype
*/
this.useGreenViewEco = function(enable, cb) {
if (typeof enable === 'boolean' && !enable) {
__internal_removeOpacity();
if (cb && cb.call) {
cb();
}
return;
}
if (__opacityEco !== undefined) {
__internal_setOpacity(enable);
if (cb && cb.call) {
cb();
}
return;
}
__callbackUseGreenViewEco = cb;
__internal_send(enable);
};
/**
* Let GreenView know what content is used for playback.
*
* This method is optional.
*
* @param {Content} content
* @name describeContent
* @function
* @memberof GreenView.prototype
*/
this.describeContent = function(content) {
__opacity = undefined;
__opacityManual = undefined;
__opacityEco = undefined;
__content = content;
};
/**
* Will apply a fullscreen layer with the provided opacity percentage.
*
* Use carefully as it will override the default opacity value.
* @param opacity {number} A percentage number value.
* @name setOpacity
* @function
* @memberof GreenView.prototype
*/
this.setOpacity = function(opacity) {
__opacityManual = opacity / 100;
__internal_setOpacity();
};
this.getOpacity = function() {
return __opacity * 100;
};
if (player && player.__proto__) {
var proto = player.__proto__;
if (proto.version && proto.getConfig && proto.getPlayerType) {
__playerType = PLAYER_BITMOVIN;
} else if (player.initialize && player.attachView && player.setProtectionData) {
__playerType = PLAYER_DASH;
}
}
}
window.GreenView = GreenView;
})();