2016-12-02 14:27:59 -05:00
# Components
2016-12-20 16:55:59 -05:00
2016-12-02 14:27:59 -05:00
The architecture of the Video.js player is centered around components. The `Player` class and all classes representing player controls and other UI elements inherit from the `Component` class. This architecture makes it easy to construct the user interface of the Video.js player in a tree-like structure that mirrors the DOM.
2016-12-20 16:55:59 -05:00
## Table of Contents
* [What is a Component? ](#what-is-a-component )
* [Creating a Component ](#creating-a-component )
* [Component Children ](#component-children )
2016-12-20 18:20:31 -05:00
* [Basic Example ](#basic-example )
* [Using Options ](#using-options )
* [Event Listening ](#event-listening )
2017-01-19 15:54:47 -05:00
* [Using on ](#using-on )
2016-12-20 18:20:31 -05:00
* [Using off ](#using-off )
* [Using one ](#using-one )
* [Using trigger ](#using-trigger )
2016-12-20 16:55:59 -05:00
* [Default Component Tree ](#default-component-tree )
* [Specific Component Details ](#specific-component-details )
2018-12-05 16:12:21 -05:00
* [Play Toggle ](#play-toggle )
2017-01-19 15:54:47 -05:00
* [Volume Panel ](#volume-panel )
2016-12-20 16:55:59 -05:00
* [Text Track Settings ](#text-track-settings )
2018-01-30 13:26:21 -05:00
* [Resize Manager ](#resize-manager )
2016-12-20 16:55:59 -05:00
2016-12-02 14:27:59 -05:00
## What is a Component?
2016-12-20 16:55:59 -05:00
2016-12-02 14:27:59 -05:00
A component is a JavaScript object that has the following features:
2017-02-21 20:50:52 +00:00
* An associated DOM element, in almost all cases.
2016-12-20 16:55:59 -05:00
* An association to a `Player` object.
* The ability to manage any number of child components.
* The ability to listen for and trigger events.
* A lifecycle of initialization and disposal.
2016-12-02 14:27:59 -05:00
2017-03-21 17:13:06 -04:00
For more specifics on the programmatic interface of a component, see [the component API docs][api].
2016-12-02 14:27:59 -05:00
## Creating a Component
2016-12-20 16:55:59 -05:00
2016-12-02 14:27:59 -05:00
Video.js components can be inherited and registered with Video.js to add new features and UI to the player.
2018-08-10 15:13:32 -04:00
For a working example, [we have a JSBin ](https://jsbin.com/vobacas/edit?html,css,js,output ) demonstrating the creation of a component for displaying a title across the top of the player.
2016-12-02 14:27:59 -05:00
In addition, there are a couple methods worth recognizing:
2016-12-20 16:55:59 -05:00
* `videojs.getComponent(String name)` : Retrieves component constructors from Video.js.
* `videojs.registerComponent(String name, Function Comp)` : Registers component constructors with Video.js.
* `videojs.extend(Function component, Object properties)` : Provides prototype inheritance. Can be used to extend a component's constructor, returning a new constructor with the given properties.
2016-12-02 14:27:59 -05:00
2016-12-20 18:20:31 -05:00
Creation:
```js
// adding a button to the player
var player = videojs('some-video-id');
var Component = videojs.getComponent('Component');
var button = new Component(player);
console.log(button.el());
```
The above code will output
```html
< div class = "video-js" >
< div class = "vjs-button" > Button< / div >
< / div >
```
Adding the new button to the player
```js
// adding a button to the player
var player = videojs('some-video-id');
var button = player.addChild('button');
console.log(button.el());
// will have the same html result as the previous example
```
2016-12-02 14:27:59 -05:00
## Component Children
2016-12-20 16:55:59 -05:00
2017-03-21 17:13:06 -04:00
Again, refer to [the component API docs][api] for complete details on methods available for managing component structures.
2016-12-20 18:20:31 -05:00
### Basic Example
2016-12-02 14:27:59 -05:00
When child component is added to a parent component, Video.js inserts the element of the child into the element of the parent. For example, adding a component like this:
2012-12-17 11:18:31 -08:00
```js
2016-12-02 14:27:59 -05:00
// Add a "BigPlayButton" component to the player. Its element will be appended to the player's element.
player.addChild('BigPlayButton');
2012-12-17 11:18:31 -08:00
```
2016-12-02 14:27:59 -05:00
Results in a DOM that looks like this:
2012-12-30 21:45:50 -08:00
2016-12-02 14:27:59 -05:00
```html
<!-- Player Element -->
< div class = "video-js" >
<!-- BigPlayButton Element -->
< div class = "vjs-big-play-button" > < / div >
< / div >
2012-12-30 21:45:50 -08:00
```
2016-12-02 14:27:59 -05:00
Conversely, removing child components will remove the child component's element from the DOM:
2012-12-30 21:45:50 -08:00
```js
2016-12-02 14:27:59 -05:00
player.removeChild('BigPlayButton');
2012-12-30 21:45:50 -08:00
```
2016-12-02 14:27:59 -05:00
Results in a DOM that looks like this:
2012-12-30 21:45:50 -08:00
```html
2016-12-02 14:27:59 -05:00
<!-- Player Element -->
< div class = "video-js" >
< / div >
2012-12-30 21:45:50 -08:00
```
2016-12-20 18:20:31 -05:00
### Using Options
Pass in options for child constructors and options for children of the child.
```js
var player = videojs('some-vid-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myButton = myComponent.addChild('MyButton', {
text: 'Press Me',
buttonChildExample: {
buttonChildOption: true
}
});
```
Children can also be added via options when a component is initialized.
> Note: Include a 'name' key which will be used if two child components of the same
> type that need different options.
```js
// MyComponent is from the above example
var myComp = new MyComponent(player, {
children: ['button', {
name: 'button',
someOtherOption: true
}, {
name: 'button',
someOtherOption: false
}]
});
```
## Event Listening
### Using `on`
```js
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function() {
var myComponent = this;
console.log('myFunc called');
};
myComponent.on('eventType', myFunc);
myComponent.trigger('eventType');
// logs 'myFunc called'
```
The context of `myFunc` will be `myComponent` unless it is bound. You can add
a listener to another element or component.
```js
var otherComponent = new Component(player);
// myComponent/myFunc is from the above example
myComponent.on(otherComponent.el(), 'eventName', myFunc);
myComponent.on(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// logs 'myFunc called' twice
```
### Using `off`
```js
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function() {
var myComponent = this;
console.log('myFunc called');
};
myComponent.on('eventType', myFunc);
myComponent.trigger('eventType');
// logs 'myFunc called'
myComponent.off('eventType', myFunc);
myComponent.trigger('eventType');
// does nothing
```
2017-01-18 01:52:23 -05:00
If myFunc gets excluded, _all_ listeners for the event type will get removed. If
eventType gets excluded, _all_ listeners will get removed from the component.
2016-12-20 18:20:31 -05:00
You can use `off` to remove listeners that get added to other elements or
components using:
`myComponent.on(otherComponent...`
In this case both the event type and listener function are **REQUIRED** .
```js
var otherComponent = new Component(player);
// myComponent/myFunc is from the above example
myComponent.on(otherComponent.el(), 'eventName', myFunc);
myComponent.on(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// logs 'myFunc called' twice
myComponent.off(ootherComponent.el(), 'eventName', myFunc);
myComponent.off(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// does nothing
```
### Using `one`
```js
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function() {
var myComponent = this;
console.log('myFunc called');
};
myComponent.one('eventName', myFunc);
myComponent.trigger('eventName');
// logs 'myFunc called'
myComponent.trigger('eventName');
// does nothing
```
You can also add a listener to another element or component that will get
triggered only once.
```js
var otherComponent = new Component(player);
// myComponent/myFunc is from the above example
myComponent.one(otherComponent.el(), 'eventName', myFunc);
myComponent.one(otherComponent, 'eventName', myFunc);
otherComponent.trigger('eventName');
// logs 'myFunc called' twice
otherComponent.trigger('eventName');
// does nothing
```
### Using `trigger`
```js
var player = videojs('some-player-id');
var Component = videojs.getComponent('Component');
var myComponent = new Component(player);
var myFunc = function(data) {
var myComponent = this;
console.log('myFunc called');
console.log(data);
};
myComponent.one('eventName', myFunc);
myComponent.trigger('eventName');
// logs 'myFunc called' and 'undefined'
myComponent.trigger({'type':'eventName'});
// logs 'myFunc called' and 'undefined'
myComponent.trigger('eventName', {data: 'some data'});
// logs 'myFunc called' and "{data: 'some data'}"
myComponent.trigger({'type':'eventName'}, {data: 'some data'});
// logs 'myFunc called' and "{data: 'some data'}"
```
2016-12-02 14:27:59 -05:00
## Default Component Tree
2016-12-20 16:55:59 -05:00
2016-12-02 14:27:59 -05:00
The default component structure of the Video.js player looks something like this:
2012-12-30 21:45:50 -08:00
2016-12-20 16:55:59 -05:00
```tree
2012-12-30 21:45:50 -08:00
Player
2017-02-21 20:50:52 +00:00
├── MediaLoader (has no DOM element)
2016-12-02 14:27:59 -05:00
├── PosterImage
├── TextTrackDisplay
├── LoadingSpinner
├── BigPlayButton
├─┬ ControlBar
│ ├── PlayToggle
2017-04-07 13:39:57 -04:00
│ ├── VolumePanel
2016-12-02 14:27:59 -05:00
│ ├── CurrentTimeDisplay (hidden by default)
│ ├── TimeDivider (hidden by default)
│ ├── DurationDisplay (hidden by default)
│ ├─┬ ProgressControl (hidden during live playback)
│ │ └─┬ SeekBar
│ │ ├── LoadProgressBar
│ │ ├── MouseTimeDisplay
│ │ └── PlayProgressBar
│ ├── LiveDisplay (hidden during VOD playback)
│ ├── RemainingTimeDisplay
│ ├── CustomControlSpacer (has no UI)
│ ├── PlaybackRateMenuButton (hidden, unless playback tech supports rate changes)
│ ├── ChaptersButton (hidden, unless there are relevant tracks)
│ ├── DescriptionsButton (hidden, unless there are relevant tracks)
│ ├── SubtitlesButton (hidden, unless there are relevant tracks)
│ ├── CaptionsButton (hidden, unless there are relevant tracks)
│ ├── AudioTrackButton (hidden, unless there are relevant tracks)
│ └── FullscreenToggle
├── ErrorDisplay (hidden, until there is an error)
2018-01-30 13:26:21 -05:00
├── TextTrackSettings
└── ResizeManager (hidden)
2016-03-25 14:34:06 -04:00
```
2016-12-02 14:27:59 -05:00
## Specific Component Details
2016-12-20 16:55:59 -05:00
2018-11-02 21:47:52 +01:00
### Play Toggle
The `PlayToggle` has one option `replay` which can show or hide replay icon. This can be set by passing `{replay: false}` as the default behavior replay icon is shown after video end playback.
Example of how to hide a replay icon
```js
let player = videojs('myplayer', {
controlBar: {
playToggle: {
replay: false
}
}
});
```
2017-01-19 15:54:47 -05:00
### Volume Panel
The `VolumePanel` includes the `MuteToggle` and the `VolumeControl` Components, which will be hidden if volume changes are not supported. There is one important option for the `VolumePanel` which can make your `VolumeControl` appear vertically over the `MuteToggle` . This can be set by passing `VolumePanel` `{inline: false}` as the default behavior is a horizontal `VolumeControl` with `{inline: true}` .
Example of a vertical `VolumeControl`
```js
let player = videojs('myplayer', {
controlBar: {
volumePanel: {
inline: false
}
}
});
```
2016-12-02 14:27:59 -05:00
### Text Track Settings
2016-12-20 16:55:59 -05:00
2016-12-02 14:27:59 -05:00
The text track settings component is only available when using emulated text tracks.
2017-03-21 17:13:06 -04:00
2018-08-10 15:13:32 -04:00
[api]: https://docs.videojs.com/Component.html
2018-01-30 13:26:21 -05:00
### Resize Manager
This new component is in charge of triggering a `playerresize` event when the player size changed.
It uses the ResizeObserver if available or a polyfill was provided. It has no element when using the ResizeObserver.
If a ResizeObserver is not available, it will fallback to an iframe element and listen to its resize event via a debounced handler.
A ResizeObserver polyfill can be passed in like so:
```js
var player = videojs('myplayer', {
resizeManager: {
ResizeObserver: ResizeObserverPoylfill
}
});
```
To force using the iframe fallback, pass in `null` as the `ResizeObserver` :
```js
var player = videojs('myplayer', {
resizeManager: {
ResizeObserver: null
}
});
```
The ResizeManager can also just be disabled like so:
```js
var player = videojs('myplayer', {
resizeManager: false
});
```