diff options
Diffstat (limited to 'javascript/videojs/src/js/plugin.js')
| -rw-r--r-- | javascript/videojs/src/js/plugin.js | 524 |
1 files changed, 0 insertions, 524 deletions
diff --git a/javascript/videojs/src/js/plugin.js b/javascript/videojs/src/js/plugin.js deleted file mode 100644 index 52ab6e7..0000000 --- a/javascript/videojs/src/js/plugin.js +++ /dev/null @@ -1,524 +0,0 @@ -/** - * @file plugin.js - */ -import evented from './mixins/evented'; -import stateful from './mixins/stateful'; -import * as Events from './utils/events'; -import log from './utils/log'; -import Player from './player'; - -/** - * The base plugin name. - * - * @private - * @constant - * @type {string} - */ -const BASE_PLUGIN_NAME = 'plugin'; - -/** - * The key on which a player's active plugins cache is stored. - * - * @private - * @constant - * @type {string} - */ -const PLUGIN_CACHE_KEY = 'activePlugins_'; - -/** - * Stores registered plugins in a private space. - * - * @private - * @type {Object} - */ -const pluginStorage = {}; - -/** - * Reports whether or not a plugin has been registered. - * - * @private - * @param {string} name - * The name of a plugin. - * - * @return {boolean} - * Whether or not the plugin has been registered. - */ -const pluginExists = (name) => pluginStorage.hasOwnProperty(name); - -/** - * Get a single registered plugin by name. - * - * @private - * @param {string} name - * The name of a plugin. - * - * @return {typeof Plugin|Function|undefined} - * The plugin (or undefined). - */ -const getPlugin = (name) => pluginExists(name) ? pluginStorage[name] : undefined; - -/** - * Marks a plugin as "active" on a player. - * - * Also, ensures that the player has an object for tracking active plugins. - * - * @private - * @param {Player} player - * A Video.js player instance. - * - * @param {string} name - * The name of a plugin. - */ -const markPluginAsActive = (player, name) => { - player[PLUGIN_CACHE_KEY] = player[PLUGIN_CACHE_KEY] || {}; - player[PLUGIN_CACHE_KEY][name] = true; -}; - -/** - * Triggers a pair of plugin setup events. - * - * @private - * @param {Player} player - * A Video.js player instance. - * - * @param {PluginEventHash} hash - * A plugin event hash. - * - * @param {boolean} [before] - * If true, prefixes the event name with "before". In other words, - * use this to trigger "beforepluginsetup" instead of "pluginsetup". - */ -const triggerSetupEvent = (player, hash, before) => { - const eventName = (before ? 'before' : '') + 'pluginsetup'; - - player.trigger(eventName, hash); - player.trigger(eventName + ':' + hash.name, hash); -}; - -/** - * Takes a basic plugin function and returns a wrapper function which marks - * on the player that the plugin has been activated. - * - * @private - * @param {string} name - * The name of the plugin. - * - * @param {Function} plugin - * The basic plugin. - * - * @return {Function} - * A wrapper function for the given plugin. - */ -const createBasicPlugin = function(name, plugin) { - const basicPluginWrapper = function() { - - // We trigger the "beforepluginsetup" and "pluginsetup" events on the player - // regardless, but we want the hash to be consistent with the hash provided - // for advanced plugins. - // - // The only potentially counter-intuitive thing here is the `instance` in - // the "pluginsetup" event is the value returned by the `plugin` function. - triggerSetupEvent(this, {name, plugin, instance: null}, true); - - const instance = plugin.apply(this, arguments); - - markPluginAsActive(this, name); - triggerSetupEvent(this, {name, plugin, instance}); - - return instance; - }; - - Object.keys(plugin).forEach(function(prop) { - basicPluginWrapper[prop] = plugin[prop]; - }); - - return basicPluginWrapper; -}; - -/** - * Takes a plugin sub-class and returns a factory function for generating - * instances of it. - * - * This factory function will replace itself with an instance of the requested - * sub-class of Plugin. - * - * @private - * @param {string} name - * The name of the plugin. - * - * @param {Plugin} PluginSubClass - * The advanced plugin. - * - * @return {Function} - */ -const createPluginFactory = (name, PluginSubClass) => { - - // Add a `name` property to the plugin prototype so that each plugin can - // refer to itself by name. - PluginSubClass.prototype.name = name; - - return function(...args) { - triggerSetupEvent(this, {name, plugin: PluginSubClass, instance: null}, true); - - const instance = new PluginSubClass(...[this, ...args]); - - // The plugin is replaced by a function that returns the current instance. - this[name] = () => instance; - - triggerSetupEvent(this, instance.getEventHash()); - - return instance; - }; -}; - -/** - * Parent class for all advanced plugins. - * - * @mixes module:evented~EventedMixin - * @mixes module:stateful~StatefulMixin - * @fires Player#beforepluginsetup - * @fires Player#beforepluginsetup:$name - * @fires Player#pluginsetup - * @fires Player#pluginsetup:$name - * @listens Player#dispose - * @throws {Error} - * If attempting to instantiate the base {@link Plugin} class - * directly instead of via a sub-class. - */ -class Plugin { - - /** - * Creates an instance of this class. - * - * Sub-classes should call `super` to ensure plugins are properly initialized. - * - * @param {Player} player - * A Video.js player instance. - */ - constructor(player) { - if (this.constructor === Plugin) { - throw new Error('Plugin must be sub-classed; not directly instantiated.'); - } - - this.player = player; - - if (!this.log) { - this.log = this.player.log.createLogger(this.name); - } - - // Make this object evented, but remove the added `trigger` method so we - // use the prototype version instead. - evented(this); - delete this.trigger; - - stateful(this, this.constructor.defaultState); - markPluginAsActive(player, this.name); - - // Auto-bind the dispose method so we can use it as a listener and unbind - // it later easily. - this.dispose = this.dispose.bind(this); - - // If the player is disposed, dispose the plugin. - player.on('dispose', this.dispose); - } - - /** - * Get the version of the plugin that was set on <pluginName>.VERSION - */ - version() { - return this.constructor.VERSION; - } - - /** - * Each event triggered by plugins includes a hash of additional data with - * conventional properties. - * - * This returns that object or mutates an existing hash. - * - * @param {Object} [hash={}] - * An object to be used as event an event hash. - * - * @return {PluginEventHash} - * An event hash object with provided properties mixed-in. - */ - getEventHash(hash = {}) { - hash.name = this.name; - hash.plugin = this.constructor; - hash.instance = this; - return hash; - } - - /** - * Triggers an event on the plugin object and overrides - * {@link module:evented~EventedMixin.trigger|EventedMixin.trigger}. - * - * @param {string|Object} event - * An event type or an object with a type property. - * - * @param {Object} [hash={}] - * Additional data hash to merge with a - * {@link PluginEventHash|PluginEventHash}. - * - * @return {boolean} - * Whether or not default was prevented. - */ - trigger(event, hash = {}) { - return Events.trigger(this.eventBusEl_, event, this.getEventHash(hash)); - } - - /** - * Handles "statechanged" events on the plugin. No-op by default, override by - * subclassing. - * - * @abstract - * @param {Event} e - * An event object provided by a "statechanged" event. - * - * @param {Object} e.changes - * An object describing changes that occurred with the "statechanged" - * event. - */ - handleStateChanged(e) {} - - /** - * Disposes a plugin. - * - * Subclasses can override this if they want, but for the sake of safety, - * it's probably best to subscribe the "dispose" event. - * - * @fires Plugin#dispose - */ - dispose() { - const {name, player} = this; - - /** - * Signals that a advanced plugin is about to be disposed. - * - * @event Plugin#dispose - * @type {Event} - */ - this.trigger('dispose'); - this.off(); - player.off('dispose', this.dispose); - - // Eliminate any possible sources of leaking memory by clearing up - // references between the player and the plugin instance and nulling out - // the plugin's state and replacing methods with a function that throws. - player[PLUGIN_CACHE_KEY][name] = false; - this.player = this.state = null; - - // Finally, replace the plugin name on the player with a new factory - // function, so that the plugin is ready to be set up again. - player[name] = createPluginFactory(name, pluginStorage[name]); - } - - /** - * Determines if a plugin is a basic plugin (i.e. not a sub-class of `Plugin`). - * - * @param {string|Function} plugin - * If a string, matches the name of a plugin. If a function, will be - * tested directly. - * - * @return {boolean} - * Whether or not a plugin is a basic plugin. - */ - static isBasic(plugin) { - const p = (typeof plugin === 'string') ? getPlugin(plugin) : plugin; - - return typeof p === 'function' && !Plugin.prototype.isPrototypeOf(p.prototype); - } - - /** - * Register a Video.js plugin. - * - * @param {string} name - * The name of the plugin to be registered. Must be a string and - * must not match an existing plugin or a method on the `Player` - * prototype. - * - * @param {typeof Plugin|Function} plugin - * A sub-class of `Plugin` or a function for basic plugins. - * - * @return {typeof Plugin|Function} - * For advanced plugins, a factory function for that plugin. For - * basic plugins, a wrapper function that initializes the plugin. - */ - static registerPlugin(name, plugin) { - if (typeof name !== 'string') { - throw new Error(`Illegal plugin name, "${name}", must be a string, was ${typeof name}.`); - } - - if (pluginExists(name)) { - log.warn(`A plugin named "${name}" already exists. You may want to avoid re-registering plugins!`); - } else if (Player.prototype.hasOwnProperty(name)) { - throw new Error(`Illegal plugin name, "${name}", cannot share a name with an existing player method!`); - } - - if (typeof plugin !== 'function') { - throw new Error(`Illegal plugin for "${name}", must be a function, was ${typeof plugin}.`); - } - - pluginStorage[name] = plugin; - - // Add a player prototype method for all sub-classed plugins (but not for - // the base Plugin class). - if (name !== BASE_PLUGIN_NAME) { - if (Plugin.isBasic(plugin)) { - Player.prototype[name] = createBasicPlugin(name, plugin); - } else { - Player.prototype[name] = createPluginFactory(name, plugin); - } - } - - return plugin; - } - - /** - * De-register a Video.js plugin. - * - * @param {string} name - * The name of the plugin to be de-registered. Must be a string that - * matches an existing plugin. - * - * @throws {Error} - * If an attempt is made to de-register the base plugin. - */ - static deregisterPlugin(name) { - if (name === BASE_PLUGIN_NAME) { - throw new Error('Cannot de-register base plugin.'); - } - if (pluginExists(name)) { - delete pluginStorage[name]; - delete Player.prototype[name]; - } - } - - /** - * Gets an object containing multiple Video.js plugins. - * - * @param {Array} [names] - * If provided, should be an array of plugin names. Defaults to _all_ - * plugin names. - * - * @return {Object|undefined} - * An object containing plugin(s) associated with their name(s) or - * `undefined` if no matching plugins exist). - */ - static getPlugins(names = Object.keys(pluginStorage)) { - let result; - - names.forEach(name => { - const plugin = getPlugin(name); - - if (plugin) { - result = result || {}; - result[name] = plugin; - } - }); - - return result; - } - - /** - * Gets a plugin's version, if available - * - * @param {string} name - * The name of a plugin. - * - * @return {string} - * The plugin's version or an empty string. - */ - static getPluginVersion(name) { - const plugin = getPlugin(name); - - return plugin && plugin.VERSION || ''; - } -} - -/** - * Gets a plugin by name if it exists. - * - * @static - * @method getPlugin - * @memberOf Plugin - * @param {string} name - * The name of a plugin. - * - * @returns {typeof Plugin|Function|undefined} - * The plugin (or `undefined`). - */ -Plugin.getPlugin = getPlugin; - -/** - * The name of the base plugin class as it is registered. - * - * @type {string} - */ -Plugin.BASE_PLUGIN_NAME = BASE_PLUGIN_NAME; - -Plugin.registerPlugin(BASE_PLUGIN_NAME, Plugin); - -/** - * Documented in player.js - * - * @ignore - */ -Player.prototype.usingPlugin = function(name) { - return !!this[PLUGIN_CACHE_KEY] && this[PLUGIN_CACHE_KEY][name] === true; -}; - -/** - * Documented in player.js - * - * @ignore - */ -Player.prototype.hasPlugin = function(name) { - return !!pluginExists(name); -}; - -export default Plugin; - -/** - * Signals that a plugin is about to be set up on a player. - * - * @event Player#beforepluginsetup - * @type {PluginEventHash} - */ - -/** - * Signals that a plugin is about to be set up on a player - by name. The name - * is the name of the plugin. - * - * @event Player#beforepluginsetup:$name - * @type {PluginEventHash} - */ - -/** - * Signals that a plugin has just been set up on a player. - * - * @event Player#pluginsetup - * @type {PluginEventHash} - */ - -/** - * Signals that a plugin has just been set up on a player - by name. The name - * is the name of the plugin. - * - * @event Player#pluginsetup:$name - * @type {PluginEventHash} - */ - -/** - * @typedef {Object} PluginEventHash - * - * @property {string} instance - * For basic plugins, the return value of the plugin function. For - * advanced plugins, the plugin instance on which the event is fired. - * - * @property {string} name - * The name of the plugin. - * - * @property {string} plugin - * For basic plugins, the plugin function. For advanced plugins, the - * plugin class/constructor. - */ |
