mirror of
				https://github.com/videojs/video.js.git
				synced 2025-10-31 00:08:01 +02:00 
			
		
		
		
	Improved JSDoc comments everywhere for new docs generation
closes #2270
This commit is contained in:
		| @@ -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(){}; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user