mirror of
https://github.com/videojs/video.js.git
synced 2025-02-16 12:23:54 +02:00
Improved JSDoc comments everywhere for new docs generation
closes #2270
This commit is contained in:
parent
f73f69c66c
commit
77a96bea6f
@ -56,6 +56,7 @@ CHANGELOG
|
||||
* @thijstriemstra added a logged error when a plugin is missing ([view](https://github.com/videojs/video.js/pull/1931))
|
||||
* @gkatsev fixed the texttrackchange event and text track display for non-native tracks ([view](https://github.com/videojs/video.js/pull/2215))
|
||||
* @mischizzle fixed event.relatedTarget in Firefox ([view](https://github.com/videojs/video.js/pull/2025))
|
||||
* @mboles updated JSDoc comments everywhere to prepare for new docs ([view](https://github.com/videojs/video.js/pull/2270))
|
||||
|
||||
--------------------
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/**
|
||||
* This code injects the required base styles in the head of the document.
|
||||
*/
|
||||
* @file base-styles.js
|
||||
*
|
||||
* This code injects the required base styles in the head of the document.
|
||||
*/
|
||||
import window from 'global/window';
|
||||
import document from 'global/document';
|
||||
|
||||
|
@ -1,22 +1,39 @@
|
||||
/**
|
||||
* @file big-play-button.js
|
||||
*/
|
||||
import Button from './button.js';
|
||||
import Component from './component.js';
|
||||
|
||||
/* Big Play Button
|
||||
================================================================================ */
|
||||
/**
|
||||
* Initial play button. Shows before the video has played. The hiding of the
|
||||
* big play button is done via CSS and player states.
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @constructor
|
||||
*
|
||||
* @param {Object} player Main Player
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @extends Button
|
||||
* @class BigPlayButton
|
||||
*/
|
||||
class BigPlayButton extends Button {
|
||||
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return 'vjs-big-play-button';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles click for play
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
this.player_.play();
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file button.js
|
||||
*/
|
||||
import Component from './component';
|
||||
import * as Dom from './utils/dom.js';
|
||||
import * as Events from './utils/events.js';
|
||||
@ -5,12 +8,11 @@ import * as Fn from './utils/fn.js';
|
||||
import document from 'global/document';
|
||||
import assign from 'object.assign';
|
||||
|
||||
/* Button - Base class for all buttons
|
||||
================================================================================ */
|
||||
/**
|
||||
* Base class for all buttons
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
*
|
||||
* @param {Object} player Main Player
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @extends Component
|
||||
* @class Button
|
||||
*/
|
||||
@ -27,6 +29,14 @@ class Button extends Component {
|
||||
this.on('blur', this.handleBlur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @param {String=} type Element's node type. e.g. 'div'
|
||||
* @param {Object=} props An object of element attributes that should be set on the element Tag name
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(type='button', props={}) {
|
||||
// Add standard Aria and Tabindex info
|
||||
props = assign({
|
||||
@ -49,6 +59,13 @@ class Button extends Component {
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls text - both request and localize
|
||||
*
|
||||
* @param {String} text Text for button
|
||||
* @return {String}
|
||||
* @method controlText
|
||||
*/
|
||||
controlText(text) {
|
||||
if (!text) return this.controlText_ || 'Need Text';
|
||||
|
||||
@ -58,19 +75,37 @@ class Button extends Component {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows sub components to stack CSS class names
|
||||
*
|
||||
* @return {String}
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-control vjs-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// Click - Override with specific functionality for button
|
||||
/**
|
||||
* Handle Click - Override with specific functionality for button
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {}
|
||||
|
||||
// Focus - Add keyboard functionality to element
|
||||
/**
|
||||
* Handle Focus - Add keyboard functionality to element
|
||||
*
|
||||
* @method handleFocus
|
||||
*/
|
||||
handleFocus() {
|
||||
Events.on(document, 'keydown', Fn.bind(this, this.handleKeyPress));
|
||||
}
|
||||
|
||||
// KeyPress (document level) - Trigger click when keys are pressed
|
||||
/**
|
||||
* Handle KeyPress (document level) - Trigger click when keys are pressed
|
||||
*
|
||||
* @method handleKeyPress
|
||||
*/
|
||||
handleKeyPress(event) {
|
||||
// Check for space bar (32) or enter (13) keys
|
||||
if (event.which === 32 || event.which === 13) {
|
||||
@ -79,7 +114,11 @@ class Button extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
// Blur - Remove keyboard triggers
|
||||
/**
|
||||
* Handle Blur - Remove keyboard triggers
|
||||
*
|
||||
* @method handleBlur
|
||||
*/
|
||||
handleBlur() {
|
||||
Events.off(document, 'keydown', Fn.bind(this, this.handleKeyPress));
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @fileoverview Player Component - Base class for all UI objects
|
||||
* @file component.js
|
||||
*
|
||||
* Player Component - Base class for all UI objects
|
||||
*/
|
||||
|
||||
import window from 'global/window';
|
||||
@ -16,31 +17,31 @@ import mergeOptions from './utils/merge-options.js';
|
||||
|
||||
/**
|
||||
* Base UI Component class
|
||||
*
|
||||
* Components are embeddable UI objects that are represented by both a
|
||||
* javascript object and an element in the DOM. They can be children of other
|
||||
* components, and can have many children themselves.
|
||||
*
|
||||
* ```js
|
||||
* // adding a button to the player
|
||||
* var button = player.addChild('button');
|
||||
* button.el(); // -> button element
|
||||
*
|
||||
* ```
|
||||
* ```html
|
||||
* <div class="video-js">
|
||||
* <div class="vjs-button">Button</div>
|
||||
* </div>
|
||||
*
|
||||
* ```
|
||||
* Components are also event emitters.
|
||||
*
|
||||
* ```js
|
||||
* button.on('click', function(){
|
||||
* console.log('Button Clicked!');
|
||||
* });
|
||||
*
|
||||
* button.trigger('customevent');
|
||||
* ```
|
||||
*
|
||||
* @param {Object} player Main Player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @class Component
|
||||
*/
|
||||
class Component {
|
||||
|
||||
@ -105,6 +106,8 @@ class Component {
|
||||
|
||||
/**
|
||||
* Dispose of the component and all child components
|
||||
*
|
||||
* @method dispose
|
||||
*/
|
||||
dispose() {
|
||||
this.trigger({ type: 'dispose', bubbles: false });
|
||||
@ -139,6 +142,7 @@ class Component {
|
||||
* Return the component's player
|
||||
*
|
||||
* @return {Player}
|
||||
* @method player
|
||||
*/
|
||||
player() {
|
||||
return this.player_;
|
||||
@ -146,14 +150,12 @@ class Component {
|
||||
|
||||
/**
|
||||
* Deep merge of options objects
|
||||
*
|
||||
* Whenever a property is an object on both options objects
|
||||
* the two properties will be merged using mergeOptions.
|
||||
*
|
||||
* This is used for merging options for child components. We
|
||||
* want it to be easy to override individual options on a child
|
||||
* component without having to rewrite all the other default options.
|
||||
*
|
||||
* ```js
|
||||
* Parent.prototype.options_ = {
|
||||
* children: {
|
||||
* 'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
|
||||
@ -170,9 +172,9 @@ class Component {
|
||||
* }
|
||||
*
|
||||
* this.options(newOptions);
|
||||
*
|
||||
* ```
|
||||
* RESULT
|
||||
*
|
||||
* ```js
|
||||
* {
|
||||
* children: {
|
||||
* 'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' },
|
||||
@ -181,9 +183,11 @@ class Component {
|
||||
* 'childFour': {}
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param {Object} obj Object of new option values
|
||||
* @return {Object} A NEW object of this.options_ and obj merged
|
||||
* @method options
|
||||
*/
|
||||
options(obj) {
|
||||
log.warn('this.options() has been deprecated and will be moved to the constructor in 6.0');
|
||||
@ -198,10 +202,12 @@ class Component {
|
||||
|
||||
/**
|
||||
* Get the component's DOM element
|
||||
*
|
||||
* ```js
|
||||
* var domEl = myComponent.el();
|
||||
* ```
|
||||
*
|
||||
* @return {Element}
|
||||
* @method el
|
||||
*/
|
||||
el() {
|
||||
return this.el_;
|
||||
@ -213,6 +219,7 @@ class Component {
|
||||
* @param {String=} tagName Element's node type. e.g. 'div'
|
||||
* @param {Object=} attributes An object of element attributes that should be set on the element
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(tagName, attributes) {
|
||||
return Dom.createEl(tagName, attributes);
|
||||
@ -247,6 +254,7 @@ class Component {
|
||||
* Will either be the same as el() or a new element defined in createEl().
|
||||
*
|
||||
* @return {Element}
|
||||
* @method contentEl
|
||||
*/
|
||||
contentEl() {
|
||||
return this.contentEl_ || this.el_;
|
||||
@ -254,10 +262,12 @@ class Component {
|
||||
|
||||
/**
|
||||
* Get the component's ID
|
||||
*
|
||||
* ```js
|
||||
* var id = myComponent.id();
|
||||
* ```
|
||||
*
|
||||
* @return {String}
|
||||
* @method id
|
||||
*/
|
||||
id() {
|
||||
return this.id_;
|
||||
@ -265,10 +275,12 @@ class Component {
|
||||
|
||||
/**
|
||||
* Get the component's name. The name is often used to reference the component.
|
||||
*
|
||||
* ```js
|
||||
* var name = myComponent.name();
|
||||
* ```
|
||||
*
|
||||
* @return {String}
|
||||
* @method name
|
||||
*/
|
||||
name() {
|
||||
return this.name_;
|
||||
@ -276,10 +288,12 @@ class Component {
|
||||
|
||||
/**
|
||||
* Get an array of all child components
|
||||
*
|
||||
* ```js
|
||||
* var kids = myComponent.children();
|
||||
* ```
|
||||
*
|
||||
* @return {Array} The children
|
||||
* @method children
|
||||
*/
|
||||
children() {
|
||||
return this.children_;
|
||||
@ -289,6 +303,7 @@ class Component {
|
||||
* Returns a child component with the provided ID
|
||||
*
|
||||
* @return {Component}
|
||||
* @method getChildById
|
||||
*/
|
||||
getChildById(id) {
|
||||
return this.childIndex_[id];
|
||||
@ -298,6 +313,7 @@ class Component {
|
||||
* Returns a child component with the provided name
|
||||
*
|
||||
* @return {Component}
|
||||
* @method getChild
|
||||
*/
|
||||
getChild(name) {
|
||||
return this.childNameIndex_[name];
|
||||
@ -305,7 +321,7 @@ class Component {
|
||||
|
||||
/**
|
||||
* Adds a child component inside this component
|
||||
*
|
||||
* ```js
|
||||
* myComponent.el();
|
||||
* // -> <div class='my-component'></div>
|
||||
* myComponent.children();
|
||||
@ -314,9 +330,9 @@ class Component {
|
||||
* var myButton = myComponent.addChild('MyButton');
|
||||
* // -> <div class='my-component'><div class="my-button">myButton<div></div>
|
||||
* // -> myButton === myComonent.children()[0];
|
||||
*
|
||||
* ```
|
||||
* Pass in options for child constructors and options for children of the child
|
||||
*
|
||||
* ```js
|
||||
* var myButton = myComponent.addChild('MyButton', {
|
||||
* text: 'Press Me',
|
||||
* children: {
|
||||
@ -325,11 +341,12 @@ class Component {
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param {String|Component} child The class name or instance of a child to add
|
||||
* @param {Object=} options Options, including options to be passed to children of the child.
|
||||
* @return {Component} The child component (created by this process if a string was used)
|
||||
* @suppress {accessControls|checkRegExp|checkTypes|checkVars|const|constantProperty|deprecated|duplicate|es5Strict|fileoverviewTags|globalThis|invalidCasts|missingProperties|nonStandardJsDocs|strictModuleDepCheck|undefinedNames|undefinedVars|unknownDefines|uselessCode|visibility}
|
||||
* @method addChild
|
||||
*/
|
||||
addChild(child, options={}) {
|
||||
let component;
|
||||
@ -397,6 +414,7 @@ class Component {
|
||||
* child component's element from this component's element
|
||||
*
|
||||
* @param {Component} component Component to remove
|
||||
* @method removeChild
|
||||
*/
|
||||
removeChild(component) {
|
||||
if (typeof component === 'string') {
|
||||
@ -433,7 +451,7 @@ class Component {
|
||||
|
||||
/**
|
||||
* Add and initialize default child components from options
|
||||
*
|
||||
* ```js
|
||||
* // when an instance of MyComponent is created, all children in options
|
||||
* // will be added to the instance by their name strings and options
|
||||
* MyComponent.prototype.options_.children = {
|
||||
@ -441,8 +459,9 @@ class Component {
|
||||
* myChildOption: true
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* ```
|
||||
* // Or when creating the component
|
||||
* ```js
|
||||
* var myComp = new MyComponent(player, {
|
||||
* children: {
|
||||
* myChildComponent: {
|
||||
@ -450,10 +469,10 @@ class Component {
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* ```
|
||||
* The children option can also be an Array of child names or
|
||||
* child options objects (that also include a 'name' key).
|
||||
*
|
||||
* ```js
|
||||
* var myComp = new MyComponent(player, {
|
||||
* children: [
|
||||
* 'button',
|
||||
@ -463,7 +482,9 @@ class Component {
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @method initChildren
|
||||
*/
|
||||
initChildren() {
|
||||
let children = this.options_.children;
|
||||
@ -528,6 +549,7 @@ class Component {
|
||||
* Allows sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
// Child classes can include a function that does:
|
||||
@ -537,26 +559,24 @@ class Component {
|
||||
|
||||
/**
|
||||
* Add an event listener to this component's element
|
||||
*
|
||||
* ```js
|
||||
* var myFunc = function(){
|
||||
* var myComponent = this;
|
||||
* // Do something when the event is fired
|
||||
* };
|
||||
*
|
||||
* myComponent.on('eventType', myFunc);
|
||||
*
|
||||
* ```
|
||||
* The context of myFunc will be myComponent unless previously bound.
|
||||
*
|
||||
* Alternatively, you can add a listener to another element or component.
|
||||
*
|
||||
* ```js
|
||||
* myComponent.on(otherElement, 'eventName', myFunc);
|
||||
* myComponent.on(otherComponent, 'eventName', myFunc);
|
||||
*
|
||||
* ```
|
||||
* The benefit of using this over `VjsEvents.on(otherElement, 'eventName', myFunc)`
|
||||
* and `otherComponent.on('eventName', myFunc)` is that this way the listeners
|
||||
* will be automatically cleaned up when either component is disposed.
|
||||
* It will also bind myComponent as the context of myFunc.
|
||||
*
|
||||
* **NOTE**: When using this on elements in the page other than window
|
||||
* and document (both permanent), if you remove the element from the DOM
|
||||
* you need to call `myComponent.trigger(el, 'dispose')` on it to clean up
|
||||
@ -565,7 +585,8 @@ class Component {
|
||||
* @param {String|Component} first The event type or other component
|
||||
* @param {Function|String} second The event handler or event type
|
||||
* @param {Function} third The event handler
|
||||
* @return {Component} self
|
||||
* @return {Component}
|
||||
* @method on
|
||||
*/
|
||||
on(first, second, third) {
|
||||
if (typeof first === 'string' || Array.isArray(first)) {
|
||||
@ -613,23 +634,24 @@ class Component {
|
||||
|
||||
/**
|
||||
* Remove an event listener from this component's element
|
||||
*
|
||||
* ```js
|
||||
* myComponent.off('eventType', myFunc);
|
||||
*
|
||||
* ```
|
||||
* If myFunc is excluded, ALL listeners for the event type will be removed.
|
||||
* If eventType is excluded, ALL listeners will be removed from the component.
|
||||
*
|
||||
* Alternatively you can use `off` to remove listeners that were added to other
|
||||
* elements or components using `myComponent.on(otherComponent...`.
|
||||
* In this case both the event type and listener function are REQUIRED.
|
||||
*
|
||||
* ```js
|
||||
* myComponent.off(otherElement, 'eventType', myFunc);
|
||||
* myComponent.off(otherComponent, 'eventType', myFunc);
|
||||
* ```
|
||||
*
|
||||
* @param {String=|Component} first The event type or other component
|
||||
* @param {Function=|String} second The listener function or event type
|
||||
* @param {Function=} third The listener for other component
|
||||
* @return {Component}
|
||||
* @method off
|
||||
*/
|
||||
off(first, second, third) {
|
||||
if (!first || typeof first === 'string' || Array.isArray(first)) {
|
||||
@ -660,19 +682,21 @@ class Component {
|
||||
|
||||
/**
|
||||
* Add an event listener to be triggered only once and then removed
|
||||
*
|
||||
* ```js
|
||||
* myComponent.one('eventName', myFunc);
|
||||
*
|
||||
* ```
|
||||
* Alternatively you can add a listener to another element or component
|
||||
* that will be triggered only once.
|
||||
*
|
||||
* ```js
|
||||
* myComponent.one(otherElement, 'eventName', myFunc);
|
||||
* myComponent.one(otherComponent, 'eventName', myFunc);
|
||||
* ```
|
||||
*
|
||||
* @param {String|Component} first The event type or other component
|
||||
* @param {Function|String} second The listener function or event type
|
||||
* @param {Function=} third The listener function for other component
|
||||
* @return {Component}
|
||||
* @method one
|
||||
*/
|
||||
one(first, second, third) {
|
||||
if (typeof first === 'string' || Array.isArray(first)) {
|
||||
@ -698,15 +722,17 @@ class Component {
|
||||
|
||||
/**
|
||||
* Trigger an event on an element
|
||||
*
|
||||
* ```js
|
||||
* myComponent.trigger('eventName');
|
||||
* myComponent.trigger({'type':'eventName'});
|
||||
* myComponent.trigger('eventName', {data: 'some data'});
|
||||
* myComponent.trigger({'type':'eventName'}, {data: 'some data'});
|
||||
* ```
|
||||
*
|
||||
* @param {Event|Object|String} event A string (the type) or an event object with a type attribute
|
||||
* @param {Object} [hash] data hash to pass along with the event
|
||||
* @return {Component} self
|
||||
* @method trigger
|
||||
*/
|
||||
trigger(event, hash) {
|
||||
Events.trigger(this.el_, event, hash);
|
||||
@ -714,13 +740,13 @@ class Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a listener to the component's ready state
|
||||
*
|
||||
* Bind a listener to the component's ready state.
|
||||
* Different from event listeners in that if the ready event has already happened
|
||||
* it will trigger the function immediately.
|
||||
*
|
||||
* @param {Function} fn Ready listener
|
||||
* @return {Component}
|
||||
* @method ready
|
||||
*/
|
||||
ready(fn) {
|
||||
if (fn) {
|
||||
@ -739,6 +765,7 @@ class Component {
|
||||
* Trigger the ready listeners
|
||||
*
|
||||
* @return {Component}
|
||||
* @method triggerReady
|
||||
*/
|
||||
triggerReady() {
|
||||
this.isReady_ = true;
|
||||
@ -766,6 +793,7 @@ class Component {
|
||||
*
|
||||
* @param {String} classToCheck Classname to check
|
||||
* @return {Component}
|
||||
* @method hasClass
|
||||
*/
|
||||
hasClass(classToCheck) {
|
||||
return Dom.hasElClass(this.el_, classToCheck);
|
||||
@ -776,6 +804,7 @@ class Component {
|
||||
*
|
||||
* @param {String} classToAdd Classname to add
|
||||
* @return {Component}
|
||||
* @method addClass
|
||||
*/
|
||||
addClass(classToAdd) {
|
||||
Dom.addElClass(this.el_, classToAdd);
|
||||
@ -783,10 +812,11 @@ class Component {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a CSS class name from the component's element
|
||||
* Remove and return a CSS class name from the component's element
|
||||
*
|
||||
* @param {String} classToRemove Classname to remove
|
||||
* @return {Component}
|
||||
* @method removeClass
|
||||
*/
|
||||
removeClass(classToRemove) {
|
||||
Dom.removeElClass(this.el_, classToRemove);
|
||||
@ -797,6 +827,7 @@ class Component {
|
||||
* Show the component element if hidden
|
||||
*
|
||||
* @return {Component}
|
||||
* @method show
|
||||
*/
|
||||
show() {
|
||||
this.removeClass('vjs-hidden');
|
||||
@ -807,6 +838,7 @@ class Component {
|
||||
* Hide the component element if currently showing
|
||||
*
|
||||
* @return {Component}
|
||||
* @method hide
|
||||
*/
|
||||
hide() {
|
||||
this.addClass('vjs-hidden');
|
||||
@ -819,6 +851,7 @@ class Component {
|
||||
*
|
||||
* @return {Component}
|
||||
* @private
|
||||
* @method lockShowing
|
||||
*/
|
||||
lockShowing() {
|
||||
this.addClass('vjs-lock-showing');
|
||||
@ -831,6 +864,7 @@ class Component {
|
||||
*
|
||||
* @return {Component}
|
||||
* @private
|
||||
* @method unlockShowing
|
||||
*/
|
||||
unlockShowing() {
|
||||
this.removeClass('vjs-lock-showing');
|
||||
@ -839,7 +873,6 @@ class Component {
|
||||
|
||||
/**
|
||||
* Set or get the width of the component (CSS values)
|
||||
*
|
||||
* Setting the video tag dimension values only works with values in pixels.
|
||||
* Percent values will not work.
|
||||
* Some percents can be used, but width()/height() will return the number + %,
|
||||
@ -849,6 +882,7 @@ class Component {
|
||||
* @param {Boolean} skipListeners Skip the 'resize' event trigger
|
||||
* @return {Component} This component, when setting the width
|
||||
* @return {Number|String} The width, when getting
|
||||
* @method width
|
||||
*/
|
||||
width(num, skipListeners) {
|
||||
return this.dimension('width', num, skipListeners);
|
||||
@ -856,7 +890,6 @@ class Component {
|
||||
|
||||
/**
|
||||
* Get or set the height of the component (CSS values)
|
||||
*
|
||||
* Setting the video tag dimension values only works with values in pixels.
|
||||
* Percent values will not work.
|
||||
* Some percents can be used, but width()/height() will return the number + %,
|
||||
@ -866,6 +899,7 @@ class Component {
|
||||
* @param {Boolean=} skipListeners Skip the resize event trigger
|
||||
* @return {Component} This component, when setting the height
|
||||
* @return {Number|String} The height, when getting
|
||||
* @method height
|
||||
*/
|
||||
height(num, skipListeners) {
|
||||
return this.dimension('height', num, skipListeners);
|
||||
@ -874,9 +908,10 @@ class Component {
|
||||
/**
|
||||
* Set both width and height at the same time
|
||||
*
|
||||
* @param {Number|String} width
|
||||
* @param {Number|String} height
|
||||
* @param {Number|String} width Width of player
|
||||
* @param {Number|String} height Height of player
|
||||
* @return {Component} The component
|
||||
* @method dimensions
|
||||
*/
|
||||
dimensions(width, height) {
|
||||
// Skip resize listeners on width for optimization
|
||||
@ -885,10 +920,8 @@ class Component {
|
||||
|
||||
/**
|
||||
* Get or set width or height
|
||||
*
|
||||
* This is the shared code for the width() and height() methods.
|
||||
* All for an integer, integer + 'px' or integer + '%';
|
||||
*
|
||||
* Known issue: Hidden elements officially have a width of 0. We're defaulting
|
||||
* to the style.width value and falling back to computedStyle which has the
|
||||
* hidden element issue. Info, but probably not an efficient fix:
|
||||
@ -900,6 +933,7 @@ class Component {
|
||||
* @return {Component} The component if a dimension was set
|
||||
* @return {Number|String} The dimension if nothing was set
|
||||
* @private
|
||||
* @method dimension
|
||||
*/
|
||||
dimension(widthOrHeight, num, skipListeners) {
|
||||
if (num !== undefined) {
|
||||
@ -949,13 +983,13 @@ class Component {
|
||||
|
||||
/**
|
||||
* Emit 'tap' events when touch events are supported
|
||||
*
|
||||
* This is used to support toggling the controls through a tap on the video.
|
||||
*
|
||||
* We're requiring them to be enabled because otherwise every component would
|
||||
* have this extra overhead unnecessarily, on mobile devices where extra
|
||||
* overhead is especially bad.
|
||||
*
|
||||
* @private
|
||||
* @method emitTapEvents
|
||||
*/
|
||||
emitTapEvents() {
|
||||
// Track the start time so we can determine how long the touch lasted
|
||||
@ -992,7 +1026,7 @@ class Component {
|
||||
// So, if we moved only a small distance, this could still be a tap
|
||||
const xdiff = event.touches[0].pageX - firstTouch.pageX;
|
||||
const ydiff = event.touches[0].pageY - firstTouch.pageY;
|
||||
const touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
const touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
|
||||
if (touchDistance > tapMovementThreshold) {
|
||||
couldBeTap = false;
|
||||
@ -1032,12 +1066,10 @@ class Component {
|
||||
|
||||
/**
|
||||
* Report user touch activity when touch events occur
|
||||
*
|
||||
* User activity is used to determine when controls should show/hide. It's
|
||||
* relatively simple when it comes to mouse events, because any mouse event
|
||||
* should show the controls. So we capture mouse events that bubble up to the
|
||||
* player and report activity when that happens.
|
||||
*
|
||||
* With touch events it isn't as easy. We can't rely on touch events at the
|
||||
* player level, because a tap (touchstart + touchend) on the video itself on
|
||||
* mobile devices is meant to turn controls off (and on). User activity is
|
||||
@ -1045,13 +1077,13 @@ class Component {
|
||||
* turns the controls off, then the touchend event bubbles up to the player,
|
||||
* which if it reported user activity, would turn the controls right back on.
|
||||
* (We also don't want to completely block touch events from bubbling up)
|
||||
*
|
||||
* Also a touchmove, touch+hold, and anything other than a tap is not supposed
|
||||
* to turn the controls back on on a mobile device.
|
||||
*
|
||||
* Here we're setting the default component behavior to report user activity
|
||||
* whenever touch events happen, and this can be turned off by components that
|
||||
* want touch events to act differently.
|
||||
*
|
||||
* @method enableTouchActivity
|
||||
*/
|
||||
enableTouchActivity() {
|
||||
// Don't continue if the root player doesn't support reporting user activity
|
||||
@ -1087,9 +1119,11 @@ class Component {
|
||||
|
||||
/**
|
||||
* Creates timeout and sets up disposal automatically.
|
||||
*
|
||||
* @param {Function} fn The function to run after the timeout.
|
||||
* @param {Number} timeout Number of ms to delay before executing specified function.
|
||||
* @return {Number} Returns the timeout ID
|
||||
* @method setTimeout
|
||||
*/
|
||||
setTimeout(fn, timeout) {
|
||||
fn = Fn.bind(this, fn);
|
||||
@ -1110,8 +1144,10 @@ class Component {
|
||||
|
||||
/**
|
||||
* Clears a timeout and removes the associated dispose listener
|
||||
*
|
||||
* @param {Number} timeoutId The id of the timeout to clear
|
||||
* @return {Number} Returns the timeout ID
|
||||
* @method clearTimeout
|
||||
*/
|
||||
clearTimeout(timeoutId) {
|
||||
window.clearTimeout(timeoutId);
|
||||
@ -1127,9 +1163,11 @@ class Component {
|
||||
|
||||
/**
|
||||
* Creates an interval and sets up disposal automatically.
|
||||
*
|
||||
* @param {Function} fn The function to run every N seconds.
|
||||
* @param {Number} interval Number of ms to delay before executing specified function.
|
||||
* @return {Number} Returns the interval ID
|
||||
* @method setInterval
|
||||
*/
|
||||
setInterval(fn, interval) {
|
||||
fn = Fn.bind(this, fn);
|
||||
@ -1149,8 +1187,10 @@ class Component {
|
||||
|
||||
/**
|
||||
* Clears an interval and removes the associated dispose listener
|
||||
*
|
||||
* @param {Number} intervalId The id of the interval to clear
|
||||
* @return {Number} Returns the interval ID
|
||||
* @method clearInterval
|
||||
*/
|
||||
clearInterval(intervalId) {
|
||||
window.clearInterval(intervalId);
|
||||
@ -1164,6 +1204,14 @@ class Component {
|
||||
return intervalId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a component
|
||||
*
|
||||
* @param {String} name Name of the component to register
|
||||
* @param {Object} comp The component to register
|
||||
* @static
|
||||
* @method registerComponent
|
||||
*/
|
||||
static registerComponent(name, comp) {
|
||||
if (!Component.components_) {
|
||||
Component.components_ = {};
|
||||
@ -1173,6 +1221,14 @@ class Component {
|
||||
return comp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a component by name
|
||||
*
|
||||
* @param {String} name Name of the component to get
|
||||
* @return {Component}
|
||||
* @static
|
||||
* @method getComponent
|
||||
*/
|
||||
static getComponent(name) {
|
||||
if (Component.components_ && Component.components_[name]) {
|
||||
return Component.components_[name];
|
||||
@ -1184,6 +1240,14 @@ class Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the constructor using the supplied init method
|
||||
* or uses the init of the parent object
|
||||
*
|
||||
* @param {Object} props An object of properties
|
||||
* @static
|
||||
* @method extend
|
||||
*/
|
||||
static extend(props) {
|
||||
props = props || {};
|
||||
// Set up the constructor using the supplied init method
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file control-bar.js
|
||||
*/
|
||||
import Component from '../component.js';
|
||||
|
||||
// Required children
|
||||
@ -20,13 +23,18 @@ import CustomControlSpacer from './spacer-controls/custom-control-spacer.js';
|
||||
|
||||
/**
|
||||
* Container of main controls
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @constructor
|
||||
*
|
||||
* @extends Component
|
||||
* @class ControlBar
|
||||
*/
|
||||
class ControlBar extends Component {
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-control-bar'
|
||||
|
@ -1,19 +1,32 @@
|
||||
/**
|
||||
* @file fullscreen-toggle.js
|
||||
*/
|
||||
import Button from '../button.js';
|
||||
import Component from '../component.js';
|
||||
|
||||
/**
|
||||
* Toggle fullscreen video
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @extends vjs.Button
|
||||
*
|
||||
* @extends Button
|
||||
* @class FullscreenToggle
|
||||
*/
|
||||
class FullscreenToggle extends Button {
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-fullscreen-control ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles click for full screen
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
if (!this.player_.isFullscreen()) {
|
||||
this.player_.requestFullscreen();
|
||||
|
@ -1,15 +1,24 @@
|
||||
/**
|
||||
* @file live-display.js
|
||||
*/
|
||||
import Component from '../component';
|
||||
import * as Dom from '../utils/dom.js';
|
||||
|
||||
/**
|
||||
* Displays the live indicator
|
||||
* TODO - Future make it click to snap to live
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*
|
||||
* @extends Component
|
||||
* @class LiveDisplay
|
||||
*/
|
||||
class LiveDisplay extends Component {
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
var el = super.createEl('div', {
|
||||
className: 'vjs-live-control vjs-control'
|
||||
|
@ -1,13 +1,17 @@
|
||||
/**
|
||||
* @file mute-toggle.js
|
||||
*/
|
||||
import Button from '../button';
|
||||
import Component from '../component';
|
||||
import * as Dom from '../utils/dom.js';
|
||||
|
||||
/**
|
||||
* A button component for muting the audio
|
||||
* A button component for muting the audio
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Button
|
||||
* @class MuteToggle
|
||||
*/
|
||||
class MuteToggle extends Button {
|
||||
|
||||
@ -30,14 +34,30 @@ class MuteToggle extends Button {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-mute-control ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on mute
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
this.player_.muted( this.player_.muted() ? false : true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update volume
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
var vol = this.player_.volume(),
|
||||
level = 3;
|
||||
|
@ -1,12 +1,16 @@
|
||||
/**
|
||||
* @file play-toggle.js
|
||||
*/
|
||||
import Button from '../button.js';
|
||||
import Component from '../component.js';
|
||||
|
||||
/**
|
||||
* Button to toggle between play and pause
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @constructor
|
||||
* @extends Button
|
||||
* @class PlayToggle
|
||||
*/
|
||||
class PlayToggle extends Button {
|
||||
|
||||
@ -17,11 +21,21 @@ class PlayToggle extends Button {
|
||||
this.on(player, 'pause', this.handlePause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-play-control ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// handleClick - Toggle between play and pause
|
||||
/**
|
||||
* Handle click to toggle between play and pause
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
if (this.player_.paused()) {
|
||||
this.player_.play();
|
||||
@ -30,14 +44,22 @@ class PlayToggle extends Button {
|
||||
}
|
||||
}
|
||||
|
||||
// handlePlay - Add the vjs-playing class to the element so it can change appearance
|
||||
/**
|
||||
* Add the vjs-playing class to the element so it can change appearance
|
||||
*
|
||||
* @method handlePlay
|
||||
*/
|
||||
handlePlay() {
|
||||
this.removeClass('vjs-paused');
|
||||
this.addClass('vjs-playing');
|
||||
this.controlText('Pause'); // change the button text to "Pause"
|
||||
}
|
||||
|
||||
// handlePause - Add the vjs-paused class to the element so it can change appearance
|
||||
/**
|
||||
* Add the vjs-paused class to the element so it can change appearance
|
||||
*
|
||||
* @method handlePause
|
||||
*/
|
||||
handlePause() {
|
||||
this.removeClass('vjs-playing');
|
||||
this.addClass('vjs-paused');
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file playback-rate-menu-button.js
|
||||
*/
|
||||
import MenuButton from '../../menu/menu-button.js';
|
||||
import Menu from '../../menu/menu.js';
|
||||
import PlaybackRateMenuItem from './playback-rate-menu-item.js';
|
||||
@ -9,7 +12,8 @@ import * as Dom from '../../utils/dom.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends MenuButton
|
||||
* @class PlaybackRateMenuButton
|
||||
*/
|
||||
class PlaybackRateMenuButton extends MenuButton {
|
||||
|
||||
@ -23,6 +27,12 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
this.on(player, 'ratechange', this.updateLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl();
|
||||
|
||||
@ -36,11 +46,22 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-playback-rate ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// Menu creation
|
||||
/**
|
||||
* Create the playback rate menu
|
||||
*
|
||||
* @return {Menu} Menu object populated with items
|
||||
* @method createMenu
|
||||
*/
|
||||
createMenu() {
|
||||
let menu = new Menu(this.player());
|
||||
let rates = this.playbackRates();
|
||||
@ -56,11 +77,21 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
return menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates ARIA accessibility attributes
|
||||
*
|
||||
* @method updateARIAAttributes
|
||||
*/
|
||||
updateARIAAttributes() {
|
||||
// Current playback rate
|
||||
this.el().setAttribute('aria-valuenow', this.player().playbackRate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle menu item click
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
// select next rate option
|
||||
let currentRate = this.player().playbackRate();
|
||||
@ -77,10 +108,22 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
this.player().playbackRate(newRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get possible playback rates
|
||||
*
|
||||
* @return {Array} Possible playback rates
|
||||
* @method playbackRates
|
||||
*/
|
||||
playbackRates() {
|
||||
return this.options_['playbackRates'] || (this.options_.playerOptions && this.options_.playerOptions['playbackRates']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get supported playback rates
|
||||
*
|
||||
* @return {Array} Supported playback rates
|
||||
* @method playbackRateSupported
|
||||
*/
|
||||
playbackRateSupported() {
|
||||
return this.player().tech
|
||||
&& this.player().tech['featuresPlaybackRate']
|
||||
@ -91,6 +134,8 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
|
||||
/**
|
||||
* Hide playback rate controls when they're no playback rate options to select
|
||||
*
|
||||
* @method updateVisibility
|
||||
*/
|
||||
updateVisibility() {
|
||||
if (this.playbackRateSupported()) {
|
||||
@ -102,6 +147,8 @@ class PlaybackRateMenuButton extends MenuButton {
|
||||
|
||||
/**
|
||||
* Update button label when rate changed
|
||||
*
|
||||
* @method updateLabel
|
||||
*/
|
||||
updateLabel() {
|
||||
if (this.playbackRateSupported()) {
|
||||
|
@ -1,10 +1,16 @@
|
||||
/**
|
||||
* @file playback-rate-menu-item.js
|
||||
*/
|
||||
import MenuItem from '../../menu/menu-item.js';
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
* The specific menu item type for selecting a playback rate
|
||||
*
|
||||
* @constructor
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends MenuItem
|
||||
* @class PlaybackRateMenuItem
|
||||
*/
|
||||
class PlaybackRateMenuItem extends MenuItem {
|
||||
|
||||
@ -23,11 +29,21 @@ class PlaybackRateMenuItem extends MenuItem {
|
||||
this.on(player, 'ratechange', this.update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on menu item
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
super.handleClick();
|
||||
this.player().playbackRate(this.rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update playback rate with selected rate
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
this.selected(this.player().playbackRate() === this.rate);
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file load-progress-bar.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
|
||||
@ -6,7 +9,8 @@ import * as Dom from '../../utils/dom.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class LoadProgressBar
|
||||
*/
|
||||
class LoadProgressBar extends Component {
|
||||
|
||||
@ -15,6 +19,12 @@ class LoadProgressBar extends Component {
|
||||
this.on(player, 'progress', this.update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-load-progress',
|
||||
@ -22,6 +32,11 @@ class LoadProgressBar extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update progress bar
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let buffered = this.player_.buffered();
|
||||
let duration = this.player_.duration();
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file play-progress-bar.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
@ -5,10 +8,17 @@ import Component from '../../component.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class PlayProgressBar
|
||||
*/
|
||||
class PlayProgressBar extends Component {
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-play-progress',
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file progress-control.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import SeekBar from './seek-bar.js';
|
||||
|
||||
@ -7,9 +10,17 @@ import SeekBar from './seek-bar.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class ProgressControl
|
||||
*/
|
||||
class ProgressControl extends Component {
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-progress-control vjs-control'
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file seek-bar.js
|
||||
*/
|
||||
import Slider from '../../slider/slider.js';
|
||||
import Component from '../../component.js';
|
||||
import LoadProgressBar from './load-progress-bar.js';
|
||||
@ -11,7 +14,8 @@ import roundFloat from '../../utils/round-float.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Slider
|
||||
* @class SeekBar
|
||||
*/
|
||||
class SeekBar extends Slider {
|
||||
|
||||
@ -21,6 +25,12 @@ class SeekBar extends Slider {
|
||||
player.ready(Fn.bind(this, this.updateARIAAttributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-progress-holder',
|
||||
@ -28,6 +38,11 @@ class SeekBar extends Slider {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ARIA accessibility attributes
|
||||
*
|
||||
* @method updateARIAAttributes
|
||||
*/
|
||||
updateARIAAttributes() {
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
let time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
@ -35,11 +50,22 @@ class SeekBar extends Slider {
|
||||
this.el_.setAttribute('aria-valuetext', formatTime(time, this.player_.duration())); // human readable value of progress bar (time complete)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get percentage of video played
|
||||
*
|
||||
* @return {Number} Percentage played
|
||||
* @method getPercent
|
||||
*/
|
||||
getPercent() {
|
||||
let percent = this.player_.currentTime() / this.player_.duration();
|
||||
return percent >= 1 ? 1 : percent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse down on seek bar
|
||||
*
|
||||
* @method handleMouseDown
|
||||
*/
|
||||
handleMouseDown(event) {
|
||||
super.handleMouseDown(event);
|
||||
|
||||
@ -49,6 +75,11 @@ class SeekBar extends Slider {
|
||||
this.player_.pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse move on seek bar
|
||||
*
|
||||
* @method handleMouseMove
|
||||
*/
|
||||
handleMouseMove(event) {
|
||||
let newTime = this.calculateDistance(event) * this.player_.duration();
|
||||
|
||||
@ -59,6 +90,11 @@ class SeekBar extends Slider {
|
||||
this.player_.currentTime(newTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse up on seek bar
|
||||
*
|
||||
* @method handleMouseUp
|
||||
*/
|
||||
handleMouseUp(event) {
|
||||
super.handleMouseUp(event);
|
||||
|
||||
@ -68,10 +104,20 @@ class SeekBar extends Slider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move more quickly fast forward for keyboard-only users
|
||||
*
|
||||
* @method stepForward
|
||||
*/
|
||||
stepForward() {
|
||||
this.player_.currentTime(this.player_.currentTime() + 5); // more quickly fast forward for keyboard-only users
|
||||
}
|
||||
|
||||
/**
|
||||
* Move more quickly rewind for keyboard-only users
|
||||
*
|
||||
* @method stepBack
|
||||
*/
|
||||
stepBack() {
|
||||
this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users
|
||||
}
|
||||
|
@ -1,17 +1,33 @@
|
||||
/**
|
||||
* @file custom-control-spacer.js
|
||||
*/
|
||||
import Spacer from './spacer.js';
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
* Spacer specifically meant to be used as an insertion point for new plugins, etc.
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Obect=} options
|
||||
* @extends Spacer
|
||||
* @class CustomControlSpacer
|
||||
*/
|
||||
class CustomControlSpacer extends Spacer {
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-custom-control-spacer ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl({
|
||||
className: this.buildCSSClass()
|
||||
|
@ -1,17 +1,34 @@
|
||||
/**
|
||||
* @file spacer.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
* Just an empty spacer element that can be used as an append point for plugins, etc.
|
||||
* Also can be used to create space between elements when necessary.
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends Component
|
||||
* @class Spacer
|
||||
*/
|
||||
class Spacer extends Component {
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-spacer ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @param {Object} props An object of properties
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(props) {
|
||||
return super.createEl('div', {
|
||||
className: this.buildCSSClass()
|
||||
|
@ -1,7 +1,18 @@
|
||||
/**
|
||||
* @file caption-settings-menu-item.js
|
||||
*/
|
||||
import TextTrackMenuItem from './text-track-menu-item.js';
|
||||
import Component from '../../component.js';
|
||||
|
||||
class CaptionSettingsMenuItem extends TextTrackMenuItem {
|
||||
/**
|
||||
* The menu item for caption track settings menu
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends TextTrackMenuItem
|
||||
* @class CaptionSettingsMenuItem
|
||||
*/
|
||||
class CaptionSettingsMenuItem extends TextTrackMenuItem {
|
||||
|
||||
constructor(player, options) {
|
||||
options['track'] = {
|
||||
@ -16,6 +27,11 @@ class CaptionSettingsMenuItem extends TextTrackMenuItem {
|
||||
this.addClass('vjs-texttrack-settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on menu item
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
this.player().getChild('textTrackSettings').show();
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file captions-button.js
|
||||
*/
|
||||
import TextTrackButton from './text-track-button.js';
|
||||
import Component from '../../component.js';
|
||||
import CaptionSettingsMenuItem from './caption-settings-menu-item.js';
|
||||
@ -5,7 +8,11 @@ import CaptionSettingsMenuItem from './caption-settings-menu-item.js';
|
||||
/**
|
||||
* The button component for toggling and selecting captions
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} player Player object
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends TextTrackButton
|
||||
* @class CaptionsButton
|
||||
*/
|
||||
class CaptionsButton extends TextTrackButton {
|
||||
|
||||
@ -14,10 +21,21 @@ class CaptionsButton extends TextTrackButton {
|
||||
this.el_.setAttribute('aria-label','Captions Menu');
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-captions-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update caption menu items
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let threshold = 2;
|
||||
super.update();
|
||||
@ -34,6 +52,12 @@ class CaptionsButton extends TextTrackButton {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create caption menu items
|
||||
*
|
||||
* @return {Array} Array of menu items
|
||||
* @method createItems
|
||||
*/
|
||||
createItems() {
|
||||
let items = [];
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file chapters-button.js
|
||||
*/
|
||||
import TextTrackButton from './text-track-button.js';
|
||||
import Component from '../../component.js';
|
||||
import TextTrackMenuItem from './text-track-menu-item.js';
|
||||
@ -8,12 +11,16 @@ import * as Fn from '../../utils/fn.js';
|
||||
import toTitleCase from '../../utils/to-title-case.js';
|
||||
import window from 'global/window';
|
||||
|
||||
// Chapters act much differently than other text tracks
|
||||
// Cues are navigation vs. other tracks of alternative languages
|
||||
/**
|
||||
* The button component for toggling and selecting chapters
|
||||
* Chapters act much differently than other text tracks
|
||||
* Cues are navigation vs. other tracks of alternative languages
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} player Player object
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends TextTrackButton
|
||||
* @class ChaptersButton
|
||||
*/
|
||||
class ChaptersButton extends TextTrackButton {
|
||||
|
||||
@ -22,11 +29,22 @@ class ChaptersButton extends TextTrackButton {
|
||||
this.el_.setAttribute('aria-label','Chapters Menu');
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-chapters-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// Create a menu item for each text track
|
||||
/**
|
||||
* Create a menu item for each text track
|
||||
*
|
||||
* @return {Array} Array of menu items
|
||||
* @method createItems
|
||||
*/
|
||||
createItems() {
|
||||
let items = [];
|
||||
|
||||
@ -48,6 +66,12 @@ class ChaptersButton extends TextTrackButton {
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create menu from chapter buttons
|
||||
*
|
||||
* @return {Menu} Menu of chapter buttons
|
||||
* @method createMenu
|
||||
*/
|
||||
createMenu() {
|
||||
let tracks = this.player_.textTracks() || [];
|
||||
let chaptersTrack;
|
||||
|
@ -1,9 +1,17 @@
|
||||
/**
|
||||
* @file chapters-track-menu-item.js
|
||||
*/
|
||||
import MenuItem from '../../menu/menu-item.js';
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* The chapter track menu item
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends MenuItem
|
||||
* @class ChaptersTrackMenuItem
|
||||
*/
|
||||
class ChaptersTrackMenuItem extends MenuItem {
|
||||
|
||||
@ -22,12 +30,22 @@ class ChaptersTrackMenuItem extends MenuItem {
|
||||
track.addEventListener('cuechange', Fn.bind(this, this.update));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on menu item
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
super.handleClick();
|
||||
this.player_.currentTime(this.cue.startTime);
|
||||
this.update(this.cue.startTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update chapter menu item
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let cue = this.cue;
|
||||
let currentTime = this.player_.currentTime();
|
||||
|
@ -1,10 +1,16 @@
|
||||
/**
|
||||
* @file off-text-track-menu-item.js
|
||||
*/
|
||||
import TextTrackMenuItem from './text-track-menu-item.js';
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
* A special menu item for turning of a specific type of text track
|
||||
*
|
||||
* @constructor
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends TextTrackMenuItem
|
||||
* @class OffTextTrackMenuItem
|
||||
*/
|
||||
class OffTextTrackMenuItem extends TextTrackMenuItem {
|
||||
|
||||
@ -23,6 +29,12 @@ class OffTextTrackMenuItem extends TextTrackMenuItem {
|
||||
this.selected(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle text track change
|
||||
*
|
||||
* @param {Object} event Event object
|
||||
* @method handleTracksChange
|
||||
*/
|
||||
handleTracksChange(event){
|
||||
let tracks = this.player().textTracks();
|
||||
let selected = true;
|
||||
|
@ -1,10 +1,17 @@
|
||||
/**
|
||||
* @file subtitles-button.js
|
||||
*/
|
||||
import TextTrackButton from './text-track-button.js';
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
* The button component for toggling and selecting subtitles
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} player Player object
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends TextTrackButton
|
||||
* @class SubtitlesButton
|
||||
*/
|
||||
class SubtitlesButton extends TextTrackButton {
|
||||
|
||||
@ -13,6 +20,12 @@ class SubtitlesButton extends TextTrackButton {
|
||||
this.el_.setAttribute('aria-label','Subtitles Menu');
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-subtitles-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file text-track-button.js
|
||||
*/
|
||||
import MenuButton from '../../menu/menu-button.js';
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
@ -7,7 +10,10 @@ import OffTextTrackMenuItem from './off-text-track-menu-item.js';
|
||||
/**
|
||||
* The base class for buttons that toggle specific text track types (e.g. subtitles)
|
||||
*
|
||||
* @constructor
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends MenuButton
|
||||
* @class TextTrackButton
|
||||
*/
|
||||
class TextTrackButton extends MenuButton {
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file text-track-menu-item.js
|
||||
*/
|
||||
import MenuItem from '../../menu/menu-item.js';
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
@ -7,7 +10,10 @@ import document from 'global/document';
|
||||
/**
|
||||
* The specific menu item type for selecting a language within a text track kind
|
||||
*
|
||||
* @constructor
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends MenuItem
|
||||
* @class TextTrackMenuItem
|
||||
*/
|
||||
class TextTrackMenuItem extends MenuItem {
|
||||
|
||||
@ -58,6 +64,11 @@ class TextTrackMenuItem extends MenuItem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on text track
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick(event) {
|
||||
let kind = this.track['kind'];
|
||||
let tracks = this.player_.textTracks();
|
||||
@ -81,6 +92,11 @@ class TextTrackMenuItem extends MenuItem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle text track change
|
||||
*
|
||||
* @method handleTracksChange
|
||||
*/
|
||||
handleTracksChange(event){
|
||||
this.selected(this.track['mode'] === 'showing');
|
||||
}
|
||||
|
@ -1,12 +1,17 @@
|
||||
/**
|
||||
* @file current-time-display.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
* Displays the current time
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class CurrentTimeDisplay
|
||||
*/
|
||||
class CurrentTimeDisplay extends Component {
|
||||
|
||||
@ -16,6 +21,12 @@ class CurrentTimeDisplay extends Component {
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl('div', {
|
||||
className: 'vjs-current-time vjs-time-control vjs-control'
|
||||
@ -31,6 +42,11 @@ class CurrentTimeDisplay extends Component {
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update current time display
|
||||
*
|
||||
* @method updateContent
|
||||
*/
|
||||
updateContent() {
|
||||
// Allows for smooth scrubbing, when player can't keep up.
|
||||
let time = (this.player_.scrubbing) ? this.player_.getCache().currentTime : this.player_.currentTime();
|
||||
|
@ -1,12 +1,17 @@
|
||||
/**
|
||||
* @file duration-display.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
* Displays the duration
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class DurationDisplay
|
||||
*/
|
||||
class DurationDisplay extends Component {
|
||||
|
||||
@ -22,6 +27,12 @@ class DurationDisplay extends Component {
|
||||
this.on(player, 'loadedmetadata', this.updateContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl('div', {
|
||||
className: 'vjs-duration vjs-time-control vjs-control'
|
||||
@ -37,6 +48,11 @@ class DurationDisplay extends Component {
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update duration time display
|
||||
*
|
||||
* @method updateContent
|
||||
*/
|
||||
updateContent() {
|
||||
let duration = this.player_.duration();
|
||||
if (duration) {
|
||||
|
@ -1,12 +1,17 @@
|
||||
/**
|
||||
* @file remaining-time-display.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
import * as Dom from '../../utils/dom.js';
|
||||
import formatTime from '../../utils/format-time.js';
|
||||
|
||||
/**
|
||||
* Displays the time left in the video
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class RemainingTimeDisplay
|
||||
*/
|
||||
class RemainingTimeDisplay extends Component {
|
||||
|
||||
@ -16,6 +21,12 @@ class RemainingTimeDisplay extends Component {
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = super.createEl('div', {
|
||||
className: 'vjs-remaining-time vjs-time-control vjs-control'
|
||||
@ -31,6 +42,11 @@ class RemainingTimeDisplay extends Component {
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update remaining time display
|
||||
*
|
||||
* @method updateContent
|
||||
*/
|
||||
updateContent() {
|
||||
if (this.player_.duration()) {
|
||||
const localizedText = this.localize('Remaining Time');
|
||||
|
@ -1,16 +1,25 @@
|
||||
/**
|
||||
* @file time-divider.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
* The separator between the current time and duration
|
||||
*
|
||||
* The separator between the current time and duration.
|
||||
* Can be hidden if it's not needed in the design.
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class TimeDivider
|
||||
*/
|
||||
class TimeDivider extends Component {
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-time-control vjs-time-divider',
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file volume-bar.js
|
||||
*/
|
||||
import Slider from '../../slider/slider.js';
|
||||
import Component from '../../component.js';
|
||||
import * as Fn from '../../utils/fn.js';
|
||||
@ -11,7 +14,8 @@ import VolumeLevel from './volume-level.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Slider
|
||||
* @class VolumeBar
|
||||
*/
|
||||
class VolumeBar extends Slider {
|
||||
|
||||
@ -21,6 +25,12 @@ class VolumeBar extends Slider {
|
||||
player.ready(Fn.bind(this, this.updateARIAAttributes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-volume-bar',
|
||||
@ -28,6 +38,11 @@ class VolumeBar extends Slider {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse move on volume bar
|
||||
*
|
||||
* @method handleMouseMove
|
||||
*/
|
||||
handleMouseMove(event) {
|
||||
if (this.player_.muted()) {
|
||||
this.player_.muted(false);
|
||||
@ -36,6 +51,12 @@ class VolumeBar extends Slider {
|
||||
this.player_.volume(this.calculateDistance(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get percent of volume level
|
||||
*
|
||||
* @retun {Number} Volume level percent
|
||||
* @method getPercent
|
||||
*/
|
||||
getPercent() {
|
||||
if (this.player_.muted()) {
|
||||
return 0;
|
||||
@ -44,14 +65,29 @@ class VolumeBar extends Slider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase volume level for keyboard users
|
||||
*
|
||||
* @method stepForward
|
||||
*/
|
||||
stepForward() {
|
||||
this.player_.volume(this.player_.volume() + 0.1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrease volume level for keyboard users
|
||||
*
|
||||
* @method stepBack
|
||||
*/
|
||||
stepBack() {
|
||||
this.player_.volume(this.player_.volume() - 0.1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update ARIA accessibility attributes
|
||||
*
|
||||
* @method updateARIAAttributes
|
||||
*/
|
||||
updateARIAAttributes() {
|
||||
// Current value of volume bar as a percentage
|
||||
this.el_.setAttribute('aria-valuenow', roundFloat(this.player_.volume()*100, 2));
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file volume-control.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
|
||||
// Required children
|
||||
@ -8,7 +11,8 @@ import VolumeBar from './volume-bar.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class VolumeControl
|
||||
*/
|
||||
class VolumeControl extends Component {
|
||||
|
||||
@ -28,6 +32,12 @@ class VolumeControl extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-volume-control vjs-control'
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file volume-level.js
|
||||
*/
|
||||
import Component from '../../component.js';
|
||||
|
||||
/**
|
||||
@ -5,10 +8,17 @@ import Component from '../../component.js';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class VolumeLevel
|
||||
*/
|
||||
class VolumeLevel extends Component {
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-volume-level',
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file volume-menu-button.js
|
||||
*/
|
||||
import Button from '../button.js';
|
||||
import Component from '../component.js';
|
||||
import Menu from '../menu/menu.js';
|
||||
@ -6,8 +9,12 @@ import MuteToggle from './mute-toggle.js';
|
||||
import VolumeBar from './volume-control/volume-bar.js';
|
||||
|
||||
/**
|
||||
* Menu button with a popup for showing the volume slider.
|
||||
* @constructor
|
||||
* Button for volume menu
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @extends MenuButton
|
||||
* @class VolumeMenuButton
|
||||
*/
|
||||
class VolumeMenuButton extends MenuButton {
|
||||
|
||||
@ -31,10 +38,22 @@ class VolumeMenuButton extends MenuButton {
|
||||
this.addClass('vjs-menu-button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-volume-menu-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {Menu} The volume menu button
|
||||
* @method createMenu
|
||||
*/
|
||||
createMenu() {
|
||||
let menu = new Menu(this.player_, {
|
||||
contentElType: 'div'
|
||||
@ -56,6 +75,11 @@ class VolumeMenuButton extends MenuButton {
|
||||
return menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on volume menu and calls super
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
MuteToggle.prototype.handleClick.call(this);
|
||||
super.handleClick();
|
||||
|
@ -1,11 +1,16 @@
|
||||
/**
|
||||
* @file error-display.js
|
||||
*/
|
||||
import Component from './component';
|
||||
import * as Dom from './utils/dom.js';
|
||||
import * as Dom from './utils/dom.js';
|
||||
|
||||
/**
|
||||
* Display that an error has occurred making the video unplayable
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
*
|
||||
* @param {Object} player Main Player
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @extends Component
|
||||
* @class ErrorDisplay
|
||||
*/
|
||||
class ErrorDisplay extends Component {
|
||||
|
||||
@ -16,6 +21,12 @@ class ErrorDisplay extends Component {
|
||||
this.on(player, 'error', this.update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
var el = super.createEl('div', {
|
||||
className: 'vjs-error-display'
|
||||
@ -27,6 +38,11 @@ class ErrorDisplay extends Component {
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the error message in localized language
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
if (this.player().error()) {
|
||||
this.contentEl_.innerHTML = this.localize(this.player().error().message);
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file event-emitter.js
|
||||
*/
|
||||
import * as Events from './utils/events.js';
|
||||
|
||||
var EventEmitter = function() {};
|
||||
|
@ -1,4 +1,6 @@
|
||||
/**
|
||||
/*
|
||||
* @file extends.js
|
||||
*
|
||||
* A combination of node inherits and babel's inherits (after transpile).
|
||||
* Both work the same but node adds `super_` to the subClass
|
||||
* and Bable adds the superClass as __proto__. Both seem useful.
|
||||
@ -23,18 +25,17 @@ const _inherits = function (subClass, superClass) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Function for subclassing using the same inheritance that
|
||||
* videojs uses internally
|
||||
*
|
||||
* ```
|
||||
* ```js
|
||||
* var Button = videojs.getComponent('Button');
|
||||
*
|
||||
* ```
|
||||
* ```js
|
||||
* var MyButton = videojs.extends(Button, {
|
||||
* constructor: function(player, options) {
|
||||
* Button.call(this, player, options);
|
||||
* },
|
||||
*
|
||||
* onClick: function() {
|
||||
* // doSomething
|
||||
* }
|
||||
|
@ -1,6 +1,9 @@
|
||||
/**
|
||||
* @file fullscreen-api.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
|
||||
/**
|
||||
/*
|
||||
* Store the browser-specific methods for the fullscreen API
|
||||
* @type {Object|undefined}
|
||||
* @private
|
||||
|
@ -1,12 +1,16 @@
|
||||
/**
|
||||
* @file global-options.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
let navigator = window.navigator;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Global Player instance options, surfaced from Player.prototype.options_
|
||||
* options = Player.prototype.options_
|
||||
* All options should use string keys so they avoid
|
||||
* renaming by closure compiler
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
export default {
|
||||
|
@ -1,15 +1,23 @@
|
||||
/**
|
||||
* @file loading-spinner.js
|
||||
*/
|
||||
import Component from './component';
|
||||
|
||||
/* Loading Spinner
|
||||
================================================================================ */
|
||||
/**
|
||||
* Loading spinner for waiting events
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @constructor
|
||||
*
|
||||
* @extends Component
|
||||
* @class LoadingSpinner
|
||||
*/
|
||||
class LoadingSpinner extends Component {
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-loading-spinner'
|
||||
|
@ -1,7 +1,11 @@
|
||||
/**
|
||||
* @file media-error.js
|
||||
*/
|
||||
import assign from 'object.assign';
|
||||
|
||||
/**
|
||||
/*
|
||||
* Custom MediaError to mimic the HTML5 MediaError
|
||||
*
|
||||
* @param {Number} code The media error code
|
||||
*/
|
||||
let MediaError = function(code){
|
||||
@ -19,29 +23,32 @@ let MediaError = function(code){
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* The error code that refers two one of the defined
|
||||
* MediaError types
|
||||
*
|
||||
* @type {Number}
|
||||
*/
|
||||
MediaError.prototype.code = 0;
|
||||
|
||||
/**
|
||||
/*
|
||||
* An optional message to be shown with the error.
|
||||
* Message is not part of the HTML5 video spec
|
||||
* but allows for more informative custom errors.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
MediaError.prototype.message = '';
|
||||
|
||||
/**
|
||||
/*
|
||||
* An optional status code that can be set by plugins
|
||||
* to allow even more detail about the error.
|
||||
* For example the HLS plugin might provide the specific
|
||||
* HTTP status code that was returned when the error
|
||||
* occurred, then allowing a custom error overlay
|
||||
* to display more information.
|
||||
* @type {[type]}
|
||||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
MediaError.prototype.status = null;
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file menu-button.js
|
||||
*/
|
||||
import Button from '../button.js';
|
||||
import Component from '../component.js';
|
||||
import Menu from './menu.js';
|
||||
@ -7,9 +10,11 @@ import toTitleCase from '../utils/to-title-case.js';
|
||||
|
||||
/**
|
||||
* A button class with a popup menu
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Button
|
||||
* @class MenuButton
|
||||
*/
|
||||
class MenuButton extends Button {
|
||||
|
||||
@ -23,6 +28,11 @@ class MenuButton extends Button {
|
||||
this.el_.setAttribute('role', 'button');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update menu
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let menu = this.createMenu();
|
||||
|
||||
@ -35,6 +45,7 @@ class MenuButton extends Button {
|
||||
|
||||
/**
|
||||
* Track the state of the menu button
|
||||
*
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
@ -47,6 +58,12 @@ class MenuButton extends Button {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create menu
|
||||
*
|
||||
* @return {Menu} The constructed menu
|
||||
* @method createMenu
|
||||
*/
|
||||
createMenu() {
|
||||
var menu = new Menu(this.player_);
|
||||
|
||||
@ -73,33 +90,64 @@ class MenuButton extends Button {
|
||||
|
||||
/**
|
||||
* Create the list of menu items. Specific to each subclass.
|
||||
*
|
||||
* @method createItems
|
||||
*/
|
||||
createItems(){}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: this.buildCSSClass()
|
||||
});
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
/**
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @return {String} The constructed class name
|
||||
* @method buildCSSClass
|
||||
*/
|
||||
buildCSSClass() {
|
||||
return `vjs-menu-button ${super.buildCSSClass()}`;
|
||||
}
|
||||
|
||||
// Focus - Add keyboard functionality to element
|
||||
// This function is not needed anymore. Instead, the keyboard functionality is handled by
|
||||
// treating the button as triggering a submenu. When the button is pressed, the submenu
|
||||
// appears. Pressing the button again makes the submenu disappear.
|
||||
/**
|
||||
* Focus - Add keyboard functionality to element
|
||||
* This function is not needed anymore. Instead, the
|
||||
* keyboard functionality is handled by
|
||||
* treating the button as triggering a submenu.
|
||||
* When the button is pressed, the submenu
|
||||
* appears. Pressing the button again makes
|
||||
* the submenu disappear.
|
||||
*
|
||||
* @method handleFocus
|
||||
*/
|
||||
handleFocus() {}
|
||||
|
||||
// Can't turn off list display that we turned on with focus, because list would go away.
|
||||
/**
|
||||
* Can't turn off list display that we turned
|
||||
* on with focus, because list would go away.
|
||||
*
|
||||
* @method handleBlur
|
||||
*/
|
||||
handleBlur() {}
|
||||
|
||||
/**
|
||||
* When you click the button it adds focus, which
|
||||
* will show the menu indefinitely.
|
||||
* So we'll remove focus when the mouse leaves the button.
|
||||
* Focus is needed for tab navigation.
|
||||
* Allow sub components to stack CSS class names
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
// When you click the button it adds focus, which will show the menu indefinitely.
|
||||
// So we'll remove focus when the mouse leaves the button.
|
||||
// Focus is needed for tab navigation.
|
||||
this.one('mouseout', Fn.bind(this, function(){
|
||||
this.menu.unlockShowing();
|
||||
this.el_.blur();
|
||||
@ -111,6 +159,12 @@ class MenuButton extends Button {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle key press on menu
|
||||
*
|
||||
* @param {Object} Key press event
|
||||
* @method handleKeyPress
|
||||
*/
|
||||
handleKeyPress(event) {
|
||||
|
||||
// Check for space bar (32) or enter (13) keys
|
||||
@ -130,6 +184,11 @@ class MenuButton extends Button {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes changes based on button pressed
|
||||
*
|
||||
* @method pressButton
|
||||
*/
|
||||
pressButton() {
|
||||
this.buttonPressed_ = true;
|
||||
this.menu.lockShowing();
|
||||
@ -139,6 +198,11 @@ class MenuButton extends Button {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes changes based on button unpressed
|
||||
*
|
||||
* @method unpressButton
|
||||
*/
|
||||
unpressButton() {
|
||||
this.buttonPressed_ = false;
|
||||
this.menu.unlockShowing();
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file menu-item.js
|
||||
*/
|
||||
import Button from '../button.js';
|
||||
import Component from '../component.js';
|
||||
import assign from 'object.assign';
|
||||
@ -7,8 +10,8 @@ import assign from 'object.assign';
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @constructor
|
||||
* @extends Button
|
||||
* @class MenuItem
|
||||
*/
|
||||
class MenuItem extends Button {
|
||||
|
||||
@ -17,7 +20,14 @@ class MenuItem extends Button {
|
||||
this.selected(options['selected']);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @param {String=} type Desc
|
||||
* @param {Object=} props Desc
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(type, props) {
|
||||
return super.createEl('li', assign({
|
||||
className: 'vjs-menu-item',
|
||||
@ -27,6 +37,8 @@ class MenuItem extends Button {
|
||||
|
||||
/**
|
||||
* Handle a click on the menu item, and set it to selected
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
this.selected(true);
|
||||
@ -34,7 +46,9 @@ class MenuItem extends Button {
|
||||
|
||||
/**
|
||||
* Set this menu item as selected or not
|
||||
*
|
||||
* @param {Boolean} selected
|
||||
* @method selected
|
||||
*/
|
||||
selected(selected) {
|
||||
if (selected) {
|
||||
|
@ -1,24 +1,25 @@
|
||||
/**
|
||||
* @file menu.js
|
||||
*/
|
||||
import Component from '../component.js';
|
||||
import * as Dom from '../utils/dom.js';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
import * as Events from '../utils/events.js';
|
||||
|
||||
/* Menu
|
||||
================================================================================ */
|
||||
/**
|
||||
* The Menu component is used to build pop up menus, including subtitle and
|
||||
* captions selection menus.
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @class
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class Menu
|
||||
*/
|
||||
class Menu extends Component {
|
||||
|
||||
/**
|
||||
* Add a menu item to the menu
|
||||
*
|
||||
* @param {Object|String} component Component or component type to add
|
||||
* @method addItem
|
||||
*/
|
||||
addItem(component) {
|
||||
this.addChild(component);
|
||||
@ -27,6 +28,12 @@ class Menu extends Component {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let contentElType = this.options_.contentElType || 'ul';
|
||||
this.contentEl_ = Dom.createEl(contentElType, {
|
||||
|
539
src/js/player.js
539
src/js/player.js
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file plugins.js
|
||||
*/
|
||||
import Player from './player.js';
|
||||
|
||||
/**
|
||||
@ -5,6 +8,7 @@ import Player from './player.js';
|
||||
*
|
||||
* @param {String} name The name of the plugin
|
||||
* @param {Function} init The function that is run when the player inits
|
||||
* @method plugin
|
||||
*/
|
||||
var plugin = function(name, init){
|
||||
Player.prototype[name] = init;
|
||||
|
@ -1,17 +1,19 @@
|
||||
/**
|
||||
* @file poster-image.js
|
||||
*/
|
||||
import Button from './button.js';
|
||||
import Component from './component.js';
|
||||
import * as Fn from './utils/fn.js';
|
||||
import * as Dom from './utils/dom.js';
|
||||
import * as browser from './utils/browser.js';
|
||||
|
||||
/* Poster Image
|
||||
================================================================================ */
|
||||
/**
|
||||
* The component that handles showing the poster image.
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Button
|
||||
* @class PosterImage
|
||||
*/
|
||||
class PosterImage extends Button {
|
||||
|
||||
@ -24,6 +26,8 @@ class PosterImage extends Button {
|
||||
|
||||
/**
|
||||
* Clean up the poster image
|
||||
*
|
||||
* @method dispose
|
||||
*/
|
||||
dispose() {
|
||||
this.player().off('posterchange', this.update);
|
||||
@ -31,8 +35,10 @@ class PosterImage extends Button {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the poster image element
|
||||
* Create the poster's image element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = Dom.createEl('div', {
|
||||
@ -56,6 +62,8 @@ class PosterImage extends Button {
|
||||
|
||||
/**
|
||||
* Event handler for updates to the player's poster source
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
let url = this.player().poster();
|
||||
@ -73,6 +81,9 @@ class PosterImage extends Button {
|
||||
|
||||
/**
|
||||
* Set the poster source depending on the display method
|
||||
*
|
||||
* @param {String} url The URL to the poster source
|
||||
* @method setSrc
|
||||
*/
|
||||
setSrc(url) {
|
||||
if (this.fallbackImg_) {
|
||||
@ -91,6 +102,8 @@ class PosterImage extends Button {
|
||||
|
||||
/**
|
||||
* Event handler for clicks on the poster image
|
||||
*
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick() {
|
||||
// We don't want a click to trigger playback when controls are disabled
|
||||
|
@ -1,3 +1,9 @@
|
||||
/**
|
||||
* @file setup.js
|
||||
*
|
||||
* Functions for automatically setting up a player
|
||||
* based on the data-setup attribute of the video tag
|
||||
*/
|
||||
import * as Events from './utils/events.js';
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
@ -5,10 +11,6 @@ import window from 'global/window';
|
||||
let _windowLoaded = false;
|
||||
let videojs;
|
||||
|
||||
/**
|
||||
* @fileoverview Functions for automatically setting up a player
|
||||
* based on the data-setup attribute of the video tag
|
||||
*/
|
||||
|
||||
// Automatically set up any tags that have a data-setup attribute
|
||||
var autoSetup = function(){
|
||||
|
@ -1,17 +1,19 @@
|
||||
/**
|
||||
* @file slider.js
|
||||
*/
|
||||
import Component from '../component.js';
|
||||
import * as Dom from '../utils/dom.js';
|
||||
import roundFloat from '../utils/round-float.js';
|
||||
import document from 'global/document';
|
||||
import assign from 'object.assign';
|
||||
|
||||
/* Slider
|
||||
================================================================================ */
|
||||
/**
|
||||
* The base functionality for sliders like the volume bar and seek bar
|
||||
*
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @constructor
|
||||
* @extends Component
|
||||
* @class Slider
|
||||
*/
|
||||
class Slider extends Component {
|
||||
|
||||
@ -35,6 +37,14 @@ class Slider extends Component {
|
||||
this.on(player, this.playerEvent, this.update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @param {String} type Type of element to create
|
||||
* @param {Object=} props List of properties in Object form
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl(type, props={}) {
|
||||
// Add the slider element class to all sub classes
|
||||
props.className = props.className + ' vjs-slider';
|
||||
@ -49,6 +59,12 @@ class Slider extends Component {
|
||||
return super.createEl(type, props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse down on slider
|
||||
*
|
||||
* @param {Object} event Mouse down event object
|
||||
* @method handleMouseDown
|
||||
*/
|
||||
handleMouseDown(event) {
|
||||
event.preventDefault();
|
||||
Dom.blockTextSelection();
|
||||
@ -62,9 +78,18 @@ class Slider extends Component {
|
||||
this.handleMouseMove(event);
|
||||
}
|
||||
|
||||
// To be overridden by a subclass
|
||||
/**
|
||||
* To be overridden by a subclass
|
||||
*
|
||||
* @method handleMouseMove
|
||||
*/
|
||||
handleMouseMove() {}
|
||||
|
||||
/**
|
||||
* Handle mouse up on Slider
|
||||
*
|
||||
* @method handleMouseUp
|
||||
*/
|
||||
handleMouseUp() {
|
||||
Dom.unblockTextSelection();
|
||||
this.removeClass('vjs-sliding');
|
||||
@ -77,6 +102,11 @@ class Slider extends Component {
|
||||
this.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update slider
|
||||
*
|
||||
* @method update
|
||||
*/
|
||||
update() {
|
||||
// In VolumeBar init we have a setTimeout for update that pops and update to the end of the
|
||||
// execution stack. The player is destroyed before then update will cause an error
|
||||
@ -110,6 +140,12 @@ class Slider extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate distance for slider
|
||||
*
|
||||
* @param {Object} event Event object
|
||||
* @method calculateDistance
|
||||
*/
|
||||
calculateDistance(event){
|
||||
let el = this.el_;
|
||||
let box = Dom.findElPosition(el);
|
||||
@ -160,10 +196,21 @@ class Slider extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle on focus for slider
|
||||
*
|
||||
* @method handleFocus
|
||||
*/
|
||||
handleFocus() {
|
||||
this.on(document, 'keydown', this.handleKeyPress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle key press for slider
|
||||
*
|
||||
* @param {Object} event Event object
|
||||
* @method handleKeyPress
|
||||
*/
|
||||
handleKeyPress(event) {
|
||||
if (event.which === 37 || event.which === 40) { // Left and Down Arrows
|
||||
event.preventDefault();
|
||||
@ -174,6 +221,11 @@ class Slider extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle on blur for slider
|
||||
*
|
||||
* @method handleBlur
|
||||
*/
|
||||
handleBlur() {
|
||||
this.off(document, 'keydown', this.handleKeyPress);
|
||||
}
|
||||
@ -181,13 +233,22 @@ class Slider extends Component {
|
||||
/**
|
||||
* Listener for click events on slider, used to prevent clicks
|
||||
* from bubbling up to parent elements like button menus.
|
||||
* @param {Object} event Event object
|
||||
*
|
||||
* @param {Object} event Event object
|
||||
* @method handleClick
|
||||
*/
|
||||
handleClick(event) {
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set if slider is horizontal for vertical
|
||||
*
|
||||
* @param {Boolean} bool True if slider is vertical, false is horizontal
|
||||
* @return {Boolean} True if slider is vertical, false is horizontal
|
||||
* @method vertical
|
||||
*/
|
||||
vertical(bool) {
|
||||
if (bool === undefined) {
|
||||
return this.vertical_ || false;
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file flash-rtmp.js
|
||||
*/
|
||||
function FlashRtmpDecorator(Flash) {
|
||||
Flash.streamingFormats = {
|
||||
'rtmp/mp4': 'MP4',
|
||||
|
@ -1,5 +1,6 @@
|
||||
/**
|
||||
* @fileoverview VideoJS-SWF - Custom Flash Player with HTML5-ish API
|
||||
* @file flash.js
|
||||
* VideoJS-SWF - Custom Flash Player with HTML5-ish API
|
||||
* https://github.com/zencoder/video-js-swf
|
||||
* Not using setupTriggers. Using global onEvent func to distribute events
|
||||
*/
|
||||
@ -17,10 +18,10 @@ let navigator = window.navigator;
|
||||
/**
|
||||
* Flash Media Controller - Wrapper for fallback SWF API
|
||||
*
|
||||
* @param {Player} player
|
||||
* @param {Object=} options
|
||||
* @param {Function=} ready
|
||||
* @constructor
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends Tech
|
||||
* @class Flash
|
||||
*/
|
||||
class Flash extends Tech {
|
||||
|
||||
@ -55,6 +56,12 @@ class Flash extends Tech {
|
||||
window.videojs.Flash.onError = Flash.onError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let options = this.options_;
|
||||
|
||||
@ -96,14 +103,31 @@ class Flash extends Tech {
|
||||
return this.el_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Play for flash tech
|
||||
*
|
||||
* @method play
|
||||
*/
|
||||
play() {
|
||||
this.el_.vjs_play();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause for flash tech
|
||||
*
|
||||
* @method pause
|
||||
*/
|
||||
pause() {
|
||||
this.el_.vjs_pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set video
|
||||
*
|
||||
* @param {Object=} src Source object
|
||||
* @return {Object}
|
||||
* @method src
|
||||
*/
|
||||
src(src) {
|
||||
if (src === undefined) {
|
||||
return this.currentSrc();
|
||||
@ -113,6 +137,13 @@ class Flash extends Tech {
|
||||
return this.setSrc(src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set video
|
||||
*
|
||||
* @param {Object=} src Source object
|
||||
* @deprecated
|
||||
* @method setSrc
|
||||
*/
|
||||
setSrc(src) {
|
||||
// Make sure source URL is absolute.
|
||||
src = Url.getAbsoluteURL(src);
|
||||
@ -126,12 +157,25 @@ class Flash extends Tech {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current time
|
||||
*
|
||||
* @param {Number} time Current time of video
|
||||
* @method setCurrentTime
|
||||
*/
|
||||
setCurrentTime(time) {
|
||||
this.lastSeekTarget_ = time;
|
||||
this.el_.vjs_setProperty('currentTime', time);
|
||||
super.setCurrentTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current time
|
||||
*
|
||||
* @param {Number=} time Current time of video
|
||||
* @return {Number} Current time
|
||||
* @method currentTime
|
||||
*/
|
||||
currentTime(time) {
|
||||
// when seeking make the reported time keep up with the requested time
|
||||
// by reading the time we're seeking to
|
||||
@ -141,6 +185,11 @@ class Flash extends Tech {
|
||||
return this.el_.vjs_getProperty('currentTime');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current source
|
||||
*
|
||||
* @method currentSrc
|
||||
*/
|
||||
currentSrc() {
|
||||
if (this.currentSource_) {
|
||||
return this.currentSource_.src;
|
||||
@ -149,17 +198,37 @@ class Flash extends Tech {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load media into player
|
||||
*
|
||||
* @method load
|
||||
*/
|
||||
load() {
|
||||
this.el_.vjs_load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get poster
|
||||
*
|
||||
* @method poster
|
||||
*/
|
||||
poster() {
|
||||
this.el_.vjs_getProperty('poster');
|
||||
}
|
||||
|
||||
// poster images are not handled by the Flash tech so make this a no-op
|
||||
/**
|
||||
* Poster images are not handled by the Flash tech so make this a no-op
|
||||
*
|
||||
* @method setPoster
|
||||
*/
|
||||
setPoster() {}
|
||||
|
||||
/**
|
||||
* Determine if can seek in media
|
||||
*
|
||||
* @return {TimeRangeObject}
|
||||
* @method seekable
|
||||
*/
|
||||
seekable() {
|
||||
const duration = this.duration();
|
||||
if (duration === 0) {
|
||||
@ -168,14 +237,36 @@ class Flash extends Tech {
|
||||
return createTimeRange(0, duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get buffered time range
|
||||
*
|
||||
* @return {TimeRangeObject}
|
||||
* @method buffered
|
||||
*/
|
||||
buffered() {
|
||||
return createTimeRange(0, this.el_.vjs_getProperty('buffered'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fullscreen support -
|
||||
* Flash does not allow fullscreen through javascript
|
||||
* so always returns false
|
||||
*
|
||||
* @return {Boolean} false
|
||||
* @method supportsFullScreen
|
||||
*/
|
||||
supportsFullScreen() {
|
||||
return false; // Flash does not allow fullscreen through javascript
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to enter fullscreen
|
||||
* Flash does not allow fullscreen through javascript
|
||||
* so always returns false
|
||||
*
|
||||
* @return {Boolean} false
|
||||
* @method enterFullScreen
|
||||
*/
|
||||
enterFullScreen() {
|
||||
return false;
|
||||
}
|
||||
@ -217,16 +308,18 @@ Flash.isSupported = function(){
|
||||
// Add Source Handler pattern functions to this tech
|
||||
Tech.withSourceHandlers(Flash);
|
||||
|
||||
/**
|
||||
/*
|
||||
* The default native source handler.
|
||||
* This simply passes the source to the video element. Nothing fancy.
|
||||
*
|
||||
* @param {Object} source The source object
|
||||
* @param {Flash} tech The instance of the Flash tech
|
||||
*/
|
||||
Flash.nativeSourceHandler = {};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check Flash can handle the source natively
|
||||
*
|
||||
* @param {Object} source The source object
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
@ -255,10 +348,11 @@ Flash.nativeSourceHandler.canHandleSource = function(source){
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Pass the source to the flash object
|
||||
* Adaptive source handlers will have more complicated workflows before passing
|
||||
* video data to the video element
|
||||
*
|
||||
* @param {Object} source The source object
|
||||
* @param {Flash} tech The instance of the Flash tech
|
||||
*/
|
||||
@ -266,7 +360,7 @@ Flash.nativeSourceHandler.handleSource = function(source, tech){
|
||||
tech.setSrc(source.src);
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Clean up the source handler when disposing the player or switching sources..
|
||||
* (no cleanup is needed when supporting the format natively)
|
||||
*/
|
||||
|
@ -1,5 +1,6 @@
|
||||
/**
|
||||
* @fileoverview HTML5 Media Controller - Wrapper for HTML5 Media API
|
||||
* @file html5.js
|
||||
* HTML5 Media Controller - Wrapper for HTML5 Media API
|
||||
*/
|
||||
|
||||
import Tech from './tech.js';
|
||||
@ -16,10 +17,11 @@ import mergeOptions from '../utils/merge-options.js';
|
||||
|
||||
/**
|
||||
* HTML5 Media Controller - Wrapper for HTML5 Media API
|
||||
* @param {Player|Object} player
|
||||
* @param {Object=} options
|
||||
* @param {Function=} ready
|
||||
* @constructor
|
||||
*
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends Tech
|
||||
* @class Html5
|
||||
*/
|
||||
class Html5 extends Tech {
|
||||
|
||||
@ -78,12 +80,22 @@ class Html5 extends Tech {
|
||||
this.triggerReady();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dispose of html5 media element
|
||||
*
|
||||
* @method dispose
|
||||
*/
|
||||
dispose() {
|
||||
Html5.disposeMediaElement(this.el_);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
let el = this.options_.tag;
|
||||
|
||||
@ -147,6 +159,11 @@ class Html5 extends Tech {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hide captions from text track
|
||||
*
|
||||
* @method hideCaptions
|
||||
*/
|
||||
hideCaptions() {
|
||||
let tracks = this.el_.querySelectorAll('track');
|
||||
let i = tracks.length;
|
||||
@ -164,11 +181,42 @@ class Html5 extends Tech {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Play for html5 tech
|
||||
*
|
||||
* @method play
|
||||
*/
|
||||
play() { this.el_.play(); }
|
||||
|
||||
/**
|
||||
* Pause for html5 tech
|
||||
*
|
||||
* @method pause
|
||||
*/
|
||||
pause() { this.el_.pause(); }
|
||||
|
||||
/**
|
||||
* Paused for html5 tech
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method paused
|
||||
*/
|
||||
paused() { return this.el_.paused; }
|
||||
|
||||
/**
|
||||
* Get current time
|
||||
*
|
||||
* @return {Number}
|
||||
* @method currentTime
|
||||
*/
|
||||
currentTime() { return this.el_.currentTime; }
|
||||
|
||||
/**
|
||||
* Set current time
|
||||
*
|
||||
* @param {Number} seconds Current time of video
|
||||
* @method setCurrentTime
|
||||
*/
|
||||
setCurrentTime(seconds) {
|
||||
try {
|
||||
this.el_.currentTime = seconds;
|
||||
@ -178,19 +226,78 @@ class Html5 extends Tech {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get duration
|
||||
*
|
||||
* @return {Number}
|
||||
* @method duration
|
||||
*/
|
||||
duration() { return this.el_.duration || 0; }
|
||||
|
||||
/**
|
||||
* Get a TimeRange object that represents the intersection
|
||||
* of the time ranges for which the user agent has all
|
||||
* relevant media
|
||||
*
|
||||
* @return {TimeRangeObject}
|
||||
* @method buffered
|
||||
*/
|
||||
buffered() { return this.el_.buffered; }
|
||||
|
||||
/**
|
||||
* Get volume level
|
||||
*
|
||||
* @return {Number}
|
||||
* @method volume
|
||||
*/
|
||||
volume() { return this.el_.volume; }
|
||||
|
||||
/**
|
||||
* Set volume level
|
||||
*
|
||||
* @param {Number} percentAsDecimal Volume percent as a decimal
|
||||
* @method setVolume
|
||||
*/
|
||||
setVolume(percentAsDecimal) { this.el_.volume = percentAsDecimal; }
|
||||
|
||||
/**
|
||||
* Get if muted
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method muted
|
||||
*/
|
||||
muted() { return this.el_.muted; }
|
||||
|
||||
/**
|
||||
* Set muted
|
||||
*
|
||||
* @param {Boolean} If player is to be muted or note
|
||||
* @method setMuted
|
||||
*/
|
||||
setMuted(muted) { this.el_.muted = muted; }
|
||||
|
||||
/**
|
||||
* Get player width
|
||||
*
|
||||
* @return {Number}
|
||||
* @method width
|
||||
*/
|
||||
width() { return this.el_.offsetWidth; }
|
||||
|
||||
/**
|
||||
* Get player height
|
||||
*
|
||||
* @return {Number}
|
||||
* @method height
|
||||
*/
|
||||
height() { return this.el_.offsetHeight; }
|
||||
|
||||
/**
|
||||
* Get if there is fullscreen support
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method supportsFullScreen
|
||||
*/
|
||||
supportsFullScreen() {
|
||||
if (typeof this.el_.webkitEnterFullScreen === 'function') {
|
||||
let userAgent = window.navigator.userAgent;
|
||||
@ -202,6 +309,11 @@ class Html5 extends Tech {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to enter fullscreen
|
||||
*
|
||||
* @method enterFullScreen
|
||||
*/
|
||||
enterFullScreen() {
|
||||
var video = this.el_;
|
||||
|
||||
@ -231,10 +343,22 @@ class Html5 extends Tech {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to exit fullscreen
|
||||
*
|
||||
* @method exitFullScreen
|
||||
*/
|
||||
exitFullScreen() {
|
||||
this.el_.webkitExitFullScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/set video
|
||||
*
|
||||
* @param {Object=} src Source object
|
||||
* @return {Object}
|
||||
* @method src
|
||||
*/
|
||||
src(src) {
|
||||
if (src === undefined) {
|
||||
return this.el_.src;
|
||||
@ -244,42 +368,220 @@ class Html5 extends Tech {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set video
|
||||
*
|
||||
* @param {Object} src Source object
|
||||
* @deprecated
|
||||
* @method setSrc
|
||||
*/
|
||||
setSrc(src) { this.el_.src = src; }
|
||||
|
||||
/**
|
||||
* Load media into player
|
||||
*
|
||||
* @method load
|
||||
*/
|
||||
load(){ this.el_.load(); }
|
||||
|
||||
/**
|
||||
* Get current source
|
||||
*
|
||||
* @return {Object}
|
||||
* @method currentSrc
|
||||
*/
|
||||
currentSrc() { return this.el_.currentSrc; }
|
||||
|
||||
/**
|
||||
* Get poster
|
||||
*
|
||||
* @return {String}
|
||||
* @method poster
|
||||
*/
|
||||
poster() { return this.el_.poster; }
|
||||
|
||||
/**
|
||||
* Set poster
|
||||
*
|
||||
* @param {String} val URL to poster image
|
||||
* @method
|
||||
*/
|
||||
setPoster(val) { this.el_.poster = val; }
|
||||
|
||||
/**
|
||||
* Get preload attribute
|
||||
*
|
||||
* @return {String}
|
||||
* @method preload
|
||||
*/
|
||||
preload() { return this.el_.preload; }
|
||||
|
||||
/**
|
||||
* Set preload attribute
|
||||
*
|
||||
* @param {String} val Value for preload attribute
|
||||
* @method setPreload
|
||||
*/
|
||||
setPreload(val) { this.el_.preload = val; }
|
||||
|
||||
/**
|
||||
* Get autoplay attribute
|
||||
*
|
||||
* @return {String}
|
||||
* @method autoplay
|
||||
*/
|
||||
autoplay() { return this.el_.autoplay; }
|
||||
|
||||
/**
|
||||
* Set autoplay attribute
|
||||
*
|
||||
* @param {String} val Value for preload attribute
|
||||
* @method setAutoplay
|
||||
*/
|
||||
setAutoplay(val) { this.el_.autoplay = val; }
|
||||
|
||||
/**
|
||||
* Get controls attribute
|
||||
*
|
||||
* @return {String}
|
||||
* @method controls
|
||||
*/
|
||||
controls() { return this.el_.controls; }
|
||||
|
||||
/**
|
||||
* Set controls attribute
|
||||
*
|
||||
* @param {String} val Value for controls attribute
|
||||
* @method setControls
|
||||
*/
|
||||
setControls(val) { this.el_.controls = !!val; }
|
||||
|
||||
/**
|
||||
* Get loop attribute
|
||||
*
|
||||
* @return {String}
|
||||
* @method loop
|
||||
*/
|
||||
loop() { return this.el_.loop; }
|
||||
|
||||
/**
|
||||
* Set loop attribute
|
||||
*
|
||||
* @param {String} val Value for loop attribute
|
||||
* @method setLoop
|
||||
*/
|
||||
setLoop(val) { this.el_.loop = val; }
|
||||
|
||||
/**
|
||||
* Get error value
|
||||
*
|
||||
* @return {String}
|
||||
* @method error
|
||||
*/
|
||||
error() { return this.el_.error; }
|
||||
|
||||
/**
|
||||
* Get whether or not the player is in the "seeking" state
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method seeking
|
||||
*/
|
||||
seeking() { return this.el_.seeking; }
|
||||
|
||||
/**
|
||||
* Get a TimeRanges object that represents the
|
||||
* ranges of the media resource to which it is possible
|
||||
* for the user agent to seek.
|
||||
*
|
||||
* @return {TimeRangeObject}
|
||||
* @method seekable
|
||||
*/
|
||||
seekable() { return this.el_.seekable; }
|
||||
|
||||
/**
|
||||
* Get if video ended
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method ended
|
||||
*/
|
||||
ended() { return this.el_.ended; }
|
||||
|
||||
/**
|
||||
* Get the value of the muted content attribute
|
||||
* This attribute has no dynamic effect, it only
|
||||
* controls the default state of the element
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method defaultMuted
|
||||
*/
|
||||
defaultMuted() { return this.el_.defaultMuted; }
|
||||
|
||||
/**
|
||||
* Get desired speed at which the media resource is to play
|
||||
*
|
||||
* @return {Number}
|
||||
* @method playbackRate
|
||||
*/
|
||||
playbackRate() { return this.el_.playbackRate; }
|
||||
|
||||
/**
|
||||
* Set desired speed at which the media resource is to play
|
||||
*
|
||||
* @param {Number} val Speed at which the media resource is to play
|
||||
* @method setPlaybackRate
|
||||
*/
|
||||
setPlaybackRate(val) { this.el_.playbackRate = val; }
|
||||
|
||||
/**
|
||||
* Get the current state of network activity for the element, from
|
||||
* the list below
|
||||
* NETWORK_EMPTY (numeric value 0)
|
||||
* NETWORK_IDLE (numeric value 1)
|
||||
* NETWORK_LOADING (numeric value 2)
|
||||
* NETWORK_NO_SOURCE (numeric value 3)
|
||||
*
|
||||
* @return {Number}
|
||||
* @method networkState
|
||||
*/
|
||||
networkState() { return this.el_.networkState; }
|
||||
|
||||
/**
|
||||
* Get a value that expresses the current state of the element
|
||||
* with respect to rendering the current playback position, from
|
||||
* the codes in the list below
|
||||
* HAVE_NOTHING (numeric value 0)
|
||||
* HAVE_METADATA (numeric value 1)
|
||||
* HAVE_CURRENT_DATA (numeric value 2)
|
||||
* HAVE_FUTURE_DATA (numeric value 3)
|
||||
* HAVE_ENOUGH_DATA (numeric value 4)
|
||||
*
|
||||
* @return {Number}
|
||||
* @method readyState
|
||||
*/
|
||||
readyState() { return this.el_.readyState; }
|
||||
|
||||
/**
|
||||
* Get width of video
|
||||
*
|
||||
* @return {Number}
|
||||
* @method videoWidth
|
||||
*/
|
||||
videoWidth() { return this.el_.videoWidth; }
|
||||
|
||||
/**
|
||||
* Get height of video
|
||||
*
|
||||
* @return {Number}
|
||||
* @method videoHeight
|
||||
*/
|
||||
videoHeight() { return this.el_.videoHeight; }
|
||||
|
||||
/**
|
||||
* Get text tracks
|
||||
*
|
||||
* @return {TextTrackList}
|
||||
* @method textTracks
|
||||
*/
|
||||
textTracks() {
|
||||
if (!this['featuresNativeTextTracks']) {
|
||||
return super.textTracks();
|
||||
@ -287,6 +589,17 @@ class Html5 extends Tech {
|
||||
|
||||
return this.el_.textTracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a text track object
|
||||
*
|
||||
* @param {String} kind Text track kind (subtitles, captions, descriptions
|
||||
* chapters and metadata)
|
||||
* @param {String=} label Label to identify the text track
|
||||
* @param {String=} language Two letter language abbreviation
|
||||
* @return {TextTrackObject}
|
||||
* @method addTextTrack
|
||||
*/
|
||||
addTextTrack(kind, label, language) {
|
||||
if (!this['featuresNativeTextTracks']) {
|
||||
return super.addTextTrack(kind, label, language);
|
||||
@ -295,6 +608,14 @@ class Html5 extends Tech {
|
||||
return this.el_.addTextTrack(kind, label, language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a remote text track object
|
||||
*
|
||||
* @param {Object} options The object should contain values for
|
||||
* kind, language, label and src (location of the WebVTT file)
|
||||
* @return {TextTrackObject}
|
||||
* @method addRemoteTextTrack
|
||||
*/
|
||||
addRemoteTextTrack(options={}) {
|
||||
if (!this['featuresNativeTextTracks']) {
|
||||
return super.addRemoteTextTrack(options);
|
||||
@ -346,6 +667,12 @@ class Html5 extends Tech {
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove remote text track from TextTrackList object
|
||||
*
|
||||
* @param {TextTrackObject} track Texttrack object to remove
|
||||
* @method removeRemoteTextTrack
|
||||
*/
|
||||
removeRemoteTextTrack(track) {
|
||||
if (!this['featuresNativeTextTracks']) {
|
||||
return super.removeRemoteTextTrack(track);
|
||||
@ -370,12 +697,13 @@ class Html5 extends Tech {
|
||||
|
||||
/* HTML5 Support Testing ---------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Element for testing browser HTML5 video capabilities
|
||||
* @type {Element}
|
||||
* @constant
|
||||
* @private
|
||||
*/
|
||||
/*
|
||||
* Element for testing browser HTML5 video capabilities
|
||||
*
|
||||
* @type {Element}
|
||||
* @constant
|
||||
* @private
|
||||
*/
|
||||
Html5.TEST_VID = document.createElement('video');
|
||||
let track = document.createElement('track');
|
||||
track.kind = 'captions';
|
||||
@ -383,8 +711,9 @@ track.srclang = 'en';
|
||||
track.label = 'English';
|
||||
Html5.TEST_VID.appendChild(track);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check if HTML5 video is supported by this browser/device
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Html5.isSupported = function(){
|
||||
@ -401,16 +730,18 @@ Html5.isSupported = function(){
|
||||
// Add Source Handler pattern functions to this tech
|
||||
Tech.withSourceHandlers(Html5);
|
||||
|
||||
/**
|
||||
/*
|
||||
* The default native source handler.
|
||||
* This simply passes the source to the video element. Nothing fancy.
|
||||
*
|
||||
* @param {Object} source The source object
|
||||
* @param {Html5} tech The instance of the HTML5 tech
|
||||
*/
|
||||
Html5.nativeSourceHandler = {};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check if the video element can handle the source natively
|
||||
*
|
||||
* @param {Object} source The source object
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
@ -440,10 +771,11 @@ Html5.nativeSourceHandler.canHandleSource = function(source){
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Pass the source to the video element
|
||||
* Adaptive source handlers will have more complicated workflows before passing
|
||||
* video data to the video element
|
||||
*
|
||||
* @param {Object} source The source object
|
||||
* @param {Html5} tech The instance of the Html5 tech
|
||||
*/
|
||||
@ -451,19 +783,20 @@ Html5.nativeSourceHandler.handleSource = function(source, tech){
|
||||
tech.setSrc(source.src);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clean up the source handler when disposing the player or switching sources..
|
||||
* (no cleanup is needed when supporting the format natively)
|
||||
*/
|
||||
/*
|
||||
* Clean up the source handler when disposing the player or switching sources..
|
||||
* (no cleanup is needed when supporting the format natively)
|
||||
*/
|
||||
Html5.nativeSourceHandler.dispose = function(){};
|
||||
|
||||
// Register the native source handler
|
||||
Html5.registerSourceHandler(Html5.nativeSourceHandler);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check if the volume can be changed in this browser/device.
|
||||
* Volume cannot be changed in a lot of mobile devices.
|
||||
* Specifically, it can't be changed from 1 on iOS.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Html5.canControlVolume = function(){
|
||||
@ -472,9 +805,10 @@ Html5.canControlVolume = function(){
|
||||
return volume !== Html5.TEST_VID.volume;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check if playbackRate is supported in this browser/device.
|
||||
* @return {[type]} [description]
|
||||
*
|
||||
* @return {Number} [description]
|
||||
*/
|
||||
Html5.canControlPlaybackRate = function(){
|
||||
var playbackRate = Html5.TEST_VID.playbackRate;
|
||||
@ -482,8 +816,9 @@ Html5.canControlPlaybackRate = function(){
|
||||
return playbackRate !== Html5.TEST_VID.playbackRate;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Check to see if native text tracks are supported by this browser/device
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Html5.supportsNativeTextTracks = function() {
|
||||
@ -505,40 +840,44 @@ Html5.supportsNativeTextTracks = function() {
|
||||
return supportsTextTracks;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Set the tech's volume control support status
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Html5.prototype['featuresVolumeControl'] = Html5.canControlVolume();
|
||||
|
||||
/**
|
||||
/*
|
||||
* Set the tech's playbackRate support status
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Html5.prototype['featuresPlaybackRate'] = Html5.canControlPlaybackRate();
|
||||
|
||||
/**
|
||||
/*
|
||||
* Set the tech's status on moving the video element.
|
||||
* In iOS, if you move a video element in the DOM, it breaks video playback.
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Html5.prototype['movingMediaElementInDOM'] = !browser.IS_IOS;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Set the the tech's fullscreen resize support status.
|
||||
* HTML video is able to automatically resize when going to fullscreen.
|
||||
* (No longer appears to be used. Can probably be removed.)
|
||||
*/
|
||||
Html5.prototype['featuresFullscreenResize'] = true;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Set the tech's progress event support status
|
||||
* (this disables the manual progress events of the Tech)
|
||||
*/
|
||||
Html5.prototype['featuresProgressEvents'] = true;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Sets the tech's status on native text track support
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
Html5.prototype['featuresNativeTextTracks'] = Html5.supportsNativeTextTracks();
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file loader.js
|
||||
*/
|
||||
import Component from '../component';
|
||||
import window from 'global/window';
|
||||
import toTitleCase from '../utils/to-title-case.js';
|
||||
@ -6,7 +9,11 @@ import toTitleCase from '../utils/to-title-case.js';
|
||||
* The Media Loader is the component that decides which playback technology to load
|
||||
* when the player is initialized.
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} player Main Player
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends Component
|
||||
* @class MediaLoader
|
||||
*/
|
||||
class MediaLoader extends Component {
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/**
|
||||
* @fileoverview Media Technology Controller - Base class for media playback
|
||||
* @file tech.js
|
||||
* Media Technology Controller - Base class for media playback
|
||||
* technology controllers like Flash and HTML5
|
||||
*/
|
||||
|
||||
@ -15,9 +16,11 @@ import document from 'global/document';
|
||||
|
||||
/**
|
||||
* Base class for media (HTML5 Video, Flash) controllers
|
||||
* @param {Player|Object} player Central player instance
|
||||
*
|
||||
* @param {Object=} options Options object
|
||||
* @constructor
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends Component
|
||||
* @class Tech
|
||||
*/
|
||||
class Tech extends Component {
|
||||
|
||||
@ -61,19 +64,18 @@ class Tech extends Component {
|
||||
* on a mobile device a click on the video toggles controls.
|
||||
* (toggling controls is done by toggling the user state between active and
|
||||
* inactive)
|
||||
*
|
||||
* A tap can signal that a user has become active, or has become inactive
|
||||
* e.g. a quick tap on an iPhone movie should reveal the controls. Another
|
||||
* quick tap should hide them again (signaling the user is in an inactive
|
||||
* viewing state)
|
||||
*
|
||||
* In addition to this, we still want the user to be considered inactive after
|
||||
* a few seconds of inactivity.
|
||||
*
|
||||
* Note: the only part of iOS interaction we can't mimic with this setup
|
||||
* is a touch and hold on the video element counting as activity in order to
|
||||
* keep the controls showing, but that shouldn't be an issue. A touch and hold on
|
||||
* any controls will still keep the user active
|
||||
*
|
||||
* @method initControlsListeners
|
||||
*/
|
||||
initControlsListeners() {
|
||||
// if we're loading the playback object after it has started loading or playing the
|
||||
@ -92,6 +94,11 @@ class Tech extends Component {
|
||||
================================================================================ */
|
||||
// Manually trigger progress events based on changes to the buffered amount
|
||||
// Many flash players and older HTML5 browsers don't send progress or progress-like events
|
||||
/**
|
||||
* Turn on progress events
|
||||
*
|
||||
* @method manualProgressOn
|
||||
*/
|
||||
manualProgressOn() {
|
||||
this.on('durationchange', this.onDurationChange);
|
||||
|
||||
@ -101,6 +108,11 @@ class Tech extends Component {
|
||||
this.trackProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn off progress events
|
||||
*
|
||||
* @method manualProgressOff
|
||||
*/
|
||||
manualProgressOff() {
|
||||
this.manualProgress = false;
|
||||
this.stopTrackingProgress();
|
||||
@ -108,6 +120,11 @@ class Tech extends Component {
|
||||
this.off('durationchange', this.onDurationChange);
|
||||
}
|
||||
|
||||
/**
|
||||
* Track progress
|
||||
*
|
||||
* @method trackProgress
|
||||
*/
|
||||
trackProgress() {
|
||||
this.progressInterval = this.setInterval(Fn.bind(this, function(){
|
||||
// Don't trigger unless buffered amount is greater than last time
|
||||
@ -126,23 +143,50 @@ class Tech extends Component {
|
||||
}), 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update duration
|
||||
*
|
||||
* @method onDurationChange
|
||||
*/
|
||||
onDurationChange() {
|
||||
this.duration_ = this.duration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and get TimeRange object for buffering
|
||||
*
|
||||
* @return {TimeRangeObject}
|
||||
* @method buffered
|
||||
*/
|
||||
buffered() {
|
||||
return createTimeRange(0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get buffered percent
|
||||
*
|
||||
* @return {Number}
|
||||
* @method bufferedPercent
|
||||
*/
|
||||
bufferedPercent() {
|
||||
return bufferedPercent(this.buffered(), this.duration_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops tracking progress by clearing progress interval
|
||||
*
|
||||
* @method stopTrackingProgress
|
||||
*/
|
||||
stopTrackingProgress() {
|
||||
this.clearInterval(this.progressInterval);
|
||||
}
|
||||
|
||||
/*! Time Tracking -------------------------------------------------------------- */
|
||||
/**
|
||||
* Set event listeners for on play and pause and tracking current time
|
||||
*
|
||||
* @method manualTimeUpdatesOn
|
||||
*/
|
||||
manualTimeUpdatesOn() {
|
||||
this.manualTimeUpdates = true;
|
||||
|
||||
@ -150,6 +194,11 @@ class Tech extends Component {
|
||||
this.on('pause', this.stopTrackingCurrentTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove event listeners for on play and pause and tracking current time
|
||||
*
|
||||
* @method manualTimeUpdatesOff
|
||||
*/
|
||||
manualTimeUpdatesOff() {
|
||||
this.manualTimeUpdates = false;
|
||||
this.stopTrackingCurrentTime();
|
||||
@ -157,6 +206,11 @@ class Tech extends Component {
|
||||
this.off('pause', this.stopTrackingCurrentTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks current time
|
||||
*
|
||||
* @method trackCurrentTime
|
||||
*/
|
||||
trackCurrentTime() {
|
||||
if (this.currentTimeInterval) { this.stopTrackingCurrentTime(); }
|
||||
this.currentTimeInterval = this.setInterval(function(){
|
||||
@ -164,7 +218,11 @@ class Tech extends Component {
|
||||
}, 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
|
||||
}
|
||||
|
||||
// Turn off play progress tracking (when paused or dragging)
|
||||
/**
|
||||
* Turn off play progress tracking (when paused or dragging)
|
||||
*
|
||||
* @method stopTrackingCurrentTime
|
||||
*/
|
||||
stopTrackingCurrentTime() {
|
||||
this.clearInterval(this.currentTimeInterval);
|
||||
|
||||
@ -173,6 +231,11 @@ class Tech extends Component {
|
||||
this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn off any manual progress or timeupdate tracking
|
||||
*
|
||||
* @method dispose
|
||||
*/
|
||||
dispose() {
|
||||
// Turn off any manual progress or timeupdate tracking
|
||||
if (this.manualProgress) { this.manualProgressOff(); }
|
||||
@ -182,11 +245,21 @@ class Tech extends Component {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current time
|
||||
*
|
||||
* @method setCurrentTime
|
||||
*/
|
||||
setCurrentTime() {
|
||||
// improve the accuracy of manual timeupdates
|
||||
if (this.manualTimeUpdates) { this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true }); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize texttrack listeners
|
||||
*
|
||||
* @method initTextTrackListeners
|
||||
*/
|
||||
initTextTrackListeners() {
|
||||
let textTrackListChanges = Fn.bind(this, function() {
|
||||
this.trigger('texttrackchange');
|
||||
@ -205,6 +278,11 @@ class Tech extends Component {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate texttracks
|
||||
*
|
||||
* @method emulateTextTracks
|
||||
*/
|
||||
emulateTextTracks() {
|
||||
if (!window['WebVTT'] && this.el().parentNode != null) {
|
||||
let script = document.createElement('script');
|
||||
@ -239,22 +317,44 @@ class Tech extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Provide default methods for text tracks.
|
||||
*
|
||||
* Html5 tech overrides these.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get texttracks
|
||||
*
|
||||
* @returns {TextTrackList}
|
||||
* @method textTracks
|
||||
*/
|
||||
textTracks() {
|
||||
this.textTracks_ = this.textTracks_ || new TextTrackList();
|
||||
return this.textTracks_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get remote texttracks
|
||||
*
|
||||
* @returns {TextTrackList}
|
||||
* @method remoteTextTracks
|
||||
*/
|
||||
remoteTextTracks() {
|
||||
this.remoteTextTracks_ = this.remoteTextTracks_ || new TextTrackList();
|
||||
return this.remoteTextTracks_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a remote text track object
|
||||
*
|
||||
* @param {String} kind Text track kind (subtitles, captions, descriptions
|
||||
* chapters and metadata)
|
||||
* @param {String=} label Label to identify the text track
|
||||
* @param {String=} language Two letter language abbreviation
|
||||
* @return {TextTrackObject}
|
||||
* @method addTextTrack
|
||||
*/
|
||||
addTextTrack(kind, label, language) {
|
||||
if (!kind) {
|
||||
throw new Error('TextTrack kind is required but was not provided');
|
||||
@ -263,6 +363,14 @@ class Tech extends Component {
|
||||
return createTrackHelper(this, kind, label, language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a remote text track object
|
||||
*
|
||||
* @param {Object} options The object should contain values for
|
||||
* kind, language, label and src (location of the WebVTT file)
|
||||
* @return {TextTrackObject}
|
||||
* @method addRemoteTextTrack
|
||||
*/
|
||||
addRemoteTextTrack(options) {
|
||||
let track = createTrackHelper(this, options.kind, options.label, options.language, options);
|
||||
this.remoteTextTracks().addTrack_(track);
|
||||
@ -271,6 +379,12 @@ class Tech extends Component {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove remote texttrack
|
||||
*
|
||||
* @param {TextTrackObject} track Texttrack to remove
|
||||
* @method removeRemoteTextTrack
|
||||
*/
|
||||
removeRemoteTextTrack(track) {
|
||||
this.textTracks().removeTrack_(track);
|
||||
this.remoteTextTracks().removeTrack_(track);
|
||||
@ -278,16 +392,18 @@ class Tech extends Component {
|
||||
|
||||
/**
|
||||
* Provide a default setPoster method for techs
|
||||
*
|
||||
* Poster support for techs should be optional, so we don't want techs to
|
||||
* break if they don't have a way to set a poster.
|
||||
*
|
||||
* @method setPoster
|
||||
*/
|
||||
setPoster() {}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* List of associated text tracks
|
||||
*
|
||||
* @type {Array}
|
||||
* @private
|
||||
*/
|
||||
@ -325,8 +441,8 @@ Tech.prototype.featuresTimeupdateEvents = false;
|
||||
|
||||
Tech.prototype.featuresNativeTextTracks = false;
|
||||
|
||||
/**
|
||||
* A functional mixin for techs that want to use the Source Handler pattern.
|
||||
/*
|
||||
* A functional mixin for techs that want to use the Source Handler pattern.
|
||||
*
|
||||
* ##### EXAMPLE:
|
||||
*
|
||||
@ -334,14 +450,14 @@ Tech.prototype.featuresNativeTextTracks = false;
|
||||
*
|
||||
*/
|
||||
Tech.withSourceHandlers = function(_Tech){
|
||||
/**
|
||||
* Register a source handler
|
||||
* Source handlers are scripts for handling specific formats.
|
||||
* The source handler pattern is used for adaptive formats (HLS, DASH) that
|
||||
* manually load video data and feed it into a Source Buffer (Media Source Extensions)
|
||||
* @param {Function} handler The source handler
|
||||
* @param {Boolean} first Register it before any existing handlers
|
||||
*/
|
||||
/*
|
||||
* Register a source handler
|
||||
* Source handlers are scripts for handling specific formats.
|
||||
* The source handler pattern is used for adaptive formats (HLS, DASH) that
|
||||
* manually load video data and feed it into a Source Buffer (Media Source Extensions)
|
||||
* @param {Function} handler The source handler
|
||||
* @param {Boolean} first Register it before any existing handlers
|
||||
*/
|
||||
_Tech.registerSourceHandler = function(handler, index){
|
||||
let handlers = _Tech.sourceHandlers;
|
||||
|
||||
@ -357,13 +473,13 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
handlers.splice(index, 0, handler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the first source handler that supports the source
|
||||
* TODO: Answer question: should 'probably' be prioritized over 'maybe'
|
||||
* @param {Object} source The source object
|
||||
* @returns {Object} The first source handler that supports the source
|
||||
* @returns {null} Null if no source handler is found
|
||||
*/
|
||||
/*
|
||||
* Return the first source handler that supports the source
|
||||
* TODO: Answer question: should 'probably' be prioritized over 'maybe'
|
||||
* @param {Object} source The source object
|
||||
* @returns {Object} The first source handler that supports the source
|
||||
* @returns {null} Null if no source handler is found
|
||||
*/
|
||||
_Tech.selectSourceHandler = function(source){
|
||||
let handlers = _Tech.sourceHandlers || [];
|
||||
let can;
|
||||
@ -379,11 +495,11 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the tech can support the given source
|
||||
* @param {Object} srcObj The source object
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
/*
|
||||
* Check if the tech can support the given source
|
||||
* @param {Object} srcObj The source object
|
||||
* @return {String} 'probably', 'maybe', or '' (empty string)
|
||||
*/
|
||||
_Tech.canPlaySource = function(srcObj){
|
||||
let sh = _Tech.selectSourceHandler(srcObj);
|
||||
|
||||
@ -394,13 +510,13 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a function for setting the source using a source object
|
||||
* and source handlers.
|
||||
* Should never be called unless a source handler was found.
|
||||
* @param {Object} source A source object with src and type keys
|
||||
* @return {Tech} self
|
||||
*/
|
||||
/*
|
||||
* Create a function for setting the source using a source object
|
||||
* and source handlers.
|
||||
* Should never be called unless a source handler was found.
|
||||
* @param {Object} source A source object with src and type keys
|
||||
* @return {Tech} self
|
||||
*/
|
||||
_Tech.prototype.setSource = function(source){
|
||||
let sh = _Tech.selectSourceHandler(source);
|
||||
|
||||
@ -425,9 +541,9 @@ Tech.withSourceHandlers = function(_Tech){
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clean up any existing source handler
|
||||
*/
|
||||
/*
|
||||
* Clean up any existing source handler
|
||||
*/
|
||||
_Tech.prototype.disposeSourceHandler = function(){
|
||||
if (this.sourceHandler_ && this.sourceHandler_.dispose) {
|
||||
this.sourceHandler_.dispose();
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file text-track-cue-list.js
|
||||
*/
|
||||
import * as browser from '../utils/browser.js';
|
||||
import document from 'global/document';
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file text-track-display.js
|
||||
*/
|
||||
import Component from '../component';
|
||||
import Menu from '../menu/menu.js';
|
||||
import MenuItem from '../menu/menu-item.js';
|
||||
@ -24,7 +27,11 @@ const fontMap = {
|
||||
/**
|
||||
* The component for displaying text track cues
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} player Main Player
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @param {Function=} ready Ready callback function
|
||||
* @extends Component
|
||||
* @class TextTrackDisplay
|
||||
*/
|
||||
class TextTrackDisplay extends Component {
|
||||
|
||||
@ -54,6 +61,11 @@ class TextTrackDisplay extends Component {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle display texttracks
|
||||
*
|
||||
* @method toggleDisplay
|
||||
*/
|
||||
toggleDisplay() {
|
||||
if (this.player_.tech && this.player_.tech['featuresNativeTextTracks']) {
|
||||
this.hide();
|
||||
@ -62,18 +74,34 @@ class TextTrackDisplay extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-text-track-display'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear display texttracks
|
||||
*
|
||||
* @method clearDisplay
|
||||
*/
|
||||
clearDisplay() {
|
||||
if (typeof window['WebVTT'] === 'function') {
|
||||
window['WebVTT']['processCues'](window, [], this.el_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update display texttracks
|
||||
*
|
||||
* @method updateDisplay
|
||||
*/
|
||||
updateDisplay() {
|
||||
var tracks = this.player_.textTracks();
|
||||
|
||||
@ -91,6 +119,12 @@ class TextTrackDisplay extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add texttrack to texttrack list
|
||||
*
|
||||
* @param {TextTrackObject} track Texttrack object to be added to list
|
||||
* @method updateForTrack
|
||||
*/
|
||||
updateForTrack(track) {
|
||||
if (typeof window['WebVTT'] !== 'function' || !track['activeCues']) {
|
||||
return;
|
||||
@ -165,7 +199,14 @@ class TextTrackDisplay extends Component {
|
||||
|
||||
}
|
||||
|
||||
// Add cue HTML to display
|
||||
/**
|
||||
* Add cue HTML to display
|
||||
*
|
||||
* @param {Number} color Hex number for color, like #f0e
|
||||
* @param {Number} opacity Value for opacity,0.0 - 1.0
|
||||
* @return {RGBAColor} In the form 'rgba(255, 0, 0, 0.3)'
|
||||
* @method constructColor
|
||||
*/
|
||||
function constructColor(color, opacity) {
|
||||
return 'rgba(' +
|
||||
// color looks like "#f0e"
|
||||
@ -175,8 +216,17 @@ function constructColor(color, opacity) {
|
||||
opacity + ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to update style
|
||||
* Some style changes will throw an error, particularly in IE8. Those should be noops.
|
||||
*
|
||||
* @param {Element} el The element to be styles
|
||||
* @param {CSSProperty} style The CSS property to be styled
|
||||
* @param {CSSStyle} rule The actual style to be applied to the property
|
||||
* @method tryUpdateStyle
|
||||
*/
|
||||
function tryUpdateStyle(el, style, rule) {
|
||||
// some style changes will throw an error, particularly in IE8. Those should be noops.
|
||||
//
|
||||
try {
|
||||
el.style[style] = rule;
|
||||
} catch (e) {}
|
||||
|
@ -1,4 +1,6 @@
|
||||
/*
|
||||
/**
|
||||
* @file text-track-enums.js
|
||||
*
|
||||
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode
|
||||
*
|
||||
* enum TextTrackMode { "disabled", "hidden", "showing" };
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file text-track-list.js
|
||||
*/
|
||||
import EventEmitter from '../event-emitter';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
import * as browser from '../utils/browser.js';
|
||||
@ -52,7 +55,7 @@ TextTrackList.prototype.constructor = TextTrackList;
|
||||
* change - One or more tracks in the track list have been enabled or disabled.
|
||||
* addtrack - A track has been added to the track list.
|
||||
* removetrack - A track has been removed from the track list.
|
||||
*/
|
||||
*/
|
||||
TextTrackList.prototype.allowedEvents_ = {
|
||||
'change': 'change',
|
||||
'addtrack': 'addtrack',
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file text-track-settings.js
|
||||
*/
|
||||
import Component from '../component';
|
||||
import * as Events from '../utils/events.js';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
@ -5,6 +8,14 @@ import log from '../utils/log.js';
|
||||
import safeParseTuple from 'safe-json-parse/tuple';
|
||||
import window from 'global/window';
|
||||
|
||||
/**
|
||||
* Manipulate settings of texttracks
|
||||
*
|
||||
* @param {Object} player Main Player
|
||||
* @param {Object=} options Object of option names and values
|
||||
* @extends Component
|
||||
* @class TextTrackSettings
|
||||
*/
|
||||
class TextTrackSettings extends Component {
|
||||
|
||||
constructor(player, options) {
|
||||
@ -49,6 +60,12 @@ class TextTrackSettings extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*
|
||||
* @return {Element}
|
||||
* @method createEl
|
||||
*/
|
||||
createEl() {
|
||||
return super.createEl('div', {
|
||||
className: 'vjs-caption-settings vjs-modal-overlay',
|
||||
@ -56,6 +73,21 @@ class TextTrackSettings extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get texttrack settings
|
||||
* Settings are
|
||||
* .vjs-edge-style
|
||||
* .vjs-font-family
|
||||
* .vjs-fg-color
|
||||
* .vjs-text-opacity
|
||||
* .vjs-bg-color
|
||||
* .vjs-bg-opacity
|
||||
* .window-color
|
||||
* .vjs-window-opacity
|
||||
*
|
||||
* @return {Object}
|
||||
* @method getValues
|
||||
*/
|
||||
getValues() {
|
||||
const el = this.el();
|
||||
|
||||
@ -88,6 +120,21 @@ class TextTrackSettings extends Component {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set texttrack settings
|
||||
* Settings are
|
||||
* .vjs-edge-style
|
||||
* .vjs-font-family
|
||||
* .vjs-fg-color
|
||||
* .vjs-text-opacity
|
||||
* .vjs-bg-color
|
||||
* .vjs-bg-opacity
|
||||
* .window-color
|
||||
* .vjs-window-opacity
|
||||
*
|
||||
* @param {Object} values Object with texttrack setting values
|
||||
* @method setValues
|
||||
*/
|
||||
setValues(values) {
|
||||
const el = this.el();
|
||||
|
||||
@ -109,6 +156,11 @@ class TextTrackSettings extends Component {
|
||||
setSelectedOption(el.querySelector('.vjs-font-percent > select'), fontPercent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore texttrack settings
|
||||
*
|
||||
* @method restoreSettings
|
||||
*/
|
||||
restoreSettings() {
|
||||
let [err, values] = safeParseTuple(window.localStorage.getItem('vjs-text-track-settings'));
|
||||
|
||||
@ -121,6 +173,11 @@ class TextTrackSettings extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save texttrack settings to local storage
|
||||
*
|
||||
* @method saveSettings
|
||||
*/
|
||||
saveSettings() {
|
||||
if (!this.options_.persistTextTrackSettings) {
|
||||
return;
|
||||
@ -136,6 +193,11 @@ class TextTrackSettings extends Component {
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update display of texttrack settings
|
||||
*
|
||||
* @method updateDisplay
|
||||
*/
|
||||
updateDisplay() {
|
||||
let ttDisplay = this.player_.getChild('textTrackDisplay');
|
||||
if (ttDisplay) {
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file text-track.js
|
||||
*/
|
||||
import TextTrackCueList from './text-track-cue-list';
|
||||
import * as Fn from '../utils/fn.js';
|
||||
import * as Guid from '../utils/guid.js';
|
||||
@ -225,8 +228,8 @@ TextTrack.prototype.removeCue = function(removeCue) {
|
||||
};
|
||||
|
||||
/*
|
||||
* Downloading stuff happens below this point
|
||||
*/
|
||||
* Downloading stuff happens below this point
|
||||
*/
|
||||
var parseCues = function(srcContent, track) {
|
||||
if (typeof window['WebVTT'] !== 'function') {
|
||||
//try again a bit later
|
||||
|
@ -1,10 +1,14 @@
|
||||
/**
|
||||
* @file browser.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
|
||||
const USER_AGENT = window.navigator.userAgent;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Device is an iPhone
|
||||
*
|
||||
* @type {Boolean}
|
||||
* @constant
|
||||
* @private
|
||||
|
@ -1,11 +1,16 @@
|
||||
/**
|
||||
* @file buffer.js
|
||||
*/
|
||||
import { createTimeRange } from './time-ranges.js';
|
||||
|
||||
/**
|
||||
* Compute how much your video has been buffered
|
||||
*
|
||||
* @param {Object} Buffered object
|
||||
* @param {Number} Total duration
|
||||
* @return {Number} Percent buffered of the total duration
|
||||
* @private
|
||||
* @function bufferedPercent
|
||||
*/
|
||||
export function bufferedPercent(buffered, duration) {
|
||||
var bufferedDuration = 0,
|
||||
|
@ -1,13 +1,18 @@
|
||||
/**
|
||||
* @file dom.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
import window from 'global/window';
|
||||
import * as Guid from './guid.js';
|
||||
import * as Guid from './guid.js';
|
||||
import roundFloat from './round-float.js';
|
||||
|
||||
/**
|
||||
* Shorthand for document.getElementById()
|
||||
* Also allows for CSS (jQuery) ID syntax. But nothing other than IDs.
|
||||
*
|
||||
* @param {String} id Element ID
|
||||
* @return {Element} Element with supplied ID
|
||||
* @function getEl
|
||||
*/
|
||||
export function getEl(id){
|
||||
if (id.indexOf('#') === 0) {
|
||||
@ -19,9 +24,11 @@ export function getEl(id){
|
||||
|
||||
/**
|
||||
* Creates an element and applies properties.
|
||||
*
|
||||
* @param {String=} tagName Name of tag to be created.
|
||||
* @param {Object=} properties Element properties to be applied.
|
||||
* @return {Element}
|
||||
* @function createEl
|
||||
*/
|
||||
export function createEl(tagName='div', properties={}){
|
||||
let el = document.createElement(tagName);
|
||||
@ -32,10 +39,10 @@ export function createEl(tagName='div', properties={}){
|
||||
// Not remembering why we were checking for dash
|
||||
// but using setAttribute means you have to use getAttribute
|
||||
|
||||
// The check for dash checks for the aria-* attributes, like aria-label, aria-valuemin.
|
||||
// The check for dash checks for the aria- * attributes, like aria-label, aria-valuemin.
|
||||
// The additional check for "role" is because the default method for adding attributes does not
|
||||
// add the attribute "role". My guess is because it's not a valid attribute in some namespaces, although
|
||||
// browsers handle the attribute just fine. The W3C allows for aria-* attributes to be used in pre-HTML5 docs.
|
||||
// browsers handle the attribute just fine. The W3C allows for aria- * attributes to be used in pre-HTML5 docs.
|
||||
// http://www.w3.org/TR/wai-aria-primer/#ariahtml. Using setAttribute gets around this problem.
|
||||
if (propName.indexOf('aria-') !== -1 || propName === 'role') {
|
||||
el.setAttribute(propName, val);
|
||||
@ -49,9 +56,11 @@ export function createEl(tagName='div', properties={}){
|
||||
|
||||
/**
|
||||
* Insert an element as the first child node of another
|
||||
*
|
||||
* @param {Element} child Element to insert
|
||||
* @param {[type]} parent Element to insert child into
|
||||
* @param {Element} parent Element to insert child into
|
||||
* @private
|
||||
* @function insertElFirst
|
||||
*/
|
||||
export function insertElFirst(child, parent){
|
||||
if (parent.firstChild) {
|
||||
@ -65,13 +74,15 @@ export function insertElFirst(child, parent){
|
||||
* Element Data Store. Allows for binding data to an element without putting it directly on the element.
|
||||
* Ex. Event listeners are stored here.
|
||||
* (also from jsninja.com, slightly modified and updated for closure compiler)
|
||||
*
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
const elData = {};
|
||||
|
||||
/**
|
||||
/*
|
||||
* Unique attribute name to store an element's guid in
|
||||
*
|
||||
* @type {String}
|
||||
* @constant
|
||||
* @private
|
||||
@ -80,8 +91,10 @@ const elIdAttr = 'vdata' + (new Date()).getTime();
|
||||
|
||||
/**
|
||||
* Returns the cache object where data for an element is stored
|
||||
*
|
||||
* @param {Element} el Element to store data for.
|
||||
* @return {Object}
|
||||
* @function getElData
|
||||
*/
|
||||
export function getElData(el) {
|
||||
let id = el[elIdAttr];
|
||||
@ -99,9 +112,11 @@ export function getElData(el) {
|
||||
|
||||
/**
|
||||
* Returns whether or not an element has cached data
|
||||
*
|
||||
* @param {Element} el A dom element
|
||||
* @return {Boolean}
|
||||
* @private
|
||||
* @function hasElData
|
||||
*/
|
||||
export function hasElData(el) {
|
||||
const id = el[elIdAttr];
|
||||
@ -115,8 +130,10 @@ export function hasElData(el) {
|
||||
|
||||
/**
|
||||
* Delete data for the element from the cache and the guid attr from getElementById
|
||||
*
|
||||
* @param {Element} el Remove data for an element
|
||||
* @private
|
||||
* @function removeElData
|
||||
*/
|
||||
export function removeElData(el) {
|
||||
let id = el[elIdAttr];
|
||||
@ -143,8 +160,10 @@ export function removeElData(el) {
|
||||
|
||||
/**
|
||||
* Check if an element has a CSS class
|
||||
*
|
||||
* @param {Element} element Element to check
|
||||
* @param {String} classToCheck Classname to check
|
||||
* @function hasElClass
|
||||
*/
|
||||
export function hasElClass(element, classToCheck) {
|
||||
return ((' ' + element.className + ' ').indexOf(' ' + classToCheck + ' ') !== -1);
|
||||
@ -152,8 +171,10 @@ export function hasElClass(element, classToCheck) {
|
||||
|
||||
/**
|
||||
* Add a CSS class name to an element
|
||||
*
|
||||
* @param {Element} element Element to add class name to
|
||||
* @param {String} classToAdd Classname to add
|
||||
* @function addElClass
|
||||
*/
|
||||
export function addElClass(element, classToAdd) {
|
||||
if (!hasElClass(element, classToAdd)) {
|
||||
@ -163,8 +184,10 @@ export function addElClass(element, classToAdd) {
|
||||
|
||||
/**
|
||||
* Remove a CSS class name from an element
|
||||
*
|
||||
* @param {Element} element Element to remove from class name
|
||||
* @param {String} classToAdd Classname to remove
|
||||
* @param {String} classToRemove Classname to remove
|
||||
* @function removeElClass
|
||||
*/
|
||||
export function removeElClass(element, classToRemove) {
|
||||
if (!hasElClass(element, classToRemove)) {return;}
|
||||
@ -183,9 +206,11 @@ export function removeElClass(element, classToRemove) {
|
||||
|
||||
/**
|
||||
* Apply attributes to an HTML element.
|
||||
*
|
||||
* @param {Element} el Target element.
|
||||
* @param {Object=} attributes Element attributes to be applied.
|
||||
* @private
|
||||
* @function setElAttributes
|
||||
*/
|
||||
export function setElAttributes(el, attributes) {
|
||||
Object.getOwnPropertyNames(attributes).forEach(function(attrName){
|
||||
@ -204,9 +229,11 @@ export function setElAttributes(el, attributes) {
|
||||
* Attributes are not the same as properties. They're defined on the tag
|
||||
* or with setAttribute (which shouldn't be used with HTML)
|
||||
* This will return true or false for boolean attributes.
|
||||
*
|
||||
* @param {Element} tag Element from which to get tag attributes
|
||||
* @return {Object}
|
||||
* @private
|
||||
* @function getElAttributes
|
||||
*/
|
||||
export function getElAttributes(tag) {
|
||||
var obj, knownBooleans, attrs, attrName, attrVal;
|
||||
@ -241,7 +268,12 @@ export function getElAttributes(tag) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Attempt to block the ability to select text while dragging controls
|
||||
/**
|
||||
* Attempt to block the ability to select text while dragging controls
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method blockTextSelection
|
||||
*/
|
||||
export function blockTextSelection() {
|
||||
document.body.focus();
|
||||
document.onselectstart = function() {
|
||||
@ -249,15 +281,27 @@ export function blockTextSelection() {
|
||||
};
|
||||
}
|
||||
|
||||
// Turn off text selection blocking
|
||||
/**
|
||||
* Turn off text selection blocking
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @method unblockTextSelection
|
||||
*/
|
||||
export function unblockTextSelection() {
|
||||
document.onselectstart = function() {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
// Offset Left
|
||||
// getBoundingClientRect technique from John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
|
||||
/**
|
||||
* Offset Left
|
||||
* getBoundingClientRect technique from
|
||||
* John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
|
||||
*
|
||||
* @param {Element} el Element from which to get offset
|
||||
* @return {Object=}
|
||||
* @method findElPosition
|
||||
*/
|
||||
export function findElPosition(el) {
|
||||
let box;
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
/**
|
||||
* @fileoverview Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/)
|
||||
* @file events.js
|
||||
*
|
||||
* Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/)
|
||||
* (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible)
|
||||
* This should work very similarly to jQuery's events, however it's based off the book version which isn't as
|
||||
* robust as jquery's, so there's probably some differences.
|
||||
*/
|
||||
|
||||
import * as Dom from './dom.js';
|
||||
import * as Guid from './guid.js';
|
||||
import * as Dom from './dom.js';
|
||||
import * as Guid from './guid.js';
|
||||
import window from 'global/window';
|
||||
import document from 'global/document';
|
||||
|
||||
@ -15,9 +17,11 @@ import document from 'global/document';
|
||||
* It stores the handler function in a separate cache object
|
||||
* and adds a generic handler to the element's event,
|
||||
* along with a unique id (guid) to the element.
|
||||
*
|
||||
* @param {Element|Object} elem Element or object to bind listeners to
|
||||
* @param {String|Array} type Type of event to bind to.
|
||||
* @param {Function} fn Event listener.
|
||||
* @method on
|
||||
*/
|
||||
export function on(elem, type, fn){
|
||||
if (Array.isArray(type)) {
|
||||
@ -71,9 +75,11 @@ export function on(elem, type, fn){
|
||||
|
||||
/**
|
||||
* Removes event listeners from an element
|
||||
*
|
||||
* @param {Element|Object} elem Object to remove listeners from
|
||||
* @param {String|Array=} type Type of listener to remove. Don't include to remove all events from element.
|
||||
* @param {Function} fn Specific listener to remove. Don't include to remove listeners for an event type.
|
||||
* @method off
|
||||
*/
|
||||
export function off(elem, type, fn) {
|
||||
// Don't want to add a cache object through getElData if not needed
|
||||
@ -125,9 +131,12 @@ export function off(elem, type, fn) {
|
||||
|
||||
/**
|
||||
* Trigger an event for an element
|
||||
*
|
||||
* @param {Element|Object} elem Element to trigger an event on
|
||||
* @param {Event|Object|String} event A string (the type) or an event object with a type attribute
|
||||
* @param {Object} [hash] data hash to pass along with the event
|
||||
* @return {Boolean=} Returned only if default was prevented
|
||||
* @method trigger
|
||||
*/
|
||||
export function trigger(elem, event, hash) {
|
||||
// Fetches element data and a reference to the parent (for bubbling).
|
||||
@ -178,9 +187,11 @@ export function trigger(elem, event, hash) {
|
||||
|
||||
/**
|
||||
* Trigger a listener only once for an event
|
||||
*
|
||||
* @param {Element|Object} elem Element or object to
|
||||
* @param {String|Array} type
|
||||
* @param {Function} fn
|
||||
* @param {String|Array} type Name/type of event
|
||||
* @param {Function} fn Event handler function
|
||||
* @method one
|
||||
*/
|
||||
export function one(elem, type, fn) {
|
||||
if (Array.isArray(type)) {
|
||||
@ -197,9 +208,11 @@ export function one(elem, type, fn) {
|
||||
|
||||
/**
|
||||
* Fix a native event to have standard property values
|
||||
*
|
||||
* @param {Object} event Event object to fix
|
||||
* @return {Object}
|
||||
* @private
|
||||
* @method fixEvent
|
||||
*/
|
||||
export function fixEvent(event) {
|
||||
|
||||
@ -307,9 +320,11 @@ export function fixEvent(event) {
|
||||
|
||||
/**
|
||||
* Clean up the listener cache and dispatchers
|
||||
*
|
||||
* @param {Element|Object} elem Element to clean up
|
||||
* @param {String} type Type of event to clean up
|
||||
* @private
|
||||
* @method _cleanUpEvents
|
||||
*/
|
||||
function _cleanUpEvents(elem, type) {
|
||||
var data = Dom.getElData(elem);
|
||||
@ -343,11 +358,13 @@ function _cleanUpEvents(elem, type) {
|
||||
|
||||
/**
|
||||
* Loops through an array of event types and calls the requested method for each type.
|
||||
*
|
||||
* @param {Function} fn The event method we want to use.
|
||||
* @param {Element|Object} elem Element or object to bind listeners to
|
||||
* @param {String} type Type of event to bind to.
|
||||
* @param {Function} callback Event listener.
|
||||
* @private
|
||||
* @function _handleMultipleEvents
|
||||
*/
|
||||
function _handleMultipleEvents(fn, elem, types, callback) {
|
||||
types.forEach(function(type) {
|
||||
|
@ -1,13 +1,18 @@
|
||||
/**
|
||||
* @file fn.js
|
||||
*/
|
||||
import { newGUID } from './guid.js';
|
||||
|
||||
/**
|
||||
* Bind (a.k.a proxy or Context). A simple method for changing the context of a function
|
||||
It also stores a unique id on the function so it can be easily removed from events
|
||||
* It also stores a unique id on the function so it can be easily removed from events
|
||||
*
|
||||
* @param {*} context The object to bind as scope
|
||||
* @param {Function} fn The function to be bound to a scope
|
||||
* @param {Number=} uid An optional unique ID for the function to be set
|
||||
* @return {Function}
|
||||
* @private
|
||||
* @method bind
|
||||
*/
|
||||
export const bind = function(context, fn, uid) {
|
||||
// Make sure the function has a unique ID
|
||||
|
@ -1,11 +1,15 @@
|
||||
/**
|
||||
* @file format-time.js
|
||||
*
|
||||
* Format seconds as a time string, H:MM:SS or M:SS
|
||||
* Supplying a guide (in seconds) will force a number of leading zeros
|
||||
* to cover the length of the guide
|
||||
*
|
||||
* @param {Number} seconds Number of seconds to be turned into a string
|
||||
* @param {Number} guide Number (in seconds) to model the string after
|
||||
* @return {String} Time formatted as H:MM:SS or M:SS
|
||||
* @private
|
||||
* @function formatTime
|
||||
*/
|
||||
function formatTime(seconds, guide=seconds) {
|
||||
let s = Math.floor(seconds % 60);
|
||||
|
@ -1,4 +1,6 @@
|
||||
/**
|
||||
* @file guid.js
|
||||
*
|
||||
* Unique ID for an element or function
|
||||
* @type {Number}
|
||||
* @private
|
||||
@ -7,6 +9,9 @@ let _guid = 1;
|
||||
|
||||
/**
|
||||
* Get the next unique ID
|
||||
*
|
||||
* @return {String}
|
||||
* @function newGUID
|
||||
*/
|
||||
export function newGUID() {
|
||||
return _guid++;
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file log.js
|
||||
*/
|
||||
import window from 'global/window';
|
||||
|
||||
/**
|
||||
@ -31,8 +34,9 @@ log.warn = function(){
|
||||
* Log messages to the console and history based on the type of message
|
||||
*
|
||||
* @param {String} type The type of message, or `null` for `log`
|
||||
* @param {[type]} args The args to be passed to the log
|
||||
* @param {Object} args The args to be passed to the log
|
||||
* @private
|
||||
* @method _logType
|
||||
*/
|
||||
function _logType(type, args){
|
||||
// convert args to an array to get array functions
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file merge-options.js
|
||||
*/
|
||||
import merge from 'lodash-compat/object/merge';
|
||||
|
||||
function isPlain(obj) {
|
||||
@ -8,13 +11,13 @@ function isPlain(obj) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two options objects, recursively merging **only** plain object
|
||||
* Merge two options objects, recursively merging **only* * plain object
|
||||
* properties. Previously `deepMerge`.
|
||||
*
|
||||
* @param {Object} object The destination object
|
||||
* @param {...Object} source One or more objects to merge into the first
|
||||
*
|
||||
* @returns {Object} The updated first object
|
||||
* @function mergeOptions
|
||||
*/
|
||||
export default function mergeOptions(object={}) {
|
||||
|
||||
|
@ -1,9 +1,13 @@
|
||||
/**
|
||||
* @file round-float.js
|
||||
*
|
||||
* Should round off a number to a decimal place
|
||||
*
|
||||
* @param {Number} num Number to round
|
||||
* @param {Number} dec Number of decimal places to round to
|
||||
* @return {Number} Rounded number
|
||||
* @private
|
||||
* @method roundFloat
|
||||
*/
|
||||
const roundFloat = function(num, dec=0) {
|
||||
return Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
|
||||
|
@ -1,12 +1,16 @@
|
||||
/**
|
||||
* @file time-ranges.js
|
||||
*
|
||||
* Should create a fake TimeRange object
|
||||
* Mimics an HTML5 time range instance, which has functions that
|
||||
* return the start and end times for a range
|
||||
* TimeRanges are returned by the buffered() method
|
||||
*
|
||||
* @param {Number} start Start time in seconds
|
||||
* @param {Number} end End time in seconds
|
||||
* @return {Object} Fake TimeRange object
|
||||
* @private
|
||||
* @method createTimeRange
|
||||
*/
|
||||
export function createTimeRange(start, end){
|
||||
if (start === undefined && end === undefined) {
|
||||
|
@ -1,8 +1,12 @@
|
||||
/**
|
||||
* @file to-title-case.js
|
||||
*
|
||||
* Uppercase the first letter of a string
|
||||
*
|
||||
* @param {String} string String to be uppercased
|
||||
* @return {String}
|
||||
* @private
|
||||
* @method toTitleCase
|
||||
*/
|
||||
function toTitleCase(string){
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
|
@ -1,9 +1,14 @@
|
||||
/**
|
||||
* @file url.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
|
||||
/**
|
||||
* Resolve and parse the elements of a URL
|
||||
*
|
||||
* @param {String} url The url to parse
|
||||
* @return {Object} An object of url details
|
||||
* @method parseUrl
|
||||
*/
|
||||
export const parseUrl = function(url) {
|
||||
const props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host'];
|
||||
@ -53,9 +58,11 @@ export const parseUrl = function(url) {
|
||||
/**
|
||||
* Get absolute version of relative URL. Used to tell flash correct URL.
|
||||
* http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
|
||||
*
|
||||
* @param {String} url URL to make absolute
|
||||
* @return {String} Absolute URL
|
||||
* @private
|
||||
* @method getAbsoluteURL
|
||||
*/
|
||||
export const getAbsoluteURL = function(url){
|
||||
// Check if absolute URL
|
||||
@ -74,6 +81,7 @@ export const getAbsoluteURL = function(url){
|
||||
*
|
||||
* @param {String} path The fileName path like '/path/to/file.mp4'
|
||||
* @returns {String} The extension in lower case or an empty string if no extension could be found.
|
||||
* @method getFileExtension
|
||||
*/
|
||||
export const getFileExtension = function(path) {
|
||||
if(typeof path === 'string'){
|
||||
|
@ -1,3 +1,6 @@
|
||||
/**
|
||||
* @file video.js
|
||||
*/
|
||||
import document from 'global/document';
|
||||
import * as setup from './setup';
|
||||
import Component from './component';
|
||||
@ -27,16 +30,17 @@ if (typeof HTMLVideoElement === 'undefined') {
|
||||
/**
|
||||
* Doubles as the main function for users to create a player instance and also
|
||||
* the main library object.
|
||||
*
|
||||
* The `videojs` function can be used to initialize or retrieve a player.
|
||||
*
|
||||
* ```js
|
||||
* var myPlayer = videojs('my_video_id');
|
||||
* ```
|
||||
*
|
||||
* @param {String|Element} id Video element or video element ID
|
||||
* @param {Object=} options Optional options object for config/settings
|
||||
* @param {Function=} ready Optional ready callback
|
||||
* @return {Player} A player instance
|
||||
* @namespace
|
||||
* @return {Player} A player instance
|
||||
* @mixes videojs
|
||||
* @method videojs
|
||||
*/
|
||||
var videojs = function(id, options, ready){
|
||||
var tag; // Element of ID
|
||||
@ -88,8 +92,9 @@ var videojs = function(id, options, ready){
|
||||
// You have to wait at least once in case this script is loaded after your video in the DOM (weird behavior only with minified version)
|
||||
setup.autoSetupTimeout(1, videojs);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Current software version (semver)
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
videojs.VERSION = '__VERSION__';
|
||||
@ -97,22 +102,26 @@ videojs.VERSION = '__VERSION__';
|
||||
/**
|
||||
* Get the global options object
|
||||
*
|
||||
* @returns {Object} The global options object
|
||||
* @return {Object} The global options object
|
||||
* @mixes videojs
|
||||
* @method getGlobalOptions
|
||||
*/
|
||||
videojs.getGlobalOptions = () => globalOptions;
|
||||
|
||||
/**
|
||||
* Set options that will apply to every player
|
||||
*
|
||||
* ```js
|
||||
* videojs.setGlobalOptions({
|
||||
* autoplay: true
|
||||
* });
|
||||
* // -> all players will autoplay by default
|
||||
*
|
||||
* ```
|
||||
* NOTE: This will do a deep merge with the new options,
|
||||
* not overwrite the entire global options object.
|
||||
*
|
||||
* @returns {Object} The updated global options object
|
||||
* @return {Object} The updated global options object
|
||||
* @mixes videojs
|
||||
* @method setGlobalOptions
|
||||
*/
|
||||
videojs.setGlobalOptions = function(newOptions) {
|
||||
return mergeOptions(globalOptions, newOptions);
|
||||
@ -121,7 +130,9 @@ videojs.setGlobalOptions = function(newOptions) {
|
||||
/**
|
||||
* Get an object with the currently created players, keyed by player ID
|
||||
*
|
||||
* @returns {Object} The created players
|
||||
* @return {Object} The created players
|
||||
* @mixes videojs
|
||||
* @method getPlayers
|
||||
*/
|
||||
videojs.getPlayers = function() {
|
||||
return Player.players;
|
||||
@ -129,47 +140,49 @@ videojs.getPlayers = function() {
|
||||
|
||||
/**
|
||||
* Get a component class object by name
|
||||
*
|
||||
* ```js
|
||||
* var VjsButton = videojs.getComponent('Button');
|
||||
*
|
||||
* // Create a new instance of the component
|
||||
* var myButton = new VjsButton(myPlayer);
|
||||
* ```
|
||||
*
|
||||
* @return {Component} Component identified by name
|
||||
* @mixes videojs
|
||||
* @method getComponent
|
||||
*/
|
||||
videojs.getComponent = Component.getComponent;
|
||||
|
||||
/**
|
||||
* Register a component so it can referred to by name
|
||||
*
|
||||
* Used when adding to other
|
||||
* components, either through addChild
|
||||
* `component.addChild('myComponent')`
|
||||
* or through default children options
|
||||
* `{ children: ['myComponent'] }`.
|
||||
*
|
||||
* ```js
|
||||
* // Get a component to subclass
|
||||
* var VjsButton = videojs.getComponent('Button');
|
||||
*
|
||||
* // Subclass the component (see 'extends' doc for more info)
|
||||
* var MySpecialButton = videojs.extends(VjsButton, {});
|
||||
*
|
||||
* // Register the new component
|
||||
* VjsButton.registerComponent('MySepcialButton', MySepcialButton);
|
||||
*
|
||||
* // (optionally) add the new component as a default player child
|
||||
* myPlayer.addChild('MySepcialButton');
|
||||
*
|
||||
* ```
|
||||
* NOTE: You could also just initialize the component before adding.
|
||||
* `component.addChild(new MyComponent());`
|
||||
*
|
||||
* @param {String} The class name of the component
|
||||
* @param {Component} The component class
|
||||
* @returns {Component} The newly registered component
|
||||
* @return {Component} The newly registered component
|
||||
* @mixes videojs
|
||||
* @method registerComponent
|
||||
*/
|
||||
videojs.registerComponent = Component.registerComponent;
|
||||
|
||||
/**
|
||||
/*
|
||||
* A suite of browser and device tests
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
videojs.browser = browser;
|
||||
@ -177,18 +190,16 @@ videojs.browser = browser;
|
||||
/**
|
||||
* Subclass an existing class
|
||||
* Mimics ES6 subclassing with the `extends` keyword
|
||||
*
|
||||
* ```js
|
||||
* // Create a basic javascript 'class'
|
||||
* function MyClass(name){
|
||||
* // Set a property at initialization
|
||||
* this.myName = name;
|
||||
* }
|
||||
*
|
||||
* // Create an instance method
|
||||
* MyClass.prototype.sayMyName = function(){
|
||||
* alert(this.myName);
|
||||
* };
|
||||
*
|
||||
* // Subclass the exisitng class and change the name
|
||||
* // when initializing
|
||||
* var MySubClass = videojs.extends(MyClass, {
|
||||
@ -197,16 +208,17 @@ videojs.browser = browser;
|
||||
* MyClass.call(this, name)
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // Create an instance of the new sub class
|
||||
* var myInstance = new MySubClass('John');
|
||||
* myInstance.sayMyName(); // -> should alert "John"
|
||||
* ```
|
||||
*
|
||||
* @param {Function} The Class to subclass
|
||||
* @param {Object} An object including instace methods for the new class
|
||||
* Optionally including a `constructor` function
|
||||
*
|
||||
* @returns {Function} The newly created subclass
|
||||
* @return {Function} The newly created subclass
|
||||
* @mixes videojs
|
||||
* @method extends
|
||||
*/
|
||||
videojs.extends = extendsFn;
|
||||
|
||||
@ -215,7 +227,7 @@ videojs.extends = extendsFn;
|
||||
* Performs a deep merge like lodash.merge but **only merges plain objects**
|
||||
* (not arrays, elements, anything else)
|
||||
* Other values will be copied directly from the second object.
|
||||
*
|
||||
* ```js
|
||||
* var defaultOptions = {
|
||||
* foo: true,
|
||||
* bar: {
|
||||
@ -229,29 +241,29 @@ videojs.extends = extendsFn;
|
||||
* b: [4,5,6]
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* var result = videojs.mergeOptions(defaultOptions, newOptions);
|
||||
* // result.foo = false;
|
||||
* // result.bar.a = true;
|
||||
* // result.bar.b = [4,5,6];
|
||||
* ```
|
||||
*
|
||||
* @param {Object} The options object whose values will be overriden
|
||||
* @param {Object} The options object with values to override the first
|
||||
* @param {Object} Any number of additional options objects
|
||||
*
|
||||
* @returns {Object} a new object with the merged values
|
||||
* @return {Object} a new object with the merged values
|
||||
* @mixes videojs
|
||||
* @method mergeOptions
|
||||
*/
|
||||
videojs.mergeOptions = mergeOptions;
|
||||
|
||||
/**
|
||||
* Create a Video.js player plugin
|
||||
*
|
||||
* Plugins are only initialized when options for the plugin are included
|
||||
* in the player options, or the plugin function on the player instance is
|
||||
* called.
|
||||
*
|
||||
* **See the plugin guide in the docs for a more detailed example**
|
||||
*
|
||||
* ```js
|
||||
* // Make a plugin that alerts when the player plays
|
||||
* videojs.plugin('myPlugin', function(myPluginOptions) {
|
||||
* myPluginOptions = myPluginOptions || {};
|
||||
@ -263,9 +275,7 @@ videojs.mergeOptions = mergeOptions;
|
||||
* alert(alertText);
|
||||
* });
|
||||
* });
|
||||
*
|
||||
* // USAGE EXAMPLES
|
||||
*
|
||||
* // EXAMPLE 1: New player with plugin options, call plugin immediately
|
||||
* var player1 = videojs('idOne', {
|
||||
* myPlugin: {
|
||||
@ -274,7 +284,6 @@ videojs.mergeOptions = mergeOptions;
|
||||
* });
|
||||
* // Click play
|
||||
* // --> Should alert 'Custom text!'
|
||||
*
|
||||
* // EXAMPLE 3: New player, initialize plugin later
|
||||
* var player3 = videojs('idThree');
|
||||
* // Click play
|
||||
@ -286,21 +295,26 @@ videojs.mergeOptions = mergeOptions;
|
||||
* });
|
||||
* // Click play
|
||||
* // --> Should alert 'Plugin added later!'
|
||||
* ```
|
||||
*
|
||||
* @param {String} The plugin name
|
||||
* @param {Function} The plugin function that will be called with options
|
||||
* @mixes videojs
|
||||
* @method plugin
|
||||
*/
|
||||
videojs.plugin = plugin;
|
||||
|
||||
/**
|
||||
* Adding languages so that they're available to all players.
|
||||
*
|
||||
* ```js
|
||||
* videojs.addLanguage('es', { 'Hello': 'Hola' });
|
||||
* ```
|
||||
*
|
||||
* @param {String} code The language code or dictionary property
|
||||
* @param {Object} data The data values to be translated
|
||||
*
|
||||
* @return {Object} The resulting language dictionary object
|
||||
* @mixes videojs
|
||||
* @method addLanguage
|
||||
*/
|
||||
videojs.addLanguage = function(code, data){
|
||||
code = ('' + code).toLowerCase();
|
||||
@ -324,7 +338,7 @@ videojs.addLanguage = function(code, data){
|
||||
// assign(module.exports[name], component);
|
||||
// });
|
||||
|
||||
/**
|
||||
/*
|
||||
* Custom Universal Module Definition (UMD)
|
||||
*
|
||||
* Video.js will never be a non-browser lib so we can simplify UMD a bunch and
|
||||
|
@ -1,13 +1,14 @@
|
||||
import * as Url from './utils/url.js';
|
||||
/**
|
||||
* @file xhr.js
|
||||
*/
|
||||
import * as Url from './utils/url.js';
|
||||
import log from './utils/log.js';
|
||||
import mergeOptions from './utils/merge-options.js';
|
||||
import window from 'global/window';
|
||||
|
||||
/**
|
||||
/*
|
||||
* Simple http request for retrieving external files (e.g. text tracks)
|
||||
*
|
||||
* ##### Example
|
||||
*
|
||||
* // using url string
|
||||
* videojs.xhr('http://example.com/myfile.vtt', function(error, response, responseBody){});
|
||||
*
|
||||
@ -23,15 +24,15 @@ import window from 'global/window';
|
||||
* // successful, do something with the response
|
||||
* }
|
||||
* });
|
||||
*
|
||||
*
|
||||
* /////////////
|
||||
* API is modeled after the Raynos/xhr, which we hope to use after
|
||||
* getting browserify implemented.
|
||||
* https://github.com/Raynos/xhr/blob/master/index.js
|
||||
*
|
||||
* @param {Object|String} options Options block or URL string
|
||||
* @param {Function} callback The callback function
|
||||
* @returns {Object} The request
|
||||
* @return {Object} The request
|
||||
* @method xhr
|
||||
*/
|
||||
var xhr = function(options, callback){
|
||||
let abortTimeout;
|
||||
@ -46,7 +47,7 @@ var xhr = function(options, callback){
|
||||
// Merge with default options
|
||||
mergeOptions({
|
||||
method: 'GET',
|
||||
timeout: 45 * 1000
|
||||
timeout: 45 * 1000
|
||||
}, options);
|
||||
|
||||
callback = callback || function(){};
|
||||
|
Loading…
x
Reference in New Issue
Block a user