Permalink
Browse files

feat: Add `getPlayer` method to Video.js. (#4836)

  • Loading branch information...
misteroneill authored and gkatsev committed Jan 30, 2018
1 parent dcab42e commit a15e616a453006d2e8038efc98eef71bee268085
Showing with 99 additions and 45 deletions.
  1. +22 −0 docs/guides/setup.md
  2. +60 −45 src/js/video.js
  3. +17 −0 test/unit/video.test.js
@@ -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).
@@ -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 - `<video>`, `<audio>`, or `<video-js>` -
* or a string matching the `id` of such an element.
*
* @returns {Player|undefined}
* A player instance or `undefined` if there is no player instance
* matching the argument.
*/
videojs.getPlayer = (id) => {
const players = Player.players;
if (typeof id === 'string') {
return players[normalizeId(id)];
}
if (Dom.isEl(id)) {
const {player, playerId} = id;
// Element may have a `player` property referring to an already created
// player instance. If so, return that.
if (player || players[playerId]) {
return player || players[playerId];
}
}
};
/**
* Expose players object.
*
@@ -372,6 +372,23 @@ QUnit.test('should create a new tag for movingMediaElementInDOM', function(asser
Html5.nativeSourceHandler.canPlayType = oldCPT;
});
QUnit.test('getPlayer', function(assert) {
const fixture = document.getElementById('qunit-fixture');
fixture.innerHTML += '<video-js id="test_vid_id"></video-js>';
assert.notOk(videojs.getPlayer('test_vid_id'), 'no player was created yet');
const tag = document.querySelector('#test_vid_id');
const player = videojs(tag);
assert.strictEqual(videojs.getPlayer('#test_vid_id'), player, 'the player was returned when using a jQuery-style ID selector');
assert.strictEqual(videojs.getPlayer('test_vid_id'), player, 'the player was returned when using a raw ID value');
assert.strictEqual(videojs.getPlayer(tag), player, 'the player was returned when using the original tag/element');
player.dispose();
});
/* **************************************************** *
* div embed tests copied from video emebed tests above *
* **************************************************** */

0 comments on commit a15e616

Please sign in to comment.