diff --git a/docs/guides/setup.md b/docs/guides/setup.md index 4bc9dacd19..9e00f6214d 100644 --- a/docs/guides/setup.md +++ b/docs/guides/setup.md @@ -82,6 +82,28 @@ However, using an `id` attribute isn't always practical; so, the `videojs` funct videojs(document.querySelector('.video-js')); ``` +### Getting References to Players + +Once players are created, Video.js keeps track of them internally. There are a few ways to get references to pre-existing players. + +#### Using `videojs` + +Calling `videojs()` with the ID of element of an already-existing player will return that player and will not create another one. + +If there is no player matching the argument, it will attempt to create one. + +#### Using `videojs.getPlayer()` + +Sometimes, you want to get a reference to a player without the potential side effects of calling `videojs()`. This can be acheived by calling `videojs.getPlayer()` with either a string matching the element's ID or the element itself. + +#### Using `videojs.getPlayers()` or `videojs.players` + +The `videojs.players` property exposes all known players. The method, `videojs.getPlayers()` simply returns the same object. + +Players are stored on this object with keys matching their IDs. + +> **Note:** A player created from an element without an ID will be assigned an automatically-generated ID. + ## Options > **Note:** This guide only covers how to pass options during player setup. For a complete reference on _all_ available options, see the [options guide](/docs/guides/options.md). diff --git a/src/js/video.js b/src/js/video.js index 8f45a0e0e3..ff94444f33 100644 --- a/src/js/video.js +++ b/src/js/video.js @@ -41,6 +41,17 @@ if (typeof HTMLVideoElement === 'undefined' && Dom.isReal()) { document.createElement('video-js'); } +/** + * Normalize an `id` value by trimming off a leading `#` + * + * @param {string} id + * A string, maybe with a leading `#`. + * + * @returns {string} + * The string, without any leading `#`. + */ +const normalizeId = (id) => id.indexOf('#') === 0 ? id.slice(1) : id; + /** * Doubles as the main function for users to create a player instance and also * the main library object. @@ -59,62 +70,32 @@ if (typeof HTMLVideoElement === 'undefined' && Dom.isReal()) { * A player instance */ function videojs(id, options, ready) { - let tag; + let player = videojs.getPlayer(id); - // Allow for element or ID to be passed in - // String ID - if (typeof id === 'string') { - const players = videojs.getPlayers(); - - // Adjust for jQuery ID syntax - if (id.indexOf('#') === 0) { - id = id.slice(1); + if (player) { + if (options) { + log.warn(`Player "${id}" is already initialised. Options will not be applied.`); } - - // If a player instance has already been created for this ID return it. - if (players[id]) { - - // If options or ready function are passed, warn - if (options) { - log.warn(`Player "${id}" is already initialised. Options will not be applied.`); - } - - if (ready) { - players[id].ready(ready); - } - - return players[id]; + if (ready) { + player.ready(ready); } - - // Otherwise get element for ID - tag = Dom.$('#' + id); - - // ID is a media element - } else { - tag = id; + return player; } - // Check for a useable element - // re: nodeName, could be a box div also - if (!tag || !tag.nodeName) { - throw new TypeError('The element or ID supplied is not valid. (videojs)'); - } + const el = (typeof id === 'string') ? Dom.$('#' + normalizeId(id)) : id; - // Element may have a player attr referring to an already created player instance. - // If so return that otherwise set up a new player below - if (tag.player || Player.players[tag.playerId]) { - return tag.player || Player.players[tag.playerId]; + if (!Dom.isEl(el)) { + throw new TypeError('The element or ID supplied is not valid. (videojs)'); } - // Check if element is included in the DOM - if (Dom.isEl(tag) && !document.body.contains(tag)) { + if (!document.body.contains(el)) { log.warn('The element supplied is not included in the DOM'); } options = options || {}; - videojs.hooks('beforesetup').forEach(function(hookFunction) { - const opts = hookFunction(tag, mergeOptions(options)); + videojs.hooks('beforesetup').forEach((hookFunction) => { + const opts = hookFunction(el, mergeOptions(options)); if (!isObject(opts) || Array.isArray(opts)) { log.error('please return an object in beforesetup hooks'); @@ -124,9 +105,11 @@ function videojs(id, options, ready) { options = mergeOptions(options, opts); }); + // We get the current "Player" component here in case an integration has + // replaced it with a custom player. const PlayerComponent = Component.getComponent('Player'); - // If not, set up a new player - const player = new PlayerComponent(tag, options, ready); + + player = new PlayerComponent(el, options, ready); videojs.hooks('setup').forEach((hookFunction) => hookFunction(player)); @@ -270,6 +253,38 @@ videojs.options = Player.prototype.options_; */ videojs.getPlayers = () => Player.players; +/** + * Get a single player based on an ID or DOM element. + * + * This is useful if you want to check if an element or ID has an associated + * Video.js player, but not create one if it doesn't. + * + * @param {string|Element} id + * An HTML element - `