videojs-errors
Version:
A VideoJS plugin for custom error reporting
253 lines (213 loc) • 8.01 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', {
value: true
});
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var _videoJs = require('video.js');
var _videoJs2 = _interopRequireDefault(_videoJs);
var _globalWindow = require('global/window');
var _globalWindow2 = _interopRequireDefault(_globalWindow);
var _globalDocument = require('global/document');
var _globalDocument2 = _interopRequireDefault(_globalDocument);
var FlashObj = _videoJs2['default'].getComponent('Flash');
// Default options for the plugin.
var defaults = {
header: '',
code: '',
message: '',
timeout: 45 * 1000,
errors: {
'1': {
type: 'MEDIA_ERR_ABORTED',
headline: 'The video download was cancelled'
},
'2': {
type: 'MEDIA_ERR_NETWORK',
headline: 'The video connection was lost, please confirm you are ' + 'connected to the internet'
},
'3': {
type: 'MEDIA_ERR_DECODE',
headline: 'The video is bad or in a format that cannot be played on your browser'
},
'4': {
type: 'MEDIA_ERR_SRC_NOT_SUPPORTED',
headline: 'This video is either unavailable or not supported in this browser'
},
'5': {
type: 'MEDIA_ERR_ENCRYPTED',
headline: 'The video you are trying to watch is encrypted and we do not know how ' + 'to decrypt it'
},
'unknown': {
type: 'MEDIA_ERR_UNKNOWN',
headline: 'An unanticipated problem was encountered, check back soon and try again'
},
'-1': {
type: 'PLAYER_ERR_NO_SRC',
headline: 'No video has been loaded'
},
'-2': {
type: 'PLAYER_ERR_TIMEOUT',
headline: 'Could not download the video'
}
}
};
/**
* Monitors a player for signs of life during playback and
* triggers PLAYER_ERR_TIMEOUT if none occur within a reasonable
* timeframe.
*/
var initPlugin = function initPlugin(player, options) {
var monitor = undefined;
var listeners = [];
// clears the previous monitor timeout and sets up a new one
var resetMonitor = function resetMonitor() {
_globalWindow2['default'].clearTimeout(monitor);
monitor = _globalWindow2['default'].setTimeout(function () {
// player already has an error
// or is not playing under normal conditions
if (player.error() || player.paused() || player.ended()) {
return;
}
player.error({
code: -2,
type: 'PLAYER_ERR_TIMEOUT'
});
}, options.timeout);
// clear out any existing player timeout
// playback has recovered
if (player.error() && player.error().code === -2) {
player.error(null);
}
};
// clear any previously registered listeners
var cleanup = function cleanup() {
var listener = undefined;
while (listeners.length) {
listener = listeners.shift();
player.off(listener[0], listener[1]);
}
_globalWindow2['default'].clearTimeout(monitor);
};
// creates and tracks a player listener if the player looks alive
var healthcheck = function healthcheck(type, fn) {
var check = function check() {
// if there's an error do not reset the monitor and
// clear the error unless time is progressing
if (!player.error()) {
// error if using Flash and its API is unavailable
var tech = player.$('.vjs-tech');
if (tech && tech.type === 'application/x-shockwave-flash' && !tech.vjs_getProperty) {
player.error({
code: -2,
type: 'PLAYER_ERR_TIMEOUT'
});
return;
}
// playback isn't expected if the player is paused
if (player.paused()) {
return resetMonitor();
}
// playback isn't expected once the video has ended
if (player.ended()) {
return resetMonitor();
}
}
fn.call(this);
};
player.on(type, check);
listeners.push([type, check]);
};
var onPlayStartMonitor = function onPlayStartMonitor() {
var lastTime = 0;
cleanup();
// if no playback is detected for long enough, trigger a timeout error
resetMonitor();
healthcheck(['timeupdate', 'adtimeupdate'], function () {
var currentTime = player.currentTime();
// playback is operating normally or has recovered
if (currentTime !== lastTime) {
lastTime = currentTime;
resetMonitor();
}
});
healthcheck('progress', resetMonitor);
};
var onPlayNoSource = function onPlayNoSource() {
if (!player.currentSrc()) {
player.error({
code: -1,
type: 'PLAYER_ERR_NO_SRC'
});
}
};
var onErrorHandler = function onErrorHandler() {
var display = undefined;
var details = '';
var error = player.error();
var content = _globalDocument2['default'].createElement('div');
// In the rare case when `error()` does not return an error object,
// defensively escape the handler function.
if (!error) {
return;
}
error = _videoJs2['default'].mergeOptions(error, options.errors[error.code || 0]);
if (error.message) {
details = '<div class="vjs-errors-details">' + player.localize('Technical details') + '\n : <div class="vjs-errors-message">' + player.localize(error.message) + '</div>\n </div>';
}
if (error.code === 4 && !FlashObj.isSupported()) {
var flashMessage = player.localize(' * If you are using an older browser' + ' please try upgrading or installing Flash.');
details += '<span class="vjs-errors-flashmessage">' + flashMessage + '</span>';
}
display = player.getChild('errorDisplay');
// The code snippet below is to make sure we dispose any child closeButtons before
// making the display closeable
if (display.getChild('closeButton')) {
display.removeChild('closeButton');
}
// Make the error display closeable, and we should get a close button
display.closeable(true);
content.className = 'vjs-errors-dialog';
content.id = 'vjs-errors-dialog';
content.innerHTML = '<div class="vjs-errors-content-container">\n <h2 class="vjs-errors-headline">' + this.localize(error.headline) + '</h2>\n <div><b>' + this.localize('Error Code') + '</b>: ' + (error.type || error.code) + '</div>\n ' + details + '\n </div>\n <div class="vjs-errors-ok-button-container">\n <button class="vjs-errors-ok-button">' + this.localize('OK') + '</button>\n </div>';
display.fillWith(content);
// Get the close button inside the error display
display.contentEl().firstChild.appendChild(display.getChild('closeButton').el());
if (player.width() <= 600 || player.height() <= 250) {
display.addClass('vjs-xs');
}
var okButton = display.el().querySelector('.vjs-errors-ok-button');
_videoJs2['default'].on(okButton, 'click', function () {
display.close();
});
};
var onDisposeHandler = function onDisposeHandler() {
cleanup();
player.removeClass('vjs-errors');
player.off('play', onPlayStartMonitor);
player.off('play', onPlayNoSource);
player.off('dispose', onDisposeHandler);
player.off('error', onErrorHandler);
};
var reInitPlugin = function reInitPlugin(newOptions) {
onDisposeHandler();
initPlugin(player, _videoJs2['default'].mergeOptions(defaults, newOptions));
};
player.on('play', onPlayStartMonitor);
player.on('play', onPlayNoSource);
player.on('dispose', onDisposeHandler);
player.on('error', onErrorHandler);
player.ready(function () {
player.addClass('vjs-errors');
});
player.errors = reInitPlugin;
};
/**
* Initialize the plugin. Waits until the player is ready to do anything.
*/
var errors = function errors(options) {
initPlugin(this, _videoJs2['default'].mergeOptions(defaults, options));
};
// Register the plugin with video.js.
_videoJs2['default'].plugin('errors', errors);
exports['default'] = errors;
module.exports = exports['default'];