3 * Video.js 5.15.1 <http://videojs.com/>
4 * Copyright Brightcove, Inc. <https://www.brightcove.com/>
5 * Available under Apache License Version 2.0
6 * <https://github.com/videojs/video.js/blob/master/LICENSE>
8 * Includes vtt.js <https://github.com/mozilla/vtt.js>
9 * Available under Apache License Version 2.0
10 * <https://github.com/mozilla/vtt.js/blob/master/LICENSE>
13 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.videojs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
16 exports.__esModule = true;
18 var _button = _dereq_(2);
20 var _button2 = _interopRequireDefault(_button);
22 var _component = _dereq_(5);
24 var _component2 = _interopRequireDefault(_component);
26 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
28 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
30 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
32 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
33 * @file big-play-button.js
38 * The initial play button that shows before the video has played. The hiding of the
39 * `BigPlayButton` get done via CSS and `Player` states.
43 var BigPlayButton = function (_Button) {
44 _inherits(BigPlayButton, _Button);
46 function BigPlayButton() {
47 _classCallCheck(this, BigPlayButton);
49 return _possibleConstructorReturn(this, _Button.apply(this, arguments));
53 * Builds the default DOM `className`.
56 * The DOM `className` for this object. Always returns 'vjs-big-play-button'.
58 BigPlayButton.prototype.buildCSSClass = function buildCSSClass() {
59 return 'vjs-big-play-button';
63 * This gets called when a `BigPlayButton` "clicked". See {@link ClickableComponent}
64 * for more detailed information on what a click can be.
66 * @param {EventTarget~Event} event
67 * The `keydown`, `tap`, or `click` event that caused this function to be
75 BigPlayButton.prototype.handleClick = function handleClick(event) {
80 }(_button2['default']);
83 * The text that should display over the `BigPlayButton`s controls. Added to for localization.
90 BigPlayButton.prototype.controlText_ = 'Play Video';
92 _component2['default'].registerComponent('BigPlayButton', BigPlayButton);
93 exports['default'] = BigPlayButton;
95 },{"2":2,"5":5}],2:[function(_dereq_,module,exports){
98 exports.__esModule = true;
100 var _clickableComponent = _dereq_(3);
102 var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
104 var _component = _dereq_(5);
106 var _component2 = _interopRequireDefault(_component);
108 var _log = _dereq_(86);
110 var _log2 = _interopRequireDefault(_log);
112 var _obj = _dereq_(88);
114 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
116 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
118 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
120 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
126 * Base class for all buttons.
128 * @extends ClickableComponent
130 var Button = function (_ClickableComponent) {
131 _inherits(Button, _ClickableComponent);
134 _classCallCheck(this, Button);
136 return _possibleConstructorReturn(this, _ClickableComponent.apply(this, arguments));
140 * Create the `Button`s DOM element.
142 * @param {string} [tag=button]
143 * Element's node type. e.g. 'button'
145 * @param {Object} [props={}]
146 * An object of properties that should be set on the element.
148 * @param {Object} [attributes={}]
149 * An object of attributes that should be set on the element.
152 * The element that gets created.
154 Button.prototype.createEl = function createEl() {
155 var tag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'button';
156 var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
157 var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
159 props = (0, _obj.assign)({
160 className: this.buildCSSClass()
163 if (tag !== 'button') {
164 _log2['default'].warn('Creating a Button with an HTML element of ' + tag + ' is deprecated; use ClickableComponent instead.');
166 // Add properties for clickable element which is not a native HTML button
167 props = (0, _obj.assign)({
171 // Add ARIA attributes for clickable element which is not a native HTML button
172 attributes = (0, _obj.assign)({
177 // Add attributes for button element
178 attributes = (0, _obj.assign)({
180 // Necessary since the default button type is "submit"
183 // let the screen reader user know that the text of the button may change
184 'aria-live': 'polite'
187 var el = _component2['default'].prototype.createEl.call(this, tag, props, attributes);
189 this.createControlTextEl(el);
195 * Add a child `Component` inside of this `Button`.
197 * @param {string|Component} child
198 * The name or instance of a child to add.
200 * @param {Object} [options={}]
201 * The key/value store of options that will get passed to children of
204 * @return {Component}
205 * The `Component` that gets added as a child. When using a string the
206 * `Component` will get created by this process.
208 * @deprecated since version 5
212 Button.prototype.addChild = function addChild(child) {
213 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
215 var className = this.constructor.name;
217 _log2['default'].warn('Adding an actionable (user controllable) child to a Button (' + className + ') is not supported; use a ClickableComponent instead.');
219 // Avoid the error message generated by ClickableComponent's addChild method
220 return _component2['default'].prototype.addChild.call(this, child, options);
224 * Enable the `Button` element so that it can be activated or clicked. Use this with
225 * {@link Button#disable}.
229 Button.prototype.enable = function enable() {
230 _ClickableComponent.prototype.enable.call(this);
231 this.el_.removeAttribute('disabled');
235 * Enable the `Button` element so that it cannot be activated or clicked. Use this with
236 * {@link Button#enable}.
240 Button.prototype.disable = function disable() {
241 _ClickableComponent.prototype.disable.call(this);
242 this.el_.setAttribute('disabled', 'disabled');
246 * This gets called when a `Button` has focus and `keydown` is triggered via a key
249 * @param {EventTarget~Event} event
250 * The event that caused this function to get called.
256 Button.prototype.handleKeyPress = function handleKeyPress(event) {
258 // Ignore Space (32) or Enter (13) key operation, which is handled by the browser for a button.
259 if (event.which === 32 || event.which === 13) {
263 // Pass keypress handling up for unsupported keys
264 _ClickableComponent.prototype.handleKeyPress.call(this, event);
268 }(_clickableComponent2['default']);
270 _component2['default'].registerComponent('Button', Button);
271 exports['default'] = Button;
273 },{"3":3,"5":5,"86":86,"88":88}],3:[function(_dereq_,module,exports){
276 exports.__esModule = true;
278 var _component = _dereq_(5);
280 var _component2 = _interopRequireDefault(_component);
282 var _dom = _dereq_(81);
284 var Dom = _interopRequireWildcard(_dom);
286 var _events = _dereq_(82);
288 var Events = _interopRequireWildcard(_events);
290 var _fn = _dereq_(83);
292 var Fn = _interopRequireWildcard(_fn);
294 var _log = _dereq_(86);
296 var _log2 = _interopRequireDefault(_log);
298 var _document = _dereq_(94);
300 var _document2 = _interopRequireDefault(_document);
302 var _obj = _dereq_(88);
304 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
306 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
308 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
310 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
312 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
318 * Clickable Component which is clickable or keyboard actionable,
319 * but is not a native HTML button.
323 var ClickableComponent = function (_Component) {
324 _inherits(ClickableComponent, _Component);
327 * Creates an instance of this class.
329 * @param {Player} player
330 * The `Player` that this class should be attached to.
332 * @param {Object} [options]
333 * The key/value store of player options.
335 function ClickableComponent(player, options) {
336 _classCallCheck(this, ClickableComponent);
338 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
340 _this.emitTapEvents();
347 * Create the `Component`s DOM element.
349 * @param {string} [tag=div]
350 * The element's node type.
352 * @param {Object} [props={}]
353 * An object of properties that should be set on the element.
355 * @param {Object} [attributes={}]
356 * An object of attributes that should be set on the element.
359 * The element that gets created.
363 ClickableComponent.prototype.createEl = function createEl() {
364 var tag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div';
365 var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
366 var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
368 props = (0, _obj.assign)({
369 className: this.buildCSSClass(),
373 if (tag === 'button') {
374 _log2['default'].error('Creating a ClickableComponent with an HTML element of ' + tag + ' is not supported; use a Button instead.');
377 // Add ARIA attributes for clickable element which is not a native HTML button
378 attributes = (0, _obj.assign)({
381 // let the screen reader user know that the text of the element may change
382 'aria-live': 'polite'
385 this.tabIndex_ = props.tabIndex;
387 var el = _Component.prototype.createEl.call(this, tag, props, attributes);
389 this.createControlTextEl(el);
395 * Create a control text element on this `Component`
397 * @param {Element} [el]
398 * Parent element for the control text.
401 * The control text element that gets created.
405 ClickableComponent.prototype.createControlTextEl = function createControlTextEl(el) {
406 this.controlTextEl_ = Dom.createEl('span', {
407 className: 'vjs-control-text'
411 el.appendChild(this.controlTextEl_);
414 this.controlText(this.controlText_, el);
416 return this.controlTextEl_;
420 * Get or set the localize text to use for the controls on the `Component`.
422 * @param {string} [text]
423 * Control text for element.
425 * @param {Element} [el=this.el()]
426 * Element to set the title on.
428 * @return {string|ClickableComponent}
429 * - The control text when getting
430 * - Returns itself when setting; method can be chained.
434 ClickableComponent.prototype.controlText = function controlText(text) {
435 var el = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.el();
438 return this.controlText_ || 'Need Text';
441 var localizedText = this.localize(text);
443 this.controlText_ = text;
444 this.controlTextEl_.innerHTML = localizedText;
445 el.setAttribute('title', localizedText);
451 * Builds the default DOM `className`.
454 * The DOM `className` for this object.
458 ClickableComponent.prototype.buildCSSClass = function buildCSSClass() {
459 return 'vjs-control vjs-button ' + _Component.prototype.buildCSSClass.call(this);
463 * Enable this `Component`s element.
465 * @return {ClickableComponent}
466 * Returns itself; method can be chained.
470 ClickableComponent.prototype.enable = function enable() {
471 this.removeClass('vjs-disabled');
472 this.el_.setAttribute('aria-disabled', 'false');
473 if (typeof this.tabIndex_ !== 'undefined') {
474 this.el_.setAttribute('tabIndex', this.tabIndex_);
476 this.on('tap', this.handleClick);
477 this.on('click', this.handleClick);
478 this.on('focus', this.handleFocus);
479 this.on('blur', this.handleBlur);
484 * Disable this `Component`s element.
486 * @return {ClickableComponent}
487 * Returns itself; method can be chained.
491 ClickableComponent.prototype.disable = function disable() {
492 this.addClass('vjs-disabled');
493 this.el_.setAttribute('aria-disabled', 'true');
494 if (typeof this.tabIndex_ !== 'undefined') {
495 this.el_.removeAttribute('tabIndex');
497 this.off('tap', this.handleClick);
498 this.off('click', this.handleClick);
499 this.off('focus', this.handleFocus);
500 this.off('blur', this.handleBlur);
505 * This gets called when a `ClickableComponent` gets:
506 * - Clicked (via the `click` event, listening starts in the constructor)
507 * - Tapped (via the `tap` event, listening starts in the constructor)
508 * - The following things happen in order:
509 * 1. {@link ClickableComponent#handleFocus} is called via a `focus` event on the
510 * `ClickableComponent`.
511 * 2. {@link ClickableComponent#handleFocus} adds a listener for `keydown` on using
512 * {@link ClickableComponent#handleKeyPress}.
513 * 3. `ClickableComponent` has not had a `blur` event (`blur` means that focus was lost). The user presses
514 * the space or enter key.
515 * 4. {@link ClickableComponent#handleKeyPress} calls this function with the `keydown`
516 * event as a parameter.
518 * @param {EventTarget~Event} event
519 * The `keydown`, `tap`, or `click` event that caused this function to be
528 ClickableComponent.prototype.handleClick = function handleClick(event) {};
531 * This gets called when a `ClickableComponent` gains focus via a `focus` event.
532 * Turns on listening for `keydown` events. When they happen it
533 * calls `this.handleKeyPress`.
535 * @param {EventTarget~Event} event
536 * The `focus` event that caused this function to be called.
542 ClickableComponent.prototype.handleFocus = function handleFocus(event) {
543 Events.on(_document2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
547 * Called when this ClickableComponent has focus and a key gets pressed down. By
548 * default it will call `this.handleClick` when the key is space or enter.
550 * @param {EventTarget~Event} event
551 * The `keydown` event that caused this function to be called.
557 ClickableComponent.prototype.handleKeyPress = function handleKeyPress(event) {
559 // Support Space (32) or Enter (13) key operation to fire a click event
560 if (event.which === 32 || event.which === 13) {
561 event.preventDefault();
562 this.handleClick(event);
563 } else if (_Component.prototype.handleKeyPress) {
565 // Pass keypress handling up for unsupported keys
566 _Component.prototype.handleKeyPress.call(this, event);
571 * Called when a `ClickableComponent` loses focus. Turns off the listener for
572 * `keydown` events. Which Stops `this.handleKeyPress` from getting called.
574 * @param {EventTarget~Event} event
575 * The `blur` event that caused this function to be called.
581 ClickableComponent.prototype.handleBlur = function handleBlur(event) {
582 Events.off(_document2['default'], 'keydown', Fn.bind(this, this.handleKeyPress));
585 return ClickableComponent;
586 }(_component2['default']);
588 _component2['default'].registerComponent('ClickableComponent', ClickableComponent);
589 exports['default'] = ClickableComponent;
591 },{"5":5,"81":81,"82":82,"83":83,"86":86,"88":88,"94":94}],4:[function(_dereq_,module,exports){
594 exports.__esModule = true;
596 var _button = _dereq_(2);
598 var _button2 = _interopRequireDefault(_button);
600 var _component = _dereq_(5);
602 var _component2 = _interopRequireDefault(_component);
604 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
606 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
608 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
610 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
611 * @file close-button.js
616 * The `CloseButton` is a `{@link Button}` that fires a `close` event when
621 var CloseButton = function (_Button) {
622 _inherits(CloseButton, _Button);
625 * Creates an instance of the this class.
627 * @param {Player} player
628 * The `Player` that this class should be attached to.
630 * @param {Object} [options]
631 * The key/value store of player options.
633 function CloseButton(player, options) {
634 _classCallCheck(this, CloseButton);
636 var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
638 _this.controlText(options && options.controlText || _this.localize('Close'));
643 * Builds the default DOM `className`.
646 * The DOM `className` for this object.
650 CloseButton.prototype.buildCSSClass = function buildCSSClass() {
651 return 'vjs-close-button ' + _Button.prototype.buildCSSClass.call(this);
655 * This gets called when a `CloseButton` gets clicked. See
656 * {@link ClickableComponent#handleClick} for more information on when this will be
659 * @param {EventTarget~Event} event
660 * The `keydown`, `tap`, or `click` event that caused this function to be
665 * @fires CloseButton#close
669 CloseButton.prototype.handleClick = function handleClick(event) {
672 * Triggered when the a `CloseButton` is clicked.
674 * @event CloseButton#close
675 * @type {EventTarget~Event}
677 * @property {boolean} [bubbles=false]
678 * set to false so that the close event does not
679 * bubble up to parents if there is no listener
681 this.trigger({ type: 'close', bubbles: false });
685 }(_button2['default']);
687 _component2['default'].registerComponent('CloseButton', CloseButton);
688 exports['default'] = CloseButton;
690 },{"2":2,"5":5}],5:[function(_dereq_,module,exports){
693 exports.__esModule = true;
695 var _window = _dereq_(95);
697 var _window2 = _interopRequireDefault(_window);
699 var _dom = _dereq_(81);
701 var Dom = _interopRequireWildcard(_dom);
703 var _fn = _dereq_(83);
705 var Fn = _interopRequireWildcard(_fn);
707 var _guid = _dereq_(85);
709 var Guid = _interopRequireWildcard(_guid);
711 var _events = _dereq_(82);
713 var Events = _interopRequireWildcard(_events);
715 var _log = _dereq_(86);
717 var _log2 = _interopRequireDefault(_log);
719 var _toTitleCase = _dereq_(91);
721 var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
723 var _mergeOptions = _dereq_(87);
725 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
727 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
729 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
731 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
732 * Player Component - Base class for all UI objects
739 * Base class for all UI Components.
740 * Components are UI objects which represent both a javascript object and an element
741 * in the DOM. They can be children of other components, and can have
742 * children themselves.
744 * Components can also use methods from {@link EventTarget}
746 var Component = function () {
749 * A callback that is called when a component is ready. Does not have any
750 * parameters and any callback value will be ignored.
752 * @callback Component~ReadyCallback
757 * Creates an instance of this class.
759 * @param {Player} player
760 * The `Player` that this class should be attached to.
762 * @param {Object} [options]
763 * The key/value store of player options.
765 * @param {Object[]} [options.children]
766 * An array of children objects to initialize this component with. Children objects have
767 * a name property that will be used if more than one component of the same type needs to be
770 * @param {Component~ReadyCallback} [ready]
771 * Function that gets called when the `Component` is ready.
773 function Component(player, options, ready) {
774 _classCallCheck(this, Component);
776 // The component might be the player itself and we can't pass `this` to super
777 if (!player && this.play) {
778 this.player_ = player = this; // eslint-disable-line
780 this.player_ = player;
783 // Make a copy of prototype.options_ to protect against overriding defaults
784 this.options_ = (0, _mergeOptions2['default'])({}, this.options_);
786 // Updated options with supplied options
787 options = this.options_ = (0, _mergeOptions2['default'])(this.options_, options);
789 // Get ID from options or options element if one is supplied
790 this.id_ = options.id || options.el && options.el.id;
792 // If there was no ID from the options, generate one
794 // Don't require the player ID function in the case of mock players
795 var id = player && player.id && player.id() || 'no_player';
797 this.id_ = id + '_component_' + Guid.newGUID();
800 this.name_ = options.name || null;
802 // Create element if one wasn't provided in options
804 this.el_ = options.el;
805 } else if (options.createEl !== false) {
806 this.el_ = this.createEl();
810 this.childIndex_ = {};
811 this.childNameIndex_ = {};
813 // Add any child components in options
814 if (options.initChildren !== false) {
819 // Don't want to trigger ready here or it will before init is actually
820 // finished for all children that run this constructor
822 if (options.reportTouchActivity !== false) {
823 this.enableTouchActivity();
828 * Dispose of the `Component` and all child components.
830 * @fires Component#dispose
834 Component.prototype.dispose = function dispose() {
837 * Triggered when a `Component` is disposed.
839 * @event Component#dispose
840 * @type {EventTarget~Event}
842 * @property {boolean} [bubbles=false]
843 * set to false so that the close event does not
846 this.trigger({ type: 'dispose', bubbles: false });
848 // Dispose all children.
849 if (this.children_) {
850 for (var i = this.children_.length - 1; i >= 0; i--) {
851 if (this.children_[i].dispose) {
852 this.children_[i].dispose();
857 // Delete child references
858 this.children_ = null;
859 this.childIndex_ = null;
860 this.childNameIndex_ = null;
862 // Remove all event listeners.
865 // Remove element from DOM
866 if (this.el_.parentNode) {
867 this.el_.parentNode.removeChild(this.el_);
870 Dom.removeElData(this.el_);
875 * Return the {@link Player} that the `Component` has attached to.
878 * The player that this `Component` has attached to.
882 Component.prototype.player = function player() {
887 * Deep merge of options objects with new options.
888 * > Note: When both `obj` and `options` contain properties whose values are objects.
889 * The two properties get merged using {@link module:mergeOptions}
891 * @param {Object} obj
892 * The object that contains new options.
895 * A new object of `this.options_` and `obj` merged together.
897 * @deprecated since version 5
901 Component.prototype.options = function options(obj) {
902 _log2['default'].warn('this.options() has been deprecated and will be moved to the constructor in 6.0');
905 return this.options_;
908 this.options_ = (0, _mergeOptions2['default'])(this.options_, obj);
909 return this.options_;
913 * Get the `Component`s DOM element
916 * The DOM element for this `Component`.
920 Component.prototype.el = function el() {
925 * Create the `Component`s DOM element.
927 * @param {string} [tagName]
928 * Element's DOM node type. e.g. 'div'
930 * @param {Object} [properties]
931 * An object of properties that should be set.
933 * @param {Object} [attributes]
934 * An object of attributes that should be set.
937 * The element that gets created.
941 Component.prototype.createEl = function createEl(tagName, properties, attributes) {
942 return Dom.createEl(tagName, properties, attributes);
946 * Localize a string given the string in english.
948 * @param {string} string
949 * The string to localize.
952 * The localized string or if no localization exists the english string.
956 Component.prototype.localize = function localize(string) {
957 var code = this.player_.language && this.player_.language();
958 var languages = this.player_.languages && this.player_.languages();
960 if (!code || !languages) {
964 var language = languages[code];
966 if (language && language[string]) {
967 return language[string];
970 var primaryCode = code.split('-')[0];
971 var primaryLang = languages[primaryCode];
973 if (primaryLang && primaryLang[string]) {
974 return primaryLang[string];
981 * Return the `Component`s DOM element. This is where children get inserted.
982 * This will usually be the the same as the element returned in {@link Component#el}.
985 * The content element for this `Component`.
989 Component.prototype.contentEl = function contentEl() {
990 return this.contentEl_ || this.el_;
994 * Get this `Component`s ID
997 * The id of this `Component`
1001 Component.prototype.id = function id() {
1006 * Get the `Component`s name. The name gets used to reference the `Component`
1007 * and is set during registration.
1010 * The name of this `Component`.
1014 Component.prototype.name = function name() {
1019 * Get an array of all child components
1026 Component.prototype.children = function children() {
1027 return this.children_;
1031 * Returns the child `Component` with the given `id`.
1033 * @param {string} id
1034 * The id of the child `Component` to get.
1036 * @return {Component|undefined}
1037 * The child `Component` with the given `id` or undefined.
1041 Component.prototype.getChildById = function getChildById(id) {
1042 return this.childIndex_[id];
1046 * Returns the child `Component` with the given `name`.
1048 * @param {string} name
1049 * The name of the child `Component` to get.
1051 * @return {Component|undefined}
1052 * The child `Component` with the given `name` or undefined.
1056 Component.prototype.getChild = function getChild(name) {
1061 name = (0, _toTitleCase2['default'])(name);
1063 return this.childNameIndex_[name];
1067 * Add a child `Component` inside the current `Component`.
1070 * @param {string|Component} child
1071 * The name or instance of a child to add.
1073 * @param {Object} [options={}]
1074 * The key/value store of options that will get passed to children of
1077 * @param {number} [index=this.children_.length]
1078 * The index to attempt to add a child into.
1080 * @return {Component}
1081 * The `Component` that gets added as a child. When using a string the
1082 * `Component` will get created by this process.
1086 Component.prototype.addChild = function addChild(child) {
1087 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
1088 var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.children_.length;
1090 var component = void 0;
1091 var componentName = void 0;
1093 // If child is a string, create component with options
1094 if (typeof child === 'string') {
1095 componentName = (0, _toTitleCase2['default'])(child);
1097 // Options can also be specified as a boolean,
1098 // so convert to an empty object if false.
1103 // Same as above, but true is deprecated so show a warning.
1104 if (options === true) {
1105 _log2['default'].warn('Initializing a child component with `true` is deprecated.' + 'Children should be defined in an array when possible, ' + 'but if necessary use an object instead of `true`.');
1109 var componentClassName = options.componentClass || componentName;
1111 // Set name through options
1112 options.name = componentName;
1114 // Create a new object & element for this controls set
1115 // If there's no .player_, this is a player
1116 var ComponentClass = Component.getComponent(componentClassName);
1118 if (!ComponentClass) {
1119 throw new Error('Component ' + componentClassName + ' does not exist');
1122 // data stored directly on the videojs object may be
1123 // misidentified as a component to retain
1124 // backwards-compatibility with 4.x. check to make sure the
1125 // component class can be instantiated.
1126 if (typeof ComponentClass !== 'function') {
1130 component = new ComponentClass(this.player_ || this, options);
1132 // child is a component instance
1137 this.children_.splice(index, 0, component);
1139 if (typeof component.id === 'function') {
1140 this.childIndex_[component.id()] = component;
1143 // If a name wasn't used to create the component, check if we can use the
1144 // name function of the component
1145 componentName = componentName || component.name && component.name();
1147 if (componentName) {
1148 this.childNameIndex_[componentName] = component;
1151 // Add the UI object's element to the container div (box)
1152 // Having an element is not required
1153 if (typeof component.el === 'function' && component.el()) {
1154 var childNodes = this.contentEl().children;
1155 var refNode = childNodes[index] || null;
1157 this.contentEl().insertBefore(component.el(), refNode);
1160 // Return so it can stored on parent object if desired.
1165 * Remove a child `Component` from this `Component`s list of children. Also removes
1166 * the child `Component`s element from this `Component`s element.
1168 * @param {Component} component
1169 * The child `Component` to remove.
1173 Component.prototype.removeChild = function removeChild(component) {
1174 if (typeof component === 'string') {
1175 component = this.getChild(component);
1178 if (!component || !this.children_) {
1182 var childFound = false;
1184 for (var i = this.children_.length - 1; i >= 0; i--) {
1185 if (this.children_[i] === component) {
1187 this.children_.splice(i, 1);
1196 this.childIndex_[component.id()] = null;
1197 this.childNameIndex_[component.name()] = null;
1199 var compEl = component.el();
1201 if (compEl && compEl.parentNode === this.contentEl()) {
1202 this.contentEl().removeChild(component.el());
1207 * Add and initialize default child `Component`s based upon options.
1211 Component.prototype.initChildren = function initChildren() {
1214 var children = this.options_.children;
1218 // `this` is `parent`
1219 var parentOptions = _this.options_;
1221 var handleAdd = function handleAdd(child) {
1222 var name = child.name;
1223 var opts = child.opts;
1225 // Allow options for children to be set at the parent options
1226 // e.g. videojs(id, { controlBar: false });
1227 // instead of videojs(id, { children: { controlBar: false });
1228 if (parentOptions[name] !== undefined) {
1229 opts = parentOptions[name];
1232 // Allow for disabling default components
1233 // e.g. options['children']['posterImage'] = false
1234 if (opts === false) {
1238 // Allow options to be passed as a simple boolean if no configuration
1240 if (opts === true) {
1244 // We also want to pass the original player options
1245 // to each component as well so they don't need to
1246 // reach back into the player for options later.
1247 opts.playerOptions = _this.options_.playerOptions;
1249 // Create and add the child component.
1250 // Add a direct reference to the child by name on the parent instance.
1251 // If two of the same component are used, different names should be supplied
1253 var newChild = _this.addChild(name, opts);
1256 _this[name] = newChild;
1260 // Allow for an array of children details to passed in the options
1261 var workingChildren = void 0;
1262 var Tech = Component.getComponent('Tech');
1264 if (Array.isArray(children)) {
1265 workingChildren = children;
1267 workingChildren = Object.keys(children);
1271 // children that are in this.options_ but also in workingChildren would
1272 // give us extra children we do not want. So, we want to filter them out.
1273 .concat(Object.keys(_this.options_).filter(function (child) {
1274 return !workingChildren.some(function (wchild) {
1275 if (typeof wchild === 'string') {
1276 return child === wchild;
1278 return child === wchild.name;
1280 })).map(function (child) {
1284 if (typeof child === 'string') {
1286 opts = children[name] || _this.options_[name] || {};
1292 return { name: name, opts: opts };
1293 }).filter(function (child) {
1294 // we have to make sure that child.name isn't in the techOrder since
1295 // techs are registered as Components but can't aren't compatible
1296 // See https://github.com/videojs/video.js/issues/2772
1297 var c = Component.getComponent(child.opts.componentClass || (0, _toTitleCase2['default'])(child.name));
1299 return c && !Tech.isTech(c);
1300 }).forEach(handleAdd);
1306 * Builds the default DOM class name. Should be overridden by sub-components.
1309 * The DOM class name for this object.
1315 Component.prototype.buildCSSClass = function buildCSSClass() {
1316 // Child classes can include a function that does:
1317 // return 'CLASS NAME' + this._super();
1322 * Add an `event listener` to this `Component`s element.
1324 * The benefit of using this over the following:
1325 * - `VjsEvents.on(otherElement, 'eventName', myFunc)`
1326 * - `otherComponent.on('eventName', myFunc)`
1328 * 1. Is that the listeners will get cleaned up when either component gets disposed.
1329 * 1. It will also bind `myComponent` as the context of `myFunc`.
1330 * > NOTE: If you remove the element from the DOM that has used `on` you need to
1331 * clean up references using: `myComponent.trigger(el, 'dispose')`
1332 * This will also allow the browser to garbage collect it. In special
1333 * cases such as with `window` and `document`, which are both permanent,
1334 * this is not necessary.
1336 * @param {string|Component|string[]} [first]
1337 * The event name, and array of event names, or another `Component`.
1339 * @param {EventTarget~EventListener|string|string[]} [second]
1340 * The listener function, an event name, or an Array of events names.
1342 * @param {EventTarget~EventListener} [third]
1343 * The event handler if `first` is a `Component` and `second` is an event name
1344 * or an Array of event names.
1346 * @return {Component}
1347 * Returns itself; method can be chained.
1349 * @listens Component#dispose
1353 Component.prototype.on = function on(first, second, third) {
1356 if (typeof first === 'string' || Array.isArray(first)) {
1357 Events.on(this.el_, first, Fn.bind(this, second));
1359 // Targeting another component or element
1364 var fn = Fn.bind(_this2, third);
1366 // When this component is disposed, remove the listener from the other component
1367 var removeOnDispose = function removeOnDispose() {
1368 return _this2.off(target, type, fn);
1371 // Use the same function ID so we can remove it later it using the ID
1372 // of the original listener
1373 removeOnDispose.guid = fn.guid;
1374 _this2.on('dispose', removeOnDispose);
1376 // If the other component is disposed first we need to clean the reference
1377 // to the other component in this component's removeOnDispose listener
1378 // Otherwise we create a memory leak.
1379 var cleanRemover = function cleanRemover() {
1380 return _this2.off('dispose', removeOnDispose);
1383 // Add the same function ID so we can easily remove it later
1384 cleanRemover.guid = fn.guid;
1386 // Check if this is a DOM node
1387 if (first.nodeName) {
1388 // Add the listener to the other element
1389 Events.on(target, type, fn);
1390 Events.on(target, 'dispose', cleanRemover);
1392 // Should be a component
1393 // Not using `instanceof Component` because it makes mock players difficult
1394 } else if (typeof first.on === 'function') {
1395 // Add the listener to the other component
1396 target.on(type, fn);
1397 target.on('dispose', cleanRemover);
1406 * Remove an event listener from this `Component`s element. If the second argument is
1407 * excluded all listeners for the type passed in as the first argument will be removed.
1409 * @param {string|Component|string[]} [first]
1410 * The event name, and array of event names, or another `Component`.
1412 * @param {EventTarget~EventListener|string|string[]} [second]
1413 * The listener function, an event name, or an Array of events names.
1415 * @param {EventTarget~EventListener} [third]
1416 * The event handler if `first` is a `Component` and `second` is an event name
1417 * or an Array of event names.
1419 * @return {Component}
1420 * Returns itself; method can be chained.
1424 Component.prototype.off = function off(first, second, third) {
1425 if (!first || typeof first === 'string' || Array.isArray(first)) {
1426 Events.off(this.el_, first, second);
1430 // Ensure there's at least a guid, even if the function hasn't been used
1431 var fn = Fn.bind(this, third);
1433 // Remove the dispose listener on this component,
1434 // which was given the same guid as the event listener
1435 this.off('dispose', fn);
1437 if (first.nodeName) {
1438 // Remove the listener
1439 Events.off(target, type, fn);
1440 // Remove the listener for cleaning the dispose listener
1441 Events.off(target, 'dispose', fn);
1443 target.off(type, fn);
1444 target.off('dispose', fn);
1452 * Add an event listener that gets triggered only once and then gets removed.
1454 * @param {string|Component|string[]} [first]
1455 * The event name, and array of event names, or another `Component`.
1457 * @param {EventTarget~EventListener|string|string[]} [second]
1458 * The listener function, an event name, or an Array of events names.
1460 * @param {EventTarget~EventListener} [third]
1461 * The event handler if `first` is a `Component` and `second` is an event name
1462 * or an Array of event names.
1464 * @return {Component}
1465 * Returns itself; method can be chained.
1469 Component.prototype.one = function one(first, second, third) {
1471 _arguments = arguments;
1473 if (typeof first === 'string' || Array.isArray(first)) {
1474 Events.one(this.el_, first, Fn.bind(this, second));
1479 var fn = Fn.bind(_this3, third);
1481 var newFunc = function newFunc() {
1482 _this3.off(target, type, newFunc);
1483 fn.apply(null, _arguments);
1486 // Keep the same function ID so we can remove it later
1487 newFunc.guid = fn.guid;
1489 _this3.on(target, type, newFunc);
1497 * Trigger an event on an element.
1499 * @param {EventTarget~Event|Object|string} event
1500 * The event name, and Event, or an event-like object with a type attribute
1501 * set to the event name.
1503 * @param {Object} [hash]
1504 * Data hash to pass along with the event
1506 * @return {Component}
1507 * Returns itself; method can be chained.
1511 Component.prototype.trigger = function trigger(event, hash) {
1512 Events.trigger(this.el_, event, hash);
1517 * Bind a listener to the component's ready state. If the ready event has already
1518 * happened it will trigger the function immediately.
1520 * @param {Component~ReadyCallback} fn
1521 * A function to call when ready is triggered.
1523 * @param {boolean} [sync=false]
1524 * Execute the listener synchronously if `Component` is ready.
1526 * @return {Component}
1527 * Returns itself; method can be chained.
1531 Component.prototype.ready = function ready(fn) {
1532 var sync = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1535 if (this.isReady_) {
1539 // Call the function asynchronously by default for consistency
1540 this.setTimeout(fn, 1);
1543 this.readyQueue_ = this.readyQueue_ || [];
1544 this.readyQueue_.push(fn);
1551 * Trigger all the ready listeners for this `Component`.
1553 * @fires Component#ready
1557 Component.prototype.triggerReady = function triggerReady() {
1558 this.isReady_ = true;
1560 // Ensure ready is triggered asynchronously
1561 this.setTimeout(function () {
1562 var readyQueue = this.readyQueue_;
1564 // Reset Ready Queue
1565 this.readyQueue_ = [];
1567 if (readyQueue && readyQueue.length > 0) {
1568 readyQueue.forEach(function (fn) {
1573 // Allow for using event listeners also
1575 * Triggered when a `Component` is ready.
1577 * @event Component#ready
1578 * @type {EventTarget~Event}
1580 this.trigger('ready');
1585 * Find a single DOM element matching a `selector`. This can be within the `Component`s
1586 * `contentEl()` or another custom context.
1588 * @param {string} selector
1589 * A valid CSS selector, which will be passed to `querySelector`.
1591 * @param {Element|string} [context=this.contentEl()]
1592 * A DOM element within which to query. Can also be a selector string in
1593 * which case the first matching element will get used as context. If
1594 * missing `this.contentEl()` gets used. If `this.contentEl()` returns
1595 * nothing it falls back to `document`.
1597 * @return {Element|null}
1598 * the dom element that was found, or null
1600 * @see [Information on CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_Started/Selectors)
1604 Component.prototype.$ = function $(selector, context) {
1605 return Dom.$(selector, context || this.contentEl());
1609 * Finds all DOM element matching a `selector`. This can be within the `Component`s
1610 * `contentEl()` or another custom context.
1612 * @param {string} selector
1613 * A valid CSS selector, which will be passed to `querySelectorAll`.
1615 * @param {Element|string} [context=this.contentEl()]
1616 * A DOM element within which to query. Can also be a selector string in
1617 * which case the first matching element will get used as context. If
1618 * missing `this.contentEl()` gets used. If `this.contentEl()` returns
1619 * nothing it falls back to `document`.
1621 * @return {NodeList}
1622 * a list of dom elements that were found
1624 * @see [Information on CSS Selectors](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_Started/Selectors)
1628 Component.prototype.$$ = function $$(selector, context) {
1629 return Dom.$$(selector, context || this.contentEl());
1633 * Check if a component's element has a CSS class name.
1635 * @param {string} classToCheck
1636 * CSS class name to check.
1639 * - True if the `Component` has the class.
1640 * - False if the `Component` does not have the class`
1644 Component.prototype.hasClass = function hasClass(classToCheck) {
1645 return Dom.hasElClass(this.el_, classToCheck);
1649 * Add a CSS class name to the `Component`s element.
1651 * @param {string} classToAdd
1652 * CSS class name to add
1654 * @return {Component}
1655 * Returns itself; method can be chained.
1659 Component.prototype.addClass = function addClass(classToAdd) {
1660 Dom.addElClass(this.el_, classToAdd);
1665 * Remove a CSS class name from the `Component`s element.
1667 * @param {string} classToRemove
1668 * CSS class name to remove
1670 * @return {Component}
1671 * Returns itself; method can be chained.
1675 Component.prototype.removeClass = function removeClass(classToRemove) {
1676 Dom.removeElClass(this.el_, classToRemove);
1681 * Add or remove a CSS class name from the component's element.
1682 * - `classToToggle` gets added when {@link Component#hasClass} would return false.
1683 * - `classToToggle` gets removed when {@link Component#hasClass} would return true.
1685 * @param {string} classToToggle
1686 * The class to add or remove based on (@link Component#hasClass}
1688 * @param {boolean|Dom~predicate} [predicate]
1689 * An {@link Dom~predicate} function or a boolean
1691 * @return {Component}
1692 * Returns itself; method can be chained.
1696 Component.prototype.toggleClass = function toggleClass(classToToggle, predicate) {
1697 Dom.toggleElClass(this.el_, classToToggle, predicate);
1702 * Show the `Component`s element if it is hidden by removing the
1703 * 'vjs-hidden' class name from it.
1705 * @return {Component}
1706 * Returns itself; method can be chained.
1710 Component.prototype.show = function show() {
1711 this.removeClass('vjs-hidden');
1716 * Hide the `Component`s element if it is currently showing by adding the
1717 * 'vjs-hidden` class name to it.
1719 * @return {Component}
1720 * Returns itself; method can be chained.
1724 Component.prototype.hide = function hide() {
1725 this.addClass('vjs-hidden');
1730 * Lock a `Component`s element in its visible state by adding the 'vjs-lock-showing'
1731 * class name to it. Used during fadeIn/fadeOut.
1733 * @return {Component}
1734 * Returns itself; method can be chained.
1740 Component.prototype.lockShowing = function lockShowing() {
1741 this.addClass('vjs-lock-showing');
1746 * Unlock a `Component`s element from its visible state by removing the 'vjs-lock-showing'
1747 * class name from it. Used during fadeIn/fadeOut.
1749 * @return {Component}
1750 * Returns itself; method can be chained.
1756 Component.prototype.unlockShowing = function unlockShowing() {
1757 this.removeClass('vjs-lock-showing');
1762 * Get the value of an attribute on the `Component`s element.
1764 * @param {string} attribute
1765 * Name of the attribute to get the value from.
1767 * @return {string|null}
1768 * - The value of the attribute that was asked for.
1769 * - Can be an empty string on some browsers if the attribute does not exist
1771 * - Most browsers will return null if the attribute does not exist or has
1774 * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute}
1778 Component.prototype.getAttribute = function getAttribute(attribute) {
1779 return Dom.getAttribute(this.el_, attribute);
1783 * Set the value of an attribute on the `Component`'s element
1785 * @param {string} attribute
1786 * Name of the attribute to set.
1788 * @param {string} value
1789 * Value to set the attribute to.
1791 * @return {Component}
1792 * Returns itself; method can be chained.
1794 * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute}
1798 Component.prototype.setAttribute = function setAttribute(attribute, value) {
1799 Dom.setAttribute(this.el_, attribute, value);
1804 * Remove an attribute from the `Component`s element.
1806 * @param {string} attribute
1807 * Name of the attribute to remove.
1809 * @return {Component}
1810 * Returns itself; method can be chained.
1812 * @see [DOM API]{@link https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute}
1816 Component.prototype.removeAttribute = function removeAttribute(attribute) {
1817 Dom.removeAttribute(this.el_, attribute);
1822 * Get or set the width of the component based upon the CSS styles.
1823 * See {@link Component#dimension} for more detailed information.
1825 * @param {number|string} [num]
1826 * The width that you want to set postfixed with '%', 'px' or nothing.
1828 * @param {boolean} [skipListeners]
1829 * Skip the resize event trigger
1831 * @return {Component|number|string}
1832 * - The width when getting, zero if there is no width. Can be a string
1833 * postpixed with '%' or 'px'.
1834 * - Returns itself when setting; method can be chained.
1838 Component.prototype.width = function width(num, skipListeners) {
1839 return this.dimension('width', num, skipListeners);
1843 * Get or set the height of the component based upon the CSS styles.
1844 * See {@link Component#dimension} for more detailed information.
1846 * @param {number|string} [num]
1847 * The height that you want to set postfixed with '%', 'px' or nothing.
1849 * @param {boolean} [skipListeners]
1850 * Skip the resize event trigger
1852 * @return {Component|number|string}
1853 * - The width when getting, zero if there is no width. Can be a string
1854 * postpixed with '%' or 'px'.
1855 * - Returns itself when setting; method can be chained.
1859 Component.prototype.height = function height(num, skipListeners) {
1860 return this.dimension('height', num, skipListeners);
1864 * Set both the width and height of the `Component` element at the same time.
1866 * @param {number|string} width
1867 * Width to set the `Component`s element to.
1869 * @param {number|string} height
1870 * Height to set the `Component`s element to.
1872 * @return {Component}
1873 * Returns itself; method can be chained.
1877 Component.prototype.dimensions = function dimensions(width, height) {
1878 // Skip resize listeners on width for optimization
1879 return this.width(width, true).height(height);
1883 * Get or set width or height of the `Component` element. This is the shared code
1884 * for the {@link Component#width} and {@link Component#height}.
1887 * - If the width or height in an number this will return the number postfixed with 'px'.
1888 * - If the width/height is a percent this will return the percent postfixed with '%'
1889 * - Hidden elements have a width of 0 with `window.getComputedStyle`. This function
1890 * defaults to the `Component`s `style.width` and falls back to `window.getComputedStyle`.
1891 * See [this]{@link http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/}
1892 * for more information
1893 * - If you want the computed style of the component, use {@link Component#currentWidth}
1894 * and {@link {Component#currentHeight}
1896 * @fires Component#resize
1898 * @param {string} widthOrHeight
1899 8 'width' or 'height'
1901 * @param {number|string} [num]
1904 * @param {boolean} [skipListeners]
1905 * Skip resize event trigger
1907 * @return {Component}
1908 * - the dimension when getting or 0 if unset
1909 * - Returns itself when setting; method can be chained.
1913 Component.prototype.dimension = function dimension(widthOrHeight, num, skipListeners) {
1914 if (num !== undefined) {
1915 // Set to zero if null or literally NaN (NaN !== NaN)
1916 if (num === null || num !== num) {
1920 // Check if using css width/height (% or px) and adjust
1921 if (('' + num).indexOf('%') !== -1 || ('' + num).indexOf('px') !== -1) {
1922 this.el_.style[widthOrHeight] = num;
1923 } else if (num === 'auto') {
1924 this.el_.style[widthOrHeight] = '';
1926 this.el_.style[widthOrHeight] = num + 'px';
1929 // skipListeners allows us to avoid triggering the resize event when setting both width and height
1930 if (!skipListeners) {
1932 * Triggered when a component is resized.
1934 * @event Component#resize
1935 * @type {EventTarget~Event}
1937 this.trigger('resize');
1944 // Not setting a value, so getting it
1945 // Make sure element exists
1950 // Get dimension value from style
1951 var val = this.el_.style[widthOrHeight];
1952 var pxIndex = val.indexOf('px');
1954 if (pxIndex !== -1) {
1955 // Return the pixel value with no 'px'
1956 return parseInt(val.slice(0, pxIndex), 10);
1959 // No px so using % or no style was set, so falling back to offsetWidth/height
1960 // If component has display:none, offset will return 0
1961 // TODO: handle display:none and no dimension style using px
1962 return parseInt(this.el_['offset' + (0, _toTitleCase2['default'])(widthOrHeight)], 10);
1966 * Get the width or the height of the `Component` elements computed style. Uses
1967 * `window.getComputedStyle`.
1969 * @param {string} widthOrHeight
1970 * A string containing 'width' or 'height'. Whichever one you want to get.
1973 * The dimension that gets asked for or 0 if nothing was set
1974 * for that dimension.
1978 Component.prototype.currentDimension = function currentDimension(widthOrHeight) {
1979 var computedWidthOrHeight = 0;
1981 if (widthOrHeight !== 'width' && widthOrHeight !== 'height') {
1982 throw new Error('currentDimension only accepts width or height value');
1985 if (typeof _window2['default'].getComputedStyle === 'function') {
1986 var computedStyle = _window2['default'].getComputedStyle(this.el_);
1988 computedWidthOrHeight = computedStyle.getPropertyValue(widthOrHeight) || computedStyle[widthOrHeight];
1991 // remove 'px' from variable and parse as integer
1992 computedWidthOrHeight = parseFloat(computedWidthOrHeight);
1994 // if the computed value is still 0, it's possible that the browser is lying
1995 // and we want to check the offset values.
1996 // This code also runs on IE8 and wherever getComputedStyle doesn't exist.
1997 if (computedWidthOrHeight === 0) {
1998 var rule = 'offset' + (0, _toTitleCase2['default'])(widthOrHeight);
2000 computedWidthOrHeight = this.el_[rule];
2003 return computedWidthOrHeight;
2007 * An object that contains width and height values of the `Component`s
2008 * computed style. Uses `window.getComputedStyle`.
2010 * @typedef {Object} Component~DimensionObject
2012 * @property {number} width
2013 * The width of the `Component`s computed style.
2015 * @property {number} height
2016 * The height of the `Component`s computed style.
2020 * Get an object that contains width and height values of the `Component`s
2023 * @return {Component~DimensionObject}
2024 * The dimensions of the components element
2028 Component.prototype.currentDimensions = function currentDimensions() {
2030 width: this.currentDimension('width'),
2031 height: this.currentDimension('height')
2036 * Get the width of the `Component`s computed style. Uses `window.getComputedStyle`.
2038 * @return {number} width
2039 * The width of the `Component`s computed style.
2043 Component.prototype.currentWidth = function currentWidth() {
2044 return this.currentDimension('width');
2048 * Get the height of the `Component`s computed style. Uses `window.getComputedStyle`.
2050 * @return {number} height
2051 * The height of the `Component`s computed style.
2055 Component.prototype.currentHeight = function currentHeight() {
2056 return this.currentDimension('height');
2060 * Emit a 'tap' events when touch event support gets detected. This gets used to
2061 * support toggling the controls through a tap on the video. They get enabled
2062 * because every sub-component would have extra overhead otherwise.
2065 * @fires Component#tap
2066 * @listens Component#touchstart
2067 * @listens Component#touchmove
2068 * @listens Component#touchleave
2069 * @listens Component#touchcancel
2070 * @listens Component#touchend
2074 Component.prototype.emitTapEvents = function emitTapEvents() {
2075 // Track the start time so we can determine how long the touch lasted
2077 var firstTouch = null;
2079 // Maximum movement allowed during a touch event to still be considered a tap
2080 // Other popular libs use anywhere from 2 (hammer.js) to 15,
2081 // so 10 seems like a nice, round number.
2082 var tapMovementThreshold = 10;
2084 // The maximum length a touch can be while still being considered a tap
2085 var touchTimeThreshold = 200;
2087 var couldBeTap = void 0;
2089 this.on('touchstart', function (event) {
2090 // If more than one finger, don't consider treating this as a click
2091 if (event.touches.length === 1) {
2092 // Copy pageX/pageY from the object
2094 pageX: event.touches[0].pageX,
2095 pageY: event.touches[0].pageY
2097 // Record start time so we can detect a tap vs. "touch and hold"
2098 touchStart = new Date().getTime();
2099 // Reset couldBeTap tracking
2104 this.on('touchmove', function (event) {
2105 // If more than one finger, don't consider treating this as a click
2106 if (event.touches.length > 1) {
2108 } else if (firstTouch) {
2109 // Some devices will throw touchmoves for all but the slightest of taps.
2110 // So, if we moved only a small distance, this could still be a tap
2111 var xdiff = event.touches[0].pageX - firstTouch.pageX;
2112 var ydiff = event.touches[0].pageY - firstTouch.pageY;
2113 var touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
2115 if (touchDistance > tapMovementThreshold) {
2121 var noTap = function noTap() {
2125 // TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s
2126 this.on('touchleave', noTap);
2127 this.on('touchcancel', noTap);
2129 // When the touch ends, measure how long it took and trigger the appropriate
2131 this.on('touchend', function (event) {
2133 // Proceed only if the touchmove/leave/cancel event didn't happen
2134 if (couldBeTap === true) {
2135 // Measure how long the touch lasted
2136 var touchTime = new Date().getTime() - touchStart;
2138 // Make sure the touch was less than the threshold to be considered a tap
2139 if (touchTime < touchTimeThreshold) {
2140 // Don't let browser turn this into a click
2141 event.preventDefault();
2143 * Triggered when a `Component` is tapped.
2145 * @event Component#tap
2146 * @type {EventTarget~Event}
2148 this.trigger('tap');
2149 // It may be good to copy the touchend event object and change the
2150 // type to tap, if the other event properties aren't exact after
2151 // Events.fixEvent runs (e.g. event.target)
2158 * This function reports user activity whenever touch events happen. This can get
2159 * turned off by any sub-components that wants touch events to act another way.
2161 * Report user touch activity when touch events occur. User activity gets used to
2162 * determine when controls should show/hide. It is simple when it comes to mouse
2163 * events, because any mouse event should show the controls. So we capture mouse
2164 * events that bubble up to the player and report activity when that happens.
2165 * With touch events it isn't as easy as `touchstart` and `touchend` toggle player
2166 * controls. So touch events can't help us at the player level either.
2168 * User activity gets checked asynchronously. So what could happen is a tap event
2169 * on the video turns the controls off. Then the `touchend` event bubbles up to
2170 * the player. Which, if it reported user activity, would turn the controls right
2171 * back on. We also don't want to completely block touch events from bubbling up.
2172 * Furthermore a `touchmove` event and anything other than a tap, should not turn
2175 * @listens Component#touchstart
2176 * @listens Component#touchmove
2177 * @listens Component#touchend
2178 * @listens Component#touchcancel
2182 Component.prototype.enableTouchActivity = function enableTouchActivity() {
2183 // Don't continue if the root player doesn't support reporting user activity
2184 if (!this.player() || !this.player().reportUserActivity) {
2188 // listener for reporting that the user is active
2189 var report = Fn.bind(this.player(), this.player().reportUserActivity);
2191 var touchHolding = void 0;
2193 this.on('touchstart', function () {
2195 // For as long as the they are touching the device or have their mouse down,
2196 // we consider them active even if they're not moving their finger or mouse.
2197 // So we want to continue to update that they are active
2198 this.clearInterval(touchHolding);
2199 // report at the same interval as activityCheck
2200 touchHolding = this.setInterval(report, 250);
2203 var touchEnd = function touchEnd(event) {
2205 // stop the interval that maintains activity if the touch is holding
2206 this.clearInterval(touchHolding);
2209 this.on('touchmove', report);
2210 this.on('touchend', touchEnd);
2211 this.on('touchcancel', touchEnd);
2215 * A callback that has no parameters and is bound into `Component`s context.
2217 * @callback Component~GenericCallback
2222 * Creates a function that runs after an `x` millisecond timeout. This function is a
2223 * wrapper around `window.setTimeout`. There are a few reasons to use this one
2225 * 1. It gets cleared via {@link Component#clearTimeout} when
2226 * {@link Component#dispose} gets called.
2227 * 2. The function callback will gets turned into a {@link Component~GenericCallback}
2229 * > Note: You can use `window.clearTimeout` on the id returned by this function. This
2230 * will cause its dispose listener not to get cleaned up! Please use
2231 * {@link Component#clearTimeout} or {@link Component#dispose}.
2233 * @param {Component~GenericCallback} fn
2234 * The function that will be run after `timeout`.
2236 * @param {number} timeout
2237 * Timeout in milliseconds to delay before executing the specified function.
2240 * Returns a timeout ID that gets used to identify the timeout. It can also
2241 * get used in {@link Component#clearTimeout} to clear the timeout that
2244 * @listens Component#dispose
2245 * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout}
2249 Component.prototype.setTimeout = function setTimeout(fn, timeout) {
2250 fn = Fn.bind(this, fn);
2252 var timeoutId = _window2['default'].setTimeout(fn, timeout);
2253 var disposeFn = function disposeFn() {
2254 this.clearTimeout(timeoutId);
2257 disposeFn.guid = 'vjs-timeout-' + timeoutId;
2259 this.on('dispose', disposeFn);
2265 * Clears a timeout that gets created via `window.setTimeout` or
2266 * {@link Component#setTimeout}. If you set a timeout via {@link Component#setTimeout}
2267 * use this function instead of `window.clearTimeout`. If you don't your dispose
2268 * listener will not get cleaned up until {@link Component#dispose}!
2270 * @param {number} timeoutId
2271 * The id of the timeout to clear. The return value of
2272 * {@link Component#setTimeout} or `window.setTimeout`.
2275 * Returns the timeout id that was cleared.
2277 * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearTimeout}
2281 Component.prototype.clearTimeout = function clearTimeout(timeoutId) {
2282 _window2['default'].clearTimeout(timeoutId);
2284 var disposeFn = function disposeFn() {};
2286 disposeFn.guid = 'vjs-timeout-' + timeoutId;
2288 this.off('dispose', disposeFn);
2294 * Creates a function that gets run every `x` milliseconds. This function is a wrapper
2295 * around `window.setInterval`. There are a few reasons to use this one instead though.
2296 * 1. It gets cleared via {@link Component#clearInterval} when
2297 * {@link Component#dispose} gets called.
2298 * 2. The function callback will be a {@link Component~GenericCallback}
2300 * @param {Component~GenericCallback} fn
2301 * The function to run every `x` seconds.
2303 * @param {number} interval
2304 * Execute the specified function every `x` milliseconds.
2307 * Returns an id that can be used to identify the interval. It can also be be used in
2308 * {@link Component#clearInterval} to clear the interval.
2310 * @listens Component#dispose
2311 * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval}
2315 Component.prototype.setInterval = function setInterval(fn, interval) {
2316 fn = Fn.bind(this, fn);
2318 var intervalId = _window2['default'].setInterval(fn, interval);
2320 var disposeFn = function disposeFn() {
2321 this.clearInterval(intervalId);
2324 disposeFn.guid = 'vjs-interval-' + intervalId;
2326 this.on('dispose', disposeFn);
2332 * Clears an interval that gets created via `window.setInterval` or
2333 * {@link Component#setInterval}. If you set an interval via {@link Component#setInterval}
2334 * use this function instead of `window.clearInterval`. If you don't your dispose
2335 * listener will not get cleaned up until {@link Component#dispose}!
2337 * @param {number} intervalId
2338 * The id of the interval to clear. The return value of
2339 * {@link Component#setInterval} or `window.setInterval`.
2342 * Returns the interval id that was cleared.
2344 * @see [Similar to]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/clearInterval}
2348 Component.prototype.clearInterval = function clearInterval(intervalId) {
2349 _window2['default'].clearInterval(intervalId);
2351 var disposeFn = function disposeFn() {};
2353 disposeFn.guid = 'vjs-interval-' + intervalId;
2355 this.off('dispose', disposeFn);
2361 * Register a `Component` with `videojs` given the name and the component.
2363 * > NOTE: {@link Tech}s should not be registered as a `Component`. {@link Tech}s
2364 * should be registered using {@link Tech.registerTech} or
2365 * {@link videojs:videojs.registerTech}.
2367 * > NOTE: This function can also be seen on videojs as
2368 * {@link videojs:videojs.registerComponent}.
2370 * @param {string} name
2371 * The name of the `Component` to register.
2373 * @param {Component} comp
2374 * The `Component` class to register.
2376 * @return {Component}
2377 * The `Component` that was registered.
2381 Component.registerComponent = function registerComponent(name, comp) {
2386 name = (0, _toTitleCase2['default'])(name);
2388 if (!Component.components_) {
2389 Component.components_ = {};
2392 if (name === 'Player' && Component.components_[name]) {
2394 var Player = Component.components_[name];
2396 // If we have players that were disposed, then their name will still be
2397 // in Players.players. So, we must loop through and verify that the value
2398 // for each item is not null. This allows registration of the Player component
2399 // after all players have been disposed or before any were created.
2400 if (Player.players && Object.keys(Player.players).length > 0 && Object.keys(Player.players).map(function (playerName) {
2401 return Player.players[playerName];
2402 }).every(Boolean)) {
2403 throw new Error('Can not register Player component after player has been created');
2408 Component.components_[name] = comp;
2414 * Get a `Component` based on the name it was registered with.
2416 * @param {string} name
2417 * The Name of the component to get.
2419 * @return {Component}
2420 * The `Component` that got registered under the given name.
2422 * @deprecated In `videojs` 6 this will not return `Component`s that were not
2423 * registered using {@link Component.registerComponent}. Currently we
2424 * check the global `videojs` object for a `Component` name and
2425 * return that if it exists.
2429 Component.getComponent = function getComponent(name) {
2434 name = (0, _toTitleCase2['default'])(name);
2436 if (Component.components_ && Component.components_[name]) {
2437 return Component.components_[name];
2440 if (_window2['default'] && _window2['default'].videojs && _window2['default'].videojs[name]) {
2441 _log2['default'].warn('The ' + name + ' component was added to the videojs object when it should be registered using videojs.registerComponent(name, component)');
2443 return _window2['default'].videojs[name];
2448 * Sets up the constructor using the supplied init method or uses the init of the
2451 * @param {Object} [props={}]
2452 * An object of properties.
2455 * the extended object.
2457 * @deprecated since version 5
2461 Component.extend = function extend(props) {
2462 props = props || {};
2464 _log2['default'].warn('Component.extend({}) has been deprecated, ' + ' use videojs.extend(Component, {}) instead');
2466 // Set up the constructor using the supplied init method
2467 // or using the init of the parent object
2468 // Make sure to check the unobfuscated version for external libs
2469 var init = props.init || props.init || this.prototype.init || this.prototype.init || function () {};
2470 // In Resig's simple class inheritance (previously used) the constructor
2471 // is a function that calls `this.init.apply(arguments)`
2472 // However that would prevent us from using `ParentObject.call(this);`
2473 // in a Child constructor because the `this` in `this.init`
2474 // would still refer to the Child and cause an infinite loop.
2475 // We would instead have to do
2476 // `ParentObject.prototype.init.apply(this, arguments);`
2477 // Bleh. We're not creating a _super() function, so it's good to keep
2478 // the parent constructor reference simple.
2479 var subObj = function subObj() {
2480 init.apply(this, arguments);
2483 // Inherit from this object's prototype
2484 subObj.prototype = Object.create(this.prototype);
2485 // Reset the constructor property for subObj otherwise
2486 // instances of subObj would have the constructor of the parent Object
2487 subObj.prototype.constructor = subObj;
2489 // Make the class extendable
2490 subObj.extend = Component.extend;
2492 // Extend subObj's prototype with functions and other properties from props
2493 for (var name in props) {
2494 if (props.hasOwnProperty(name)) {
2495 subObj.prototype[name] = props[name];
2505 Component.registerComponent('Component', Component);
2506 exports['default'] = Component;
2508 },{"81":81,"82":82,"83":83,"85":85,"86":86,"87":87,"91":91,"95":95}],6:[function(_dereq_,module,exports){
2511 exports.__esModule = true;
2513 var _trackButton = _dereq_(36);
2515 var _trackButton2 = _interopRequireDefault(_trackButton);
2517 var _component = _dereq_(5);
2519 var _component2 = _interopRequireDefault(_component);
2521 var _audioTrackMenuItem = _dereq_(7);
2523 var _audioTrackMenuItem2 = _interopRequireDefault(_audioTrackMenuItem);
2525 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2527 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2529 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
2531 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
2532 * @file audio-track-button.js
2537 * The base class for buttons that toggle specific {@link AudioTrack} types.
2539 * @extends TrackButton
2541 var AudioTrackButton = function (_TrackButton) {
2542 _inherits(AudioTrackButton, _TrackButton);
2545 * Creates an instance of this class.
2547 * @param {Player} player
2548 * The `Player` that this class should be attached to.
2550 * @param {Object} [options={}]
2551 * The key/value store of player options.
2553 function AudioTrackButton(player) {
2554 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
2556 _classCallCheck(this, AudioTrackButton);
2558 options.tracks = player.audioTracks && player.audioTracks();
2560 var _this = _possibleConstructorReturn(this, _TrackButton.call(this, player, options));
2562 _this.el_.setAttribute('aria-label', 'Audio Menu');
2567 * Builds the default DOM `className`.
2570 * The DOM `className` for this object.
2574 AudioTrackButton.prototype.buildCSSClass = function buildCSSClass() {
2575 return 'vjs-audio-button ' + _TrackButton.prototype.buildCSSClass.call(this);
2579 * Create a menu item for each audio track
2581 * @param {AudioTrackMenuItem[]} [items=[]]
2582 * An array of existing menu items to use.
2584 * @return {AudioTrackMenuItem[]}
2585 * An array of menu items
2589 AudioTrackButton.prototype.createItems = function createItems() {
2590 var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
2592 var tracks = this.player_.audioTracks && this.player_.audioTracks();
2598 for (var i = 0; i < tracks.length; i++) {
2599 var track = tracks[i];
2601 items.push(new _audioTrackMenuItem2['default'](this.player_, {
2603 // MenuItem is selectable
2611 return AudioTrackButton;
2612 }(_trackButton2['default']);
2615 * The text that should display over the `AudioTrackButton`s controls. Added for localization.
2622 AudioTrackButton.prototype.controlText_ = 'Audio Track';
2623 _component2['default'].registerComponent('AudioTrackButton', AudioTrackButton);
2624 exports['default'] = AudioTrackButton;
2626 },{"36":36,"5":5,"7":7}],7:[function(_dereq_,module,exports){
2629 exports.__esModule = true;
2631 var _menuItem = _dereq_(48);
2633 var _menuItem2 = _interopRequireDefault(_menuItem);
2635 var _component = _dereq_(5);
2637 var _component2 = _interopRequireDefault(_component);
2639 var _fn = _dereq_(83);
2641 var Fn = _interopRequireWildcard(_fn);
2643 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
2645 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2647 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2649 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
2651 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
2652 * @file audio-track-menu-item.js
2657 * An {@link AudioTrack} {@link MenuItem}
2661 var AudioTrackMenuItem = function (_MenuItem) {
2662 _inherits(AudioTrackMenuItem, _MenuItem);
2665 * Creates an instance of this class.
2667 * @param {Player} player
2668 * The `Player` that this class should be attached to.
2670 * @param {Object} [options]
2671 * The key/value store of player options.
2673 function AudioTrackMenuItem(player, options) {
2674 _classCallCheck(this, AudioTrackMenuItem);
2676 var track = options.track;
2677 var tracks = player.audioTracks();
2679 // Modify options for parent MenuItem class's init.
2680 options.label = track.label || track.language || 'Unknown';
2681 options.selected = track.enabled;
2683 var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
2685 _this.track = track;
2689 var changeHandler = Fn.bind(_this, _this.handleTracksChange);
2691 tracks.addEventListener('change', changeHandler);
2692 _this.on('dispose', function () {
2693 tracks.removeEventListener('change', changeHandler);
2701 * This gets called when an `AudioTrackMenuItem is "clicked". See {@link ClickableComponent}
2702 * for more detailed information on what a click can be.
2704 * @param {EventTarget~Event} [event]
2705 * The `keydown`, `tap`, or `click` event that caused this function to be
2713 AudioTrackMenuItem.prototype.handleClick = function handleClick(event) {
2714 var tracks = this.player_.audioTracks();
2716 _MenuItem.prototype.handleClick.call(this, event);
2722 for (var i = 0; i < tracks.length; i++) {
2723 var track = tracks[i];
2725 track.enabled = track === this.track;
2730 * Handle any {@link AudioTrack} change.
2732 * @param {EventTarget~Event} [event]
2733 * The {@link AudioTrackList#change} event that caused this to run.
2735 * @listens AudioTrackList#change
2739 AudioTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
2740 this.selected(this.track.enabled);
2743 return AudioTrackMenuItem;
2744 }(_menuItem2['default']);
2746 _component2['default'].registerComponent('AudioTrackMenuItem', AudioTrackMenuItem);
2747 exports['default'] = AudioTrackMenuItem;
2749 },{"48":48,"5":5,"83":83}],8:[function(_dereq_,module,exports){
2752 exports.__esModule = true;
2754 var _component = _dereq_(5);
2756 var _component2 = _interopRequireDefault(_component);
2794 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2796 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2798 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
2800 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
2801 * @file control-bar.js
2805 // Required children
2809 * Container of main controls.
2811 * @extends Component
2813 var ControlBar = function (_Component) {
2814 _inherits(ControlBar, _Component);
2816 function ControlBar() {
2817 _classCallCheck(this, ControlBar);
2819 return _possibleConstructorReturn(this, _Component.apply(this, arguments));
2823 * Create the `Component`'s DOM element
2826 * The element that was created.
2828 ControlBar.prototype.createEl = function createEl() {
2829 return _Component.prototype.createEl.call(this, 'div', {
2830 className: 'vjs-control-bar',
2833 // The control bar is a group, so it can contain menuitems
2839 }(_component2['default']);
2842 * Default options for `ControlBar`
2849 ControlBar.prototype.options_ = {
2850 children: ['playToggle', 'volumeMenuButton', 'currentTimeDisplay', 'timeDivider', 'durationDisplay', 'progressControl', 'liveDisplay', 'remainingTimeDisplay', 'customControlSpacer', 'playbackRateMenuButton', 'chaptersButton', 'descriptionsButton', 'subtitlesButton', 'captionsButton', 'audioTrackButton', 'fullscreenToggle']
2853 _component2['default'].registerComponent('ControlBar', ControlBar);
2854 exports['default'] = ControlBar;
2856 },{"10":10,"11":11,"12":12,"13":13,"18":18,"21":21,"24":24,"25":25,"27":27,"29":29,"32":32,"33":33,"34":34,"35":35,"38":38,"40":40,"5":5,"6":6,"9":9}],9:[function(_dereq_,module,exports){
2859 exports.__esModule = true;
2861 var _button = _dereq_(2);
2863 var _button2 = _interopRequireDefault(_button);
2865 var _component = _dereq_(5);
2867 var _component2 = _interopRequireDefault(_component);
2869 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2871 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2873 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
2875 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
2876 * @file fullscreen-toggle.js
2881 * Toggle fullscreen video
2885 var FullscreenToggle = function (_Button) {
2886 _inherits(FullscreenToggle, _Button);
2889 * Creates an instance of this class.
2891 * @param {Player} player
2892 * The `Player` that this class should be attached to.
2894 * @param {Object} [options]
2895 * The key/value store of player options.
2897 function FullscreenToggle(player, options) {
2898 _classCallCheck(this, FullscreenToggle);
2900 var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
2902 _this.on(player, 'fullscreenchange', _this.handleFullscreenChange);
2907 * Builds the default DOM `className`.
2910 * The DOM `className` for this object.
2914 FullscreenToggle.prototype.buildCSSClass = function buildCSSClass() {
2915 return 'vjs-fullscreen-control ' + _Button.prototype.buildCSSClass.call(this);
2919 * Handles fullscreenchange on the player and change control text accordingly.
2921 * @param {EventTarget~Event} [event]
2922 * The {@link Player#fullscreenchange} event that caused this function to be
2925 * @listens Player#fullscreenchange
2929 FullscreenToggle.prototype.handleFullscreenChange = function handleFullscreenChange(event) {
2930 if (this.player_.isFullscreen()) {
2931 this.controlText('Non-Fullscreen');
2933 this.controlText('Fullscreen');
2938 * This gets called when an `FullscreenToggle` is "clicked". See
2939 * {@link ClickableComponent} for more detailed information on what a click can be.
2941 * @param {EventTarget~Event} [event]
2942 * The `keydown`, `tap`, or `click` event that caused this function to be
2950 FullscreenToggle.prototype.handleClick = function handleClick(event) {
2951 if (!this.player_.isFullscreen()) {
2952 this.player_.requestFullscreen();
2954 this.player_.exitFullscreen();
2958 return FullscreenToggle;
2959 }(_button2['default']);
2962 * The text that should display over the `FullscreenToggle`s controls. Added for localization.
2969 FullscreenToggle.prototype.controlText_ = 'Fullscreen';
2971 _component2['default'].registerComponent('FullscreenToggle', FullscreenToggle);
2972 exports['default'] = FullscreenToggle;
2974 },{"2":2,"5":5}],10:[function(_dereq_,module,exports){
2977 exports.__esModule = true;
2979 var _component = _dereq_(5);
2981 var _component2 = _interopRequireDefault(_component);
2983 var _dom = _dereq_(81);
2985 var Dom = _interopRequireWildcard(_dom);
2987 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
2989 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
2991 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2993 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
2995 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
2996 * @file live-display.js
3000 // TODO - Future make it click to snap to live
3003 * Displays the live indicator when duration is Infinity.
3005 * @extends Component
3007 var LiveDisplay = function (_Component) {
3008 _inherits(LiveDisplay, _Component);
3011 * Creates an instance of this class.
3013 * @param {Player} player
3014 * The `Player` that this class should be attached to.
3016 * @param {Object} [options]
3017 * The key/value store of player options.
3019 function LiveDisplay(player, options) {
3020 _classCallCheck(this, LiveDisplay);
3022 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
3024 _this.updateShowing();
3025 _this.on(_this.player(), 'durationchange', _this.updateShowing);
3030 * Create the `Component`'s DOM element
3033 * The element that was created.
3037 LiveDisplay.prototype.createEl = function createEl() {
3038 var el = _Component.prototype.createEl.call(this, 'div', {
3039 className: 'vjs-live-control vjs-control'
3042 this.contentEl_ = Dom.createEl('div', {
3043 className: 'vjs-live-display',
3044 innerHTML: '<span class="vjs-control-text">' + this.localize('Stream Type') + '</span>' + this.localize('LIVE')
3049 el.appendChild(this.contentEl_);
3054 * Check the duration to see if the LiveDisplay should be showing or not. Then show/hide
3057 * @param {EventTarget~Event} [event]
3058 * The {@link Player#durationchange} event that caused this function to run.
3060 * @listens Player#durationchange
3064 LiveDisplay.prototype.updateShowing = function updateShowing(event) {
3065 if (this.player().duration() === Infinity) {
3073 }(_component2['default']);
3075 _component2['default'].registerComponent('LiveDisplay', LiveDisplay);
3076 exports['default'] = LiveDisplay;
3078 },{"5":5,"81":81}],11:[function(_dereq_,module,exports){
3081 exports.__esModule = true;
3083 var _button = _dereq_(2);
3085 var _button2 = _interopRequireDefault(_button);
3087 var _component = _dereq_(5);
3089 var _component2 = _interopRequireDefault(_component);
3091 var _dom = _dereq_(81);
3093 var Dom = _interopRequireWildcard(_dom);
3095 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
3097 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3099 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3101 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
3103 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
3104 * @file mute-toggle.js
3109 * A button component for muting the audio.
3113 var MuteToggle = function (_Button) {
3114 _inherits(MuteToggle, _Button);
3117 * Creates an instance of this class.
3119 * @param {Player} player
3120 * The `Player` that this class should be attached to.
3122 * @param {Object} [options]
3123 * The key/value store of player options.
3125 function MuteToggle(player, options) {
3126 _classCallCheck(this, MuteToggle);
3128 var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
3130 _this.on(player, 'volumechange', _this.update);
3132 // hide mute toggle if the current tech doesn't support volume control
3133 if (player.tech_ && player.tech_.featuresVolumeControl === false) {
3134 _this.addClass('vjs-hidden');
3137 _this.on(player, 'loadstart', function () {
3138 // We need to update the button to account for a default muted state.
3141 if (player.tech_.featuresVolumeControl === false) {
3142 this.addClass('vjs-hidden');
3144 this.removeClass('vjs-hidden');
3151 * Builds the default DOM `className`.
3154 * The DOM `className` for this object.
3158 MuteToggle.prototype.buildCSSClass = function buildCSSClass() {
3159 return 'vjs-mute-control ' + _Button.prototype.buildCSSClass.call(this);
3163 * This gets called when an `MuteToggle` is "clicked". See
3164 * {@link ClickableComponent} for more detailed information on what a click can be.
3166 * @param {EventTarget~Event} [event]
3167 * The `keydown`, `tap`, or `click` event that caused this function to be
3175 MuteToggle.prototype.handleClick = function handleClick(event) {
3176 this.player_.muted(this.player_.muted() ? false : true);
3180 * Update the state of volume.
3182 * @param {EventTarget~Event} [event]
3183 * The {@link Player#loadstart} event if this function was called through an
3186 * @listens Player#loadstart
3190 MuteToggle.prototype.update = function update(event) {
3191 var vol = this.player_.volume();
3194 if (vol === 0 || this.player_.muted()) {
3196 } else if (vol < 0.33) {
3198 } else if (vol < 0.67) {
3202 // Don't rewrite the button text if the actual text doesn't change.
3203 // This causes unnecessary and confusing information for screen reader users.
3204 // This check is needed because this function gets called every time the volume level is changed.
3205 var toMute = this.player_.muted() ? 'Unmute' : 'Mute';
3207 if (this.controlText() !== toMute) {
3208 this.controlText(toMute);
3211 // TODO improve muted icon classes
3212 for (var i = 0; i < 4; i++) {
3213 Dom.removeElClass(this.el_, 'vjs-vol-' + i);
3215 Dom.addElClass(this.el_, 'vjs-vol-' + level);
3219 }(_button2['default']);
3222 * The text that should display over the `MuteToggle`s controls. Added for localization.
3229 MuteToggle.prototype.controlText_ = 'Mute';
3231 _component2['default'].registerComponent('MuteToggle', MuteToggle);
3232 exports['default'] = MuteToggle;
3234 },{"2":2,"5":5,"81":81}],12:[function(_dereq_,module,exports){
3237 exports.__esModule = true;
3239 var _button = _dereq_(2);
3241 var _button2 = _interopRequireDefault(_button);
3243 var _component = _dereq_(5);
3245 var _component2 = _interopRequireDefault(_component);
3247 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3249 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3251 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
3253 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
3254 * @file play-toggle.js
3259 * Button to toggle between play and pause.
3263 var PlayToggle = function (_Button) {
3264 _inherits(PlayToggle, _Button);
3267 * Creates an instance of this class.
3269 * @param {Player} player
3270 * The `Player` that this class should be attached to.
3272 * @param {Object} [options]
3273 * The key/value store of player options.
3275 function PlayToggle(player, options) {
3276 _classCallCheck(this, PlayToggle);
3278 var _this = _possibleConstructorReturn(this, _Button.call(this, player, options));
3280 _this.on(player, 'play', _this.handlePlay);
3281 _this.on(player, 'pause', _this.handlePause);
3286 * Builds the default DOM `className`.
3289 * The DOM `className` for this object.
3293 PlayToggle.prototype.buildCSSClass = function buildCSSClass() {
3294 return 'vjs-play-control ' + _Button.prototype.buildCSSClass.call(this);
3298 * This gets called when an `PlayToggle` is "clicked". See
3299 * {@link ClickableComponent} for more detailed information on what a click can be.
3301 * @param {EventTarget~Event} [event]
3302 * The `keydown`, `tap`, or `click` event that caused this function to be
3310 PlayToggle.prototype.handleClick = function handleClick(event) {
3311 if (this.player_.paused()) {
3312 this.player_.play();
3314 this.player_.pause();
3319 * Add the vjs-playing class to the element so it can change appearance.
3321 * @param {EventTarget~Event} [event]
3322 * The event that caused this function to run.
3324 * @listens Player#play
3328 PlayToggle.prototype.handlePlay = function handlePlay(event) {
3329 this.removeClass('vjs-paused');
3330 this.addClass('vjs-playing');
3331 // change the button text to "Pause"
3332 this.controlText('Pause');
3336 * Add the vjs-paused class to the element so it can change appearance.
3338 * @param {EventTarget~Event} [event]
3339 * The event that caused this function to run.
3341 * @listens Player#pause
3345 PlayToggle.prototype.handlePause = function handlePause(event) {
3346 this.removeClass('vjs-playing');
3347 this.addClass('vjs-paused');
3348 // change the button text to "Play"
3349 this.controlText('Play');
3353 }(_button2['default']);
3356 * The text that should display over the `PlayToggle`s controls. Added for localization.
3363 PlayToggle.prototype.controlText_ = 'Play';
3365 _component2['default'].registerComponent('PlayToggle', PlayToggle);
3366 exports['default'] = PlayToggle;
3368 },{"2":2,"5":5}],13:[function(_dereq_,module,exports){
3371 exports.__esModule = true;
3373 var _menuButton = _dereq_(47);
3375 var _menuButton2 = _interopRequireDefault(_menuButton);
3377 var _menu = _dereq_(49);
3379 var _menu2 = _interopRequireDefault(_menu);
3381 var _playbackRateMenuItem = _dereq_(14);
3383 var _playbackRateMenuItem2 = _interopRequireDefault(_playbackRateMenuItem);
3385 var _component = _dereq_(5);
3387 var _component2 = _interopRequireDefault(_component);
3389 var _dom = _dereq_(81);
3391 var Dom = _interopRequireWildcard(_dom);
3393 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
3395 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3397 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3399 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
3401 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
3402 * @file playback-rate-menu-button.js
3407 * The component for controlling the playback rate.
3409 * @extends MenuButton
3411 var PlaybackRateMenuButton = function (_MenuButton) {
3412 _inherits(PlaybackRateMenuButton, _MenuButton);
3415 * Creates an instance of this class.
3417 * @param {Player} player
3418 * The `Player` that this class should be attached to.
3420 * @param {Object} [options]
3421 * The key/value store of player options.
3423 function PlaybackRateMenuButton(player, options) {
3424 _classCallCheck(this, PlaybackRateMenuButton);
3426 var _this = _possibleConstructorReturn(this, _MenuButton.call(this, player, options));
3428 _this.updateVisibility();
3429 _this.updateLabel();
3431 _this.on(player, 'loadstart', _this.updateVisibility);
3432 _this.on(player, 'ratechange', _this.updateLabel);
3437 * Create the `Component`'s DOM element
3440 * The element that was created.
3444 PlaybackRateMenuButton.prototype.createEl = function createEl() {
3445 var el = _MenuButton.prototype.createEl.call(this);
3447 this.labelEl_ = Dom.createEl('div', {
3448 className: 'vjs-playback-rate-value',
3452 el.appendChild(this.labelEl_);
3458 * Builds the default DOM `className`.
3461 * The DOM `className` for this object.
3465 PlaybackRateMenuButton.prototype.buildCSSClass = function buildCSSClass() {
3466 return 'vjs-playback-rate ' + _MenuButton.prototype.buildCSSClass.call(this);
3470 * Create the playback rate menu
3473 * Menu object populated with {@link PlaybackRateMenuItem}s
3477 PlaybackRateMenuButton.prototype.createMenu = function createMenu() {
3478 var menu = new _menu2['default'](this.player());
3479 var rates = this.playbackRates();
3482 for (var i = rates.length - 1; i >= 0; i--) {
3483 menu.addChild(new _playbackRateMenuItem2['default'](this.player(), { rate: rates[i] + 'x' }));
3491 * Updates ARIA accessibility attributes
3495 PlaybackRateMenuButton.prototype.updateARIAAttributes = function updateARIAAttributes() {
3496 // Current playback rate
3497 this.el().setAttribute('aria-valuenow', this.player().playbackRate());
3501 * This gets called when an `PlaybackRateMenuButton` is "clicked". See
3502 * {@link ClickableComponent} for more detailed information on what a click can be.
3504 * @param {EventTarget~Event} [event]
3505 * The `keydown`, `tap`, or `click` event that caused this function to be
3513 PlaybackRateMenuButton.prototype.handleClick = function handleClick(event) {
3514 // select next rate option
3515 var currentRate = this.player().playbackRate();
3516 var rates = this.playbackRates();
3518 // this will select first one if the last one currently selected
3519 var newRate = rates[0];
3521 for (var i = 0; i < rates.length; i++) {
3522 if (rates[i] > currentRate) {
3527 this.player().playbackRate(newRate);
3531 * Get possible playback rates
3534 * All possible playback rates
3538 PlaybackRateMenuButton.prototype.playbackRates = function playbackRates() {
3539 return this.options_.playbackRates || this.options_.playerOptions && this.options_.playerOptions.playbackRates;
3543 * Get whether playback rates is supported by the tech
3544 * and an array of playback rates exists
3547 * Whether changing playback rate is supported
3551 PlaybackRateMenuButton.prototype.playbackRateSupported = function playbackRateSupported() {
3552 return this.player().tech_ && this.player().tech_.featuresPlaybackRate && this.playbackRates() && this.playbackRates().length > 0;
3556 * Hide playback rate controls when they're no playback rate options to select
3558 * @param {EventTarget~Event} [event]
3559 * The event that caused this function to run.
3561 * @listens Player#loadstart
3565 PlaybackRateMenuButton.prototype.updateVisibility = function updateVisibility(event) {
3566 if (this.playbackRateSupported()) {
3567 this.removeClass('vjs-hidden');
3569 this.addClass('vjs-hidden');
3574 * Update button label when rate changed
3576 * @param {EventTarget~Event} [event]
3577 * The event that caused this function to run.
3579 * @listens Player#ratechange
3583 PlaybackRateMenuButton.prototype.updateLabel = function updateLabel(event) {
3584 if (this.playbackRateSupported()) {
3585 this.labelEl_.innerHTML = this.player().playbackRate() + 'x';
3589 return PlaybackRateMenuButton;
3590 }(_menuButton2['default']);
3593 * The text that should display over the `FullscreenToggle`s controls. Added for localization.
3600 PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate';
3602 _component2['default'].registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton);
3603 exports['default'] = PlaybackRateMenuButton;
3605 },{"14":14,"47":47,"49":49,"5":5,"81":81}],14:[function(_dereq_,module,exports){
3608 exports.__esModule = true;
3610 var _menuItem = _dereq_(48);
3612 var _menuItem2 = _interopRequireDefault(_menuItem);
3614 var _component = _dereq_(5);
3616 var _component2 = _interopRequireDefault(_component);
3618 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3620 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3622 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
3624 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
3625 * @file playback-rate-menu-item.js
3630 * The specific menu item type for selecting a playback rate.
3634 var PlaybackRateMenuItem = function (_MenuItem) {
3635 _inherits(PlaybackRateMenuItem, _MenuItem);
3638 * Creates an instance of this class.
3640 * @param {Player} player
3641 * The `Player` that this class should be attached to.
3643 * @param {Object} [options]
3644 * The key/value store of player options.
3646 function PlaybackRateMenuItem(player, options) {
3647 _classCallCheck(this, PlaybackRateMenuItem);
3649 var label = options.rate;
3650 var rate = parseFloat(label, 10);
3652 // Modify options for parent MenuItem class's init.
3653 options.label = label;
3654 options.selected = rate === 1;
3656 var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
3658 _this.label = label;
3661 _this.on(player, 'ratechange', _this.update);
3666 * This gets called when an `PlaybackRateMenuItem` is "clicked". See
3667 * {@link ClickableComponent} for more detailed information on what a click can be.
3669 * @param {EventTarget~Event} [event]
3670 * The `keydown`, `tap`, or `click` event that caused this function to be
3678 PlaybackRateMenuItem.prototype.handleClick = function handleClick(event) {
3679 _MenuItem.prototype.handleClick.call(this);
3680 this.player().playbackRate(this.rate);
3684 * Update the PlaybackRateMenuItem when the playbackrate changes.
3686 * @param {EventTarget~Event} [event]
3687 * The `ratechange` event that caused this function to run.
3689 * @listens Player#ratechange
3693 PlaybackRateMenuItem.prototype.update = function update(event) {
3694 this.selected(this.player().playbackRate() === this.rate);
3697 return PlaybackRateMenuItem;
3698 }(_menuItem2['default']);
3701 * The text that should display over the `PlaybackRateMenuItem`s controls. Added for localization.
3708 PlaybackRateMenuItem.prototype.contentElType = 'button';
3710 _component2['default'].registerComponent('PlaybackRateMenuItem', PlaybackRateMenuItem);
3711 exports['default'] = PlaybackRateMenuItem;
3713 },{"48":48,"5":5}],15:[function(_dereq_,module,exports){
3716 exports.__esModule = true;
3718 var _component = _dereq_(5);
3720 var _component2 = _interopRequireDefault(_component);
3722 var _dom = _dereq_(81);
3724 var Dom = _interopRequireWildcard(_dom);
3726 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
3728 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3730 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3732 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
3734 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
3735 * @file load-progress-bar.js
3740 * Shows loading progress
3742 * @extends Component
3744 var LoadProgressBar = function (_Component) {
3745 _inherits(LoadProgressBar, _Component);
3748 * Creates an instance of this class.
3750 * @param {Player} player
3751 * The `Player` that this class should be attached to.
3753 * @param {Object} [options]
3754 * The key/value store of player options.
3756 function LoadProgressBar(player, options) {
3757 _classCallCheck(this, LoadProgressBar);
3759 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
3761 _this.partEls_ = [];
3762 _this.on(player, 'progress', _this.update);
3767 * Create the `Component`'s DOM element
3770 * The element that was created.
3774 LoadProgressBar.prototype.createEl = function createEl() {
3775 return _Component.prototype.createEl.call(this, 'div', {
3776 className: 'vjs-load-progress',
3777 innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Loaded') + '</span>: 0%</span>'
3782 * Update progress bar
3784 * @param {EventTarget~Event} [event]
3785 * The `progress` event that caused this function to run.
3787 * @listens Player#progress
3791 LoadProgressBar.prototype.update = function update(event) {
3792 var buffered = this.player_.buffered();
3793 var duration = this.player_.duration();
3794 var bufferedEnd = this.player_.bufferedEnd();
3795 var children = this.partEls_;
3797 // get the percent width of a time compared to the total end
3798 var percentify = function percentify(time, end) {
3800 var percent = time / end || 0;
3802 return (percent >= 1 ? 1 : percent) * 100 + '%';
3805 // update the width of the progress bar
3806 this.el_.style.width = percentify(bufferedEnd, duration);
3808 // add child elements to represent the individual buffered time ranges
3809 for (var i = 0; i < buffered.length; i++) {
3810 var start = buffered.start(i);
3811 var end = buffered.end(i);
3812 var part = children[i];
3815 part = this.el_.appendChild(Dom.createEl());
3819 // set the percent based on the width of the progress bar (bufferedEnd)
3820 part.style.left = percentify(start, bufferedEnd);
3821 part.style.width = percentify(end - start, bufferedEnd);
3824 // remove unused buffered range elements
3825 for (var _i = children.length; _i > buffered.length; _i--) {
3826 this.el_.removeChild(children[_i - 1]);
3828 children.length = buffered.length;
3831 return LoadProgressBar;
3832 }(_component2['default']);
3834 _component2['default'].registerComponent('LoadProgressBar', LoadProgressBar);
3835 exports['default'] = LoadProgressBar;
3837 },{"5":5,"81":81}],16:[function(_dereq_,module,exports){
3840 exports.__esModule = true;
3842 var _component = _dereq_(5);
3844 var _component2 = _interopRequireDefault(_component);
3846 var _dom = _dereq_(81);
3848 var Dom = _interopRequireWildcard(_dom);
3850 var _fn = _dereq_(83);
3852 var Fn = _interopRequireWildcard(_fn);
3854 var _formatTime = _dereq_(84);
3856 var _formatTime2 = _interopRequireDefault(_formatTime);
3858 var _computedStyle = _dereq_(80);
3860 var _computedStyle2 = _interopRequireDefault(_computedStyle);
3862 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
3864 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
3866 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
3868 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
3870 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
3871 * @file mouse-time-display.js
3876 * The Mouse Time Display component shows the time you will seek to
3877 * when hovering over the progress bar
3879 * @extends Component
3881 var MouseTimeDisplay = function (_Component) {
3882 _inherits(MouseTimeDisplay, _Component);
3885 * Creates an instance of this class.
3887 * @param {Player} player
3888 * The `Player` that this class should be attached to.
3890 * @param {Object} [options]
3891 * The key/value store of player options.
3893 function MouseTimeDisplay(player, options) {
3894 _classCallCheck(this, MouseTimeDisplay);
3896 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
3898 if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) {
3899 _this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside;
3902 if (_this.keepTooltipsInside) {
3903 _this.tooltip = Dom.createEl('div', { className: 'vjs-time-tooltip' });
3904 _this.el().appendChild(_this.tooltip);
3905 _this.addClass('vjs-keep-tooltips-inside');
3910 player.on('ready', function () {
3911 _this.on(player.controlBar.progressControl.el(), 'mousemove', Fn.throttle(Fn.bind(_this, _this.handleMouseMove), 25));
3917 * Create the `Component`'s DOM element
3920 * The element that was created.
3924 MouseTimeDisplay.prototype.createEl = function createEl() {
3925 return _Component.prototype.createEl.call(this, 'div', {
3926 className: 'vjs-mouse-display'
3931 * Handle the mouse move event on the `MouseTimeDisplay`.
3933 * @param {EventTarget~Event} event
3934 * The `mousemove` event that caused this to event to run.
3940 MouseTimeDisplay.prototype.handleMouseMove = function handleMouseMove(event) {
3941 var duration = this.player_.duration();
3942 var newTime = this.calculateDistance(event) * duration;
3943 var position = event.pageX - Dom.findElPosition(this.el().parentNode).left;
3945 this.update(newTime, position);
3949 * Update the time and position of the `MouseTimeDisplay`.
3951 * @param {number} newTime
3952 * Time to change the `MouseTimeDisplay` to.
3954 * @param {number} position
3955 * Position from the left of the in pixels.
3959 MouseTimeDisplay.prototype.update = function update(newTime, position) {
3960 var time = (0, _formatTime2['default'])(newTime, this.player_.duration());
3962 this.el().style.left = position + 'px';
3963 this.el().setAttribute('data-current-time', time);
3965 if (this.keepTooltipsInside) {
3966 var clampedPosition = this.clampPosition_(position);
3967 var difference = position - clampedPosition + 1;
3968 var tooltipWidth = parseFloat((0, _computedStyle2['default'])(this.tooltip, 'width'));
3969 var tooltipWidthHalf = tooltipWidth / 2;
3971 this.tooltip.innerHTML = time;
3972 this.tooltip.style.right = '-' + (tooltipWidthHalf - difference) + 'px';
3977 * Get the mouse pointers x coordinate in pixels.
3979 * @param {EventTarget~Event} [event]
3980 * The `mousemove` event that was passed to this function by
3981 * {@link MouseTimeDisplay#handleMouseMove}
3984 * THe x position in pixels of the mouse pointer.
3988 MouseTimeDisplay.prototype.calculateDistance = function calculateDistance(event) {
3989 return Dom.getPointerPosition(this.el().parentNode, event).x;
3993 * This takes in a horizontal position for the bar and returns a clamped position.
3994 * Clamped position means that it will keep the position greater than half the width
3995 * of the tooltip and smaller than the player width minus half the width o the tooltip.
3996 * It will only clamp the position if `keepTooltipsInside` option is set.
3998 * @param {number} position
3999 * The position the bar wants to be
4002 * The (potentially) new clamped position.
4008 MouseTimeDisplay.prototype.clampPosition_ = function clampPosition_(position) {
4009 if (!this.keepTooltipsInside) {
4013 var playerWidth = parseFloat((0, _computedStyle2['default'])(this.player().el(), 'width'));
4014 var tooltipWidth = parseFloat((0, _computedStyle2['default'])(this.tooltip, 'width'));
4015 var tooltipWidthHalf = tooltipWidth / 2;
4016 var actualPosition = position;
4018 if (position < tooltipWidthHalf) {
4019 actualPosition = Math.ceil(tooltipWidthHalf);
4020 } else if (position > playerWidth - tooltipWidthHalf) {
4021 actualPosition = Math.floor(playerWidth - tooltipWidthHalf);
4024 return actualPosition;
4027 return MouseTimeDisplay;
4028 }(_component2['default']);
4030 _component2['default'].registerComponent('MouseTimeDisplay', MouseTimeDisplay);
4031 exports['default'] = MouseTimeDisplay;
4033 },{"5":5,"80":80,"81":81,"83":83,"84":84}],17:[function(_dereq_,module,exports){
4036 exports.__esModule = true;
4038 var _component = _dereq_(5);
4040 var _component2 = _interopRequireDefault(_component);
4042 var _fn = _dereq_(83);
4044 var Fn = _interopRequireWildcard(_fn);
4046 var _formatTime = _dereq_(84);
4048 var _formatTime2 = _interopRequireDefault(_formatTime);
4050 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
4052 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4054 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4056 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4058 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4059 * @file play-progress-bar.js
4064 * Shows play progress
4066 * @extends Component
4068 var PlayProgressBar = function (_Component) {
4069 _inherits(PlayProgressBar, _Component);
4072 * Creates an instance of this class.
4074 * @param {Player} player
4075 * The `Player` that this class should be attached to.
4077 * @param {Object} [options]
4078 * The key/value store of player options.
4080 function PlayProgressBar(player, options) {
4081 _classCallCheck(this, PlayProgressBar);
4083 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
4085 _this.updateDataAttr();
4086 _this.on(player, 'timeupdate', _this.updateDataAttr);
4087 player.ready(Fn.bind(_this, _this.updateDataAttr));
4089 if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) {
4090 _this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside;
4093 if (_this.keepTooltipsInside) {
4094 _this.addClass('vjs-keep-tooltips-inside');
4100 * Create the `Component`'s DOM element
4103 * The element that was created.
4107 PlayProgressBar.prototype.createEl = function createEl() {
4108 return _Component.prototype.createEl.call(this, 'div', {
4109 className: 'vjs-play-progress vjs-slider-bar',
4110 innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>'
4115 * Update the data-current-time attribute on the `PlayProgressBar`.
4117 * @param {EventTarget~Event} [event]
4118 * The `timeupdate` event that caused this to run.
4120 * @listens Player#timeupdate
4124 PlayProgressBar.prototype.updateDataAttr = function updateDataAttr(event) {
4125 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
4127 this.el_.setAttribute('data-current-time', (0, _formatTime2['default'])(time, this.player_.duration()));
4130 return PlayProgressBar;
4131 }(_component2['default']);
4133 _component2['default'].registerComponent('PlayProgressBar', PlayProgressBar);
4134 exports['default'] = PlayProgressBar;
4136 },{"5":5,"83":83,"84":84}],18:[function(_dereq_,module,exports){
4139 exports.__esModule = true;
4141 var _component = _dereq_(5);
4143 var _component2 = _interopRequireDefault(_component);
4149 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4151 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4153 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4155 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4156 * @file progress-control.js
4161 * The Progress Control component contains the seek bar, load progress,
4162 * and play progress.
4164 * @extends Component
4166 var ProgressControl = function (_Component) {
4167 _inherits(ProgressControl, _Component);
4169 function ProgressControl() {
4170 _classCallCheck(this, ProgressControl);
4172 return _possibleConstructorReturn(this, _Component.apply(this, arguments));
4176 * Create the `Component`'s DOM element
4179 * The element that was created.
4181 ProgressControl.prototype.createEl = function createEl() {
4182 return _Component.prototype.createEl.call(this, 'div', {
4183 className: 'vjs-progress-control vjs-control'
4187 return ProgressControl;
4188 }(_component2['default']);
4191 * Default options for `ProgressControl`
4198 ProgressControl.prototype.options_ = {
4199 children: ['seekBar']
4202 _component2['default'].registerComponent('ProgressControl', ProgressControl);
4203 exports['default'] = ProgressControl;
4205 },{"16":16,"19":19,"5":5}],19:[function(_dereq_,module,exports){
4208 exports.__esModule = true;
4210 var _slider = _dereq_(57);
4212 var _slider2 = _interopRequireDefault(_slider);
4214 var _component = _dereq_(5);
4216 var _component2 = _interopRequireDefault(_component);
4218 var _fn = _dereq_(83);
4220 var Fn = _interopRequireWildcard(_fn);
4222 var _formatTime = _dereq_(84);
4224 var _formatTime2 = _interopRequireDefault(_formatTime);
4226 var _computedStyle = _dereq_(80);
4228 var _computedStyle2 = _interopRequireDefault(_computedStyle);
4236 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
4238 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4240 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4242 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4244 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4250 * Seek Bar and holder for the progress bars
4254 var SeekBar = function (_Slider) {
4255 _inherits(SeekBar, _Slider);
4258 * Creates an instance of this class.
4260 * @param {Player} player
4261 * The `Player` that this class should be attached to.
4263 * @param {Object} [options]
4264 * The key/value store of player options.
4266 function SeekBar(player, options) {
4267 _classCallCheck(this, SeekBar);
4269 var _this = _possibleConstructorReturn(this, _Slider.call(this, player, options));
4271 _this.on(player, 'timeupdate', _this.updateProgress);
4272 _this.on(player, 'ended', _this.updateProgress);
4273 player.ready(Fn.bind(_this, _this.updateProgress));
4275 if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) {
4276 _this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside;
4279 if (_this.keepTooltipsInside) {
4280 _this.tooltipProgressBar = _this.addChild('TooltipProgressBar');
4286 * Create the `Component`'s DOM element
4289 * The element that was created.
4293 SeekBar.prototype.createEl = function createEl() {
4294 return _Slider.prototype.createEl.call(this, 'div', {
4295 className: 'vjs-progress-holder'
4297 'aria-label': 'progress bar'
4302 * Update the seek bars tooltip and width.
4304 * @param {EventTarget~Event} [event]
4305 * The `timeupdate` or `ended` event that caused this to run.
4307 * @listens Player#timeupdate
4308 * @listens Player#ended
4312 SeekBar.prototype.updateProgress = function updateProgress(event) {
4313 this.updateAriaAttributes(this.el_);
4315 if (this.keepTooltipsInside) {
4316 this.updateAriaAttributes(this.tooltipProgressBar.el_);
4317 this.tooltipProgressBar.el_.style.width = this.bar.el_.style.width;
4319 var playerWidth = parseFloat((0, _computedStyle2['default'])(this.player().el(), 'width'));
4320 var tooltipWidth = parseFloat((0, _computedStyle2['default'])(this.tooltipProgressBar.tooltip, 'width'));
4321 var tooltipStyle = this.tooltipProgressBar.el().style;
4323 tooltipStyle.maxWidth = Math.floor(playerWidth - tooltipWidth / 2) + 'px';
4324 tooltipStyle.minWidth = Math.ceil(tooltipWidth / 2) + 'px';
4325 tooltipStyle.right = '-' + tooltipWidth / 2 + 'px';
4330 * Update ARIA accessibility attributes
4332 * @param {Element} el
4333 * The element to update with aria accessibility attributes.
4337 SeekBar.prototype.updateAriaAttributes = function updateAriaAttributes(el) {
4338 // Allows for smooth scrubbing, when player can't keep up.
4339 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
4341 // machine readable value of progress bar (percentage complete)
4342 el.setAttribute('aria-valuenow', (this.getPercent() * 100).toFixed(2));
4343 // human readable value of progress bar (time complete)
4344 el.setAttribute('aria-valuetext', (0, _formatTime2['default'])(time, this.player_.duration()));
4348 * Get percentage of video played
4351 * The percentage played
4355 SeekBar.prototype.getPercent = function getPercent() {
4356 var percent = this.player_.currentTime() / this.player_.duration();
4358 return percent >= 1 ? 1 : percent;
4362 * Handle mouse down on seek bar
4364 * @param {EventTarget~Event} event
4365 * The `mousedown` event that caused this to run.
4367 * @listens mousedown
4371 SeekBar.prototype.handleMouseDown = function handleMouseDown(event) {
4372 _Slider.prototype.handleMouseDown.call(this, event);
4374 this.player_.scrubbing(true);
4376 this.videoWasPlaying = !this.player_.paused();
4378 this.pauseTimer_ = this.setTimeout(function () {
4379 this.player_.pause();
4384 * Handle mouse move on seek bar
4386 * @param {EventTarget~Event} event
4387 * The `mousemove` event that caused this to run.
4389 * @listens mousemove
4393 SeekBar.prototype.handleMouseMove = function handleMouseMove(event) {
4394 var newTime = this.calculateDistance(event) * this.player_.duration();
4396 // Don't let video end while scrubbing.
4397 if (newTime === this.player_.duration()) {
4398 newTime = newTime - 0.1;
4401 // Set new time (tell player to seek to new time)
4402 this.player_.currentTime(newTime);
4404 if (event.type === 'mousemove') {
4405 this.clearTimeout(this.pauseTimer_);
4406 this.player_.pause();
4411 * Handle mouse up on seek bar
4413 * @param {EventTarget~Event} event
4414 * The `mouseup` event that caused this to run.
4420 SeekBar.prototype.handleMouseUp = function handleMouseUp(event) {
4421 _Slider.prototype.handleMouseUp.call(this, event);
4423 this.clearTimeout(this.pauseTimer_);
4425 this.player_.scrubbing(false);
4426 if (this.videoWasPlaying) {
4427 this.player_.play();
4432 * Move more quickly fast forward for keyboard-only users
4436 SeekBar.prototype.stepForward = function stepForward() {
4437 // more quickly fast forward for keyboard-only users
4438 this.player_.currentTime(this.player_.currentTime() + 5);
4442 * Move more quickly rewind for keyboard-only users
4446 SeekBar.prototype.stepBack = function stepBack() {
4447 // more quickly rewind for keyboard-only users
4448 this.player_.currentTime(this.player_.currentTime() - 5);
4452 }(_slider2['default']);
4455 * Default options for the `SeekBar`
4462 SeekBar.prototype.options_ = {
4463 children: ['loadProgressBar', 'mouseTimeDisplay', 'playProgressBar'],
4464 barName: 'playProgressBar'
4468 * Call the update event for this Slider when this event happens on the player.
4472 SeekBar.prototype.playerEvent = 'timeupdate';
4474 _component2['default'].registerComponent('SeekBar', SeekBar);
4475 exports['default'] = SeekBar;
4477 },{"15":15,"17":17,"20":20,"5":5,"57":57,"80":80,"83":83,"84":84}],20:[function(_dereq_,module,exports){
4480 exports.__esModule = true;
4482 var _component = _dereq_(5);
4484 var _component2 = _interopRequireDefault(_component);
4486 var _fn = _dereq_(83);
4488 var Fn = _interopRequireWildcard(_fn);
4490 var _formatTime = _dereq_(84);
4492 var _formatTime2 = _interopRequireDefault(_formatTime);
4494 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
4496 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4498 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4500 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4502 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4503 * @file play-progress-bar.js
4508 * Shows play progress
4510 * @extends Component
4512 var TooltipProgressBar = function (_Component) {
4513 _inherits(TooltipProgressBar, _Component);
4516 * Creates an instance of this class.
4518 * @param {Player} player
4519 * The `Player` that this class should be attached to.
4521 * @param {Object} [options]
4522 * The key/value store of player options.
4524 function TooltipProgressBar(player, options) {
4525 _classCallCheck(this, TooltipProgressBar);
4527 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
4529 _this.updateDataAttr();
4530 _this.on(player, 'timeupdate', _this.updateDataAttr);
4531 player.ready(Fn.bind(_this, _this.updateDataAttr));
4536 * Create the `Component`'s DOM element
4539 * The element that was created.
4543 TooltipProgressBar.prototype.createEl = function createEl() {
4544 var el = _Component.prototype.createEl.call(this, 'div', {
4545 className: 'vjs-tooltip-progress-bar vjs-slider-bar',
4546 innerHTML: '<div class="vjs-time-tooltip"></div>\n <span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>'
4549 this.tooltip = el.querySelector('.vjs-time-tooltip');
4555 * Updatet the data-current-time attribute for TooltipProgressBar
4557 * @param {EventTarget~Event} [event]
4558 * The `timeupdate` event that caused this function to run.
4560 * @listens Player#timeupdate
4564 TooltipProgressBar.prototype.updateDataAttr = function updateDataAttr(event) {
4565 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
4566 var formattedTime = (0, _formatTime2['default'])(time, this.player_.duration());
4568 this.el_.setAttribute('data-current-time', formattedTime);
4569 this.tooltip.innerHTML = formattedTime;
4572 return TooltipProgressBar;
4573 }(_component2['default']);
4575 _component2['default'].registerComponent('TooltipProgressBar', TooltipProgressBar);
4576 exports['default'] = TooltipProgressBar;
4578 },{"5":5,"83":83,"84":84}],21:[function(_dereq_,module,exports){
4581 exports.__esModule = true;
4583 var _spacer = _dereq_(22);
4585 var _spacer2 = _interopRequireDefault(_spacer);
4587 var _component = _dereq_(5);
4589 var _component2 = _interopRequireDefault(_component);
4591 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4593 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4595 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4597 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4598 * @file custom-control-spacer.js
4603 * Spacer specifically meant to be used as an insertion point for new plugins, etc.
4607 var CustomControlSpacer = function (_Spacer) {
4608 _inherits(CustomControlSpacer, _Spacer);
4610 function CustomControlSpacer() {
4611 _classCallCheck(this, CustomControlSpacer);
4613 return _possibleConstructorReturn(this, _Spacer.apply(this, arguments));
4617 * Builds the default DOM `className`.
4620 * The DOM `className` for this object.
4622 CustomControlSpacer.prototype.buildCSSClass = function buildCSSClass() {
4623 return 'vjs-custom-control-spacer ' + _Spacer.prototype.buildCSSClass.call(this);
4627 * Create the `Component`'s DOM element
4630 * The element that was created.
4634 CustomControlSpacer.prototype.createEl = function createEl() {
4635 var el = _Spacer.prototype.createEl.call(this, {
4636 className: this.buildCSSClass()
4639 // No-flex/table-cell mode requires there be some content
4640 // in the cell to fill the remaining space of the table.
4641 el.innerHTML = ' ';
4645 return CustomControlSpacer;
4646 }(_spacer2['default']);
4648 _component2['default'].registerComponent('CustomControlSpacer', CustomControlSpacer);
4649 exports['default'] = CustomControlSpacer;
4651 },{"22":22,"5":5}],22:[function(_dereq_,module,exports){
4654 exports.__esModule = true;
4656 var _component = _dereq_(5);
4658 var _component2 = _interopRequireDefault(_component);
4660 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4662 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4664 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4666 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4672 * Just an empty spacer element that can be used as an append point for plugins, etc.
4673 * Also can be used to create space between elements when necessary.
4675 * @extends Component
4677 var Spacer = function (_Component) {
4678 _inherits(Spacer, _Component);
4681 _classCallCheck(this, Spacer);
4683 return _possibleConstructorReturn(this, _Component.apply(this, arguments));
4687 * Builds the default DOM `className`.
4690 * The DOM `className` for this object.
4692 Spacer.prototype.buildCSSClass = function buildCSSClass() {
4693 return 'vjs-spacer ' + _Component.prototype.buildCSSClass.call(this);
4697 * Create the `Component`'s DOM element
4700 * The element that was created.
4704 Spacer.prototype.createEl = function createEl() {
4705 return _Component.prototype.createEl.call(this, 'div', {
4706 className: this.buildCSSClass()
4711 }(_component2['default']);
4713 _component2['default'].registerComponent('Spacer', Spacer);
4715 exports['default'] = Spacer;
4717 },{"5":5}],23:[function(_dereq_,module,exports){
4720 exports.__esModule = true;
4722 var _textTrackMenuItem = _dereq_(31);
4724 var _textTrackMenuItem2 = _interopRequireDefault(_textTrackMenuItem);
4726 var _component = _dereq_(5);
4728 var _component2 = _interopRequireDefault(_component);
4730 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4732 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4734 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4736 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4737 * @file caption-settings-menu-item.js
4742 * The menu item for caption track settings menu
4744 * @extends TextTrackMenuItem
4746 var CaptionSettingsMenuItem = function (_TextTrackMenuItem) {
4747 _inherits(CaptionSettingsMenuItem, _TextTrackMenuItem);
4750 * Creates an instance of this class.
4752 * @param {Player} player
4753 * The `Player` that this class should be attached to.
4755 * @param {Object} [options]
4756 * The key/value store of player options.
4758 function CaptionSettingsMenuItem(player, options) {
4759 _classCallCheck(this, CaptionSettingsMenuItem);
4764 label: options.kind + ' settings',
4770 // CaptionSettingsMenuItem has no concept of 'selected'
4771 options.selectable = false;
4773 var _this = _possibleConstructorReturn(this, _TextTrackMenuItem.call(this, player, options));
4775 _this.addClass('vjs-texttrack-settings');
4776 _this.controlText(', opens ' + options.kind + ' settings dialog');
4781 * This gets called when an `CaptionSettingsMenuItem` is "clicked". See
4782 * {@link ClickableComponent} for more detailed information on what a click can be.
4784 * @param {EventTarget~Event} [event]
4785 * The `keydown`, `tap`, or `click` event that caused this function to be
4793 CaptionSettingsMenuItem.prototype.handleClick = function handleClick(event) {
4794 this.player().getChild('textTrackSettings').show();
4795 this.player().getChild('textTrackSettings').el_.focus();
4798 return CaptionSettingsMenuItem;
4799 }(_textTrackMenuItem2['default']);
4801 _component2['default'].registerComponent('CaptionSettingsMenuItem', CaptionSettingsMenuItem);
4802 exports['default'] = CaptionSettingsMenuItem;
4804 },{"31":31,"5":5}],24:[function(_dereq_,module,exports){
4807 exports.__esModule = true;
4809 var _textTrackButton = _dereq_(30);
4811 var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
4813 var _component = _dereq_(5);
4815 var _component2 = _interopRequireDefault(_component);
4817 var _captionSettingsMenuItem = _dereq_(23);
4819 var _captionSettingsMenuItem2 = _interopRequireDefault(_captionSettingsMenuItem);
4821 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4823 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4825 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4827 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4828 * @file captions-button.js
4833 * The button component for toggling and selecting captions
4835 * @extends TextTrackButton
4837 var CaptionsButton = function (_TextTrackButton) {
4838 _inherits(CaptionsButton, _TextTrackButton);
4841 * Creates an instance of this class.
4843 * @param {Player} player
4844 * The `Player` that this class should be attached to.
4846 * @param {Object} [options]
4847 * The key/value store of player options.
4849 * @param {Component~ReadyCallback} [ready]
4850 * The function to call when this component is ready.
4852 function CaptionsButton(player, options, ready) {
4853 _classCallCheck(this, CaptionsButton);
4855 var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
4857 _this.el_.setAttribute('aria-label', 'Captions Menu');
4862 * Builds the default DOM `className`.
4865 * The DOM `className` for this object.
4869 CaptionsButton.prototype.buildCSSClass = function buildCSSClass() {
4870 return 'vjs-captions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
4874 * Update caption menu items
4876 * @param {EventTarget~Event} [event]
4877 * The `addtrack` or `removetrack` event that caused this function to be
4880 * @listens TextTrackList#addtrack
4881 * @listens TextTrackList#removetrack
4885 CaptionsButton.prototype.update = function update(event) {
4888 _TextTrackButton.prototype.update.call(this);
4890 // if native, then threshold is 1 because no settings button
4891 if (this.player().tech_ && this.player().tech_.featuresNativeTextTracks) {
4895 if (this.items && this.items.length > threshold) {
4903 * Create caption menu items
4905 * @return {CaptionSettingsMenuItem[]}
4906 * The array of current menu items.
4910 CaptionsButton.prototype.createItems = function createItems() {
4913 if (!(this.player().tech_ && this.player().tech_.featuresNativeTextTracks)) {
4914 items.push(new _captionSettingsMenuItem2['default'](this.player_, { kind: this.kind_ }));
4917 return _TextTrackButton.prototype.createItems.call(this, items);
4920 return CaptionsButton;
4921 }(_textTrackButton2['default']);
4924 * `kind` of TextTrack to look for to associate it with this menu.
4931 CaptionsButton.prototype.kind_ = 'captions';
4934 * The text that should display over the `CaptionsButton`s controls. Added for localization.
4939 CaptionsButton.prototype.controlText_ = 'Captions';
4941 _component2['default'].registerComponent('CaptionsButton', CaptionsButton);
4942 exports['default'] = CaptionsButton;
4944 },{"23":23,"30":30,"5":5}],25:[function(_dereq_,module,exports){
4947 exports.__esModule = true;
4949 var _textTrackButton = _dereq_(30);
4951 var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
4953 var _component = _dereq_(5);
4955 var _component2 = _interopRequireDefault(_component);
4957 var _chaptersTrackMenuItem = _dereq_(26);
4959 var _chaptersTrackMenuItem2 = _interopRequireDefault(_chaptersTrackMenuItem);
4961 var _toTitleCase = _dereq_(91);
4963 var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
4965 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
4967 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4969 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
4971 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
4972 * @file chapters-button.js
4977 * The button component for toggling and selecting chapters
4978 * Chapters act much differently than other text tracks
4979 * Cues are navigation vs. other tracks of alternative languages
4981 * @extends TextTrackButton
4983 var ChaptersButton = function (_TextTrackButton) {
4984 _inherits(ChaptersButton, _TextTrackButton);
4987 * Creates an instance of this class.
4989 * @param {Player} player
4990 * The `Player` that this class should be attached to.
4992 * @param {Object} [options]
4993 * The key/value store of player options.
4995 * @param {Component~ReadyCallback} [ready]
4996 * The function to call when this function is ready.
4998 function ChaptersButton(player, options, ready) {
4999 _classCallCheck(this, ChaptersButton);
5001 var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
5003 _this.el_.setAttribute('aria-label', 'Chapters Menu');
5008 * Builds the default DOM `className`.
5011 * The DOM `className` for this object.
5015 ChaptersButton.prototype.buildCSSClass = function buildCSSClass() {
5016 return 'vjs-chapters-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
5020 * Update the menu based on the current state of its items.
5022 * @param {EventTarget~Event} [event]
5023 * An event that triggered this function to run.
5025 * @listens TextTrackList#addtrack
5026 * @listens TextTrackList#removetrack
5027 * @listens TextTrackList#change
5031 ChaptersButton.prototype.update = function update(event) {
5032 if (!this.track_ || event && (event.type === 'addtrack' || event.type === 'removetrack')) {
5033 this.setTrack(this.findChaptersTrack());
5035 _TextTrackButton.prototype.update.call(this);
5039 * Set the currently selected track for the chapters button.
5041 * @param {TextTrack} track
5042 * The new track to select. Nothing will change if this is the currently selected
5047 ChaptersButton.prototype.setTrack = function setTrack(track) {
5048 if (this.track_ === track) {
5052 if (!this.updateHandler_) {
5053 this.updateHandler_ = this.update.bind(this);
5056 // here this.track_ refers to the old track instance
5058 var remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);
5060 if (remoteTextTrackEl) {
5061 remoteTextTrackEl.removeEventListener('load', this.updateHandler_);
5067 this.track_ = track;
5069 // here this.track_ refers to the new track instance
5071 this.track_.mode = 'hidden';
5073 var _remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);
5075 if (_remoteTextTrackEl) {
5076 _remoteTextTrackEl.addEventListener('load', this.updateHandler_);
5082 * Find the track object that is currently in use by this ChaptersButton
5084 * @return {TextTrack|undefined}
5085 * The current track or undefined if none was found.
5089 ChaptersButton.prototype.findChaptersTrack = function findChaptersTrack() {
5090 var tracks = this.player_.textTracks() || [];
5092 for (var i = tracks.length - 1; i >= 0; i--) {
5093 // We will always choose the last track as our chaptersTrack
5094 var track = tracks[i];
5096 if (track.kind === this.kind_) {
5103 * Get the caption for the ChaptersButton based on the track label. This will also
5104 * use the current tracks localized kind as a fallback if a label does not exist.
5107 * The tracks current label or the localized track kind.
5111 ChaptersButton.prototype.getMenuCaption = function getMenuCaption() {
5112 if (this.track_ && this.track_.label) {
5113 return this.track_.label;
5115 return this.localize((0, _toTitleCase2['default'])(this.kind_));
5119 * Create menu from chapter track
5122 * New menu for the chapter buttons
5126 ChaptersButton.prototype.createMenu = function createMenu() {
5127 this.options_.title = this.getMenuCaption();
5128 return _TextTrackButton.prototype.createMenu.call(this);
5132 * Create a menu item for each text track
5134 * @return {TextTrackMenuItem[]}
5135 * Array of menu items
5139 ChaptersButton.prototype.createItems = function createItems() {
5146 var cues = this.track_.cues;
5152 for (var i = 0, l = cues.length; i < l; i++) {
5154 var mi = new _chaptersTrackMenuItem2['default'](this.player_, { track: this.track_, cue: cue });
5162 return ChaptersButton;
5163 }(_textTrackButton2['default']);
5166 * `kind` of TextTrack to look for to associate it with this menu.
5173 ChaptersButton.prototype.kind_ = 'chapters';
5176 * The text that should display over the `ChaptersButton`s controls. Added for localization.
5181 ChaptersButton.prototype.controlText_ = 'Chapters';
5183 _component2['default'].registerComponent('ChaptersButton', ChaptersButton);
5184 exports['default'] = ChaptersButton;
5186 },{"26":26,"30":30,"5":5,"91":91}],26:[function(_dereq_,module,exports){
5189 exports.__esModule = true;
5191 var _menuItem = _dereq_(48);
5193 var _menuItem2 = _interopRequireDefault(_menuItem);
5195 var _component = _dereq_(5);
5197 var _component2 = _interopRequireDefault(_component);
5199 var _fn = _dereq_(83);
5201 var Fn = _interopRequireWildcard(_fn);
5203 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5205 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5207 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5209 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
5211 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
5212 * @file chapters-track-menu-item.js
5217 * The chapter track menu item
5221 var ChaptersTrackMenuItem = function (_MenuItem) {
5222 _inherits(ChaptersTrackMenuItem, _MenuItem);
5225 * Creates an instance of this class.
5227 * @param {Player} player
5228 * The `Player` that this class should be attached to.
5230 * @param {Object} [options]
5231 * The key/value store of player options.
5233 function ChaptersTrackMenuItem(player, options) {
5234 _classCallCheck(this, ChaptersTrackMenuItem);
5236 var track = options.track;
5237 var cue = options.cue;
5238 var currentTime = player.currentTime();
5240 // Modify options for parent MenuItem class's init.
5241 options.selectable = true;
5242 options.label = cue.text;
5243 options.selected = cue.startTime <= currentTime && currentTime < cue.endTime;
5245 var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
5247 _this.track = track;
5249 track.addEventListener('cuechange', Fn.bind(_this, _this.update));
5254 * This gets called when an `ChaptersTrackMenuItem` is "clicked". See
5255 * {@link ClickableComponent} for more detailed information on what a click can be.
5257 * @param {EventTarget~Event} [event]
5258 * The `keydown`, `tap`, or `click` event that caused this function to be
5266 ChaptersTrackMenuItem.prototype.handleClick = function handleClick(event) {
5267 _MenuItem.prototype.handleClick.call(this);
5268 this.player_.currentTime(this.cue.startTime);
5269 this.update(this.cue.startTime);
5273 * Update chapter menu item
5275 * @param {EventTarget~Event} [event]
5276 * The `cuechange` event that caused this function to run.
5278 * @listens TextTrack#cuechange
5282 ChaptersTrackMenuItem.prototype.update = function update(event) {
5284 var currentTime = this.player_.currentTime();
5286 // vjs.log(currentTime, cue.startTime);
5287 this.selected(cue.startTime <= currentTime && currentTime < cue.endTime);
5290 return ChaptersTrackMenuItem;
5291 }(_menuItem2['default']);
5293 _component2['default'].registerComponent('ChaptersTrackMenuItem', ChaptersTrackMenuItem);
5294 exports['default'] = ChaptersTrackMenuItem;
5296 },{"48":48,"5":5,"83":83}],27:[function(_dereq_,module,exports){
5299 exports.__esModule = true;
5301 var _textTrackButton = _dereq_(30);
5303 var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
5305 var _component = _dereq_(5);
5307 var _component2 = _interopRequireDefault(_component);
5309 var _fn = _dereq_(83);
5311 var Fn = _interopRequireWildcard(_fn);
5313 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5315 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5317 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5319 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
5321 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
5322 * @file descriptions-button.js
5327 * The button component for toggling and selecting descriptions
5329 * @extends TextTrackButton
5331 var DescriptionsButton = function (_TextTrackButton) {
5332 _inherits(DescriptionsButton, _TextTrackButton);
5335 * Creates an instance of this class.
5337 * @param {Player} player
5338 * The `Player` that this class should be attached to.
5340 * @param {Object} [options]
5341 * The key/value store of player options.
5343 * @param {Component~ReadyCallback} [ready]
5344 * The function to call when this component is ready.
5346 function DescriptionsButton(player, options, ready) {
5347 _classCallCheck(this, DescriptionsButton);
5349 var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
5351 _this.el_.setAttribute('aria-label', 'Descriptions Menu');
5353 var tracks = player.textTracks();
5357 var changeHandler = Fn.bind(_this, _this.handleTracksChange);
5359 tracks.addEventListener('change', changeHandler);
5360 _this.on('dispose', function () {
5361 tracks.removeEventListener('change', changeHandler);
5369 * Handle text track change
5371 * @param {EventTarget~Event} event
5372 * The event that caused this function to run
5374 * @listens TextTrackList#change
5378 DescriptionsButton.prototype.handleTracksChange = function handleTracksChange(event) {
5379 var tracks = this.player().textTracks();
5380 var disabled = false;
5382 // Check whether a track of a different kind is showing
5383 for (var i = 0, l = tracks.length; i < l; i++) {
5384 var track = tracks[i];
5386 if (track.kind !== this.kind_ && track.mode === 'showing') {
5392 // If another track is showing, disable this menu button
5401 * Builds the default DOM `className`.
5404 * The DOM `className` for this object.
5408 DescriptionsButton.prototype.buildCSSClass = function buildCSSClass() {
5409 return 'vjs-descriptions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
5412 return DescriptionsButton;
5413 }(_textTrackButton2['default']);
5416 * `kind` of TextTrack to look for to associate it with this menu.
5423 DescriptionsButton.prototype.kind_ = 'descriptions';
5426 * The text that should display over the `DescriptionsButton`s controls. Added for localization.
5431 DescriptionsButton.prototype.controlText_ = 'Descriptions';
5433 _component2['default'].registerComponent('DescriptionsButton', DescriptionsButton);
5434 exports['default'] = DescriptionsButton;
5436 },{"30":30,"5":5,"83":83}],28:[function(_dereq_,module,exports){
5439 exports.__esModule = true;
5441 var _textTrackMenuItem = _dereq_(31);
5443 var _textTrackMenuItem2 = _interopRequireDefault(_textTrackMenuItem);
5445 var _component = _dereq_(5);
5447 var _component2 = _interopRequireDefault(_component);
5449 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5451 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5453 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
5455 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
5456 * @file off-text-track-menu-item.js
5461 * A special menu item for turning of a specific type of text track
5463 * @extends TextTrackMenuItem
5465 var OffTextTrackMenuItem = function (_TextTrackMenuItem) {
5466 _inherits(OffTextTrackMenuItem, _TextTrackMenuItem);
5469 * Creates an instance of this class.
5471 * @param {Player} player
5472 * The `Player` that this class should be attached to.
5474 * @param {Object} [options]
5475 * The key/value store of player options.
5477 function OffTextTrackMenuItem(player, options) {
5478 _classCallCheck(this, OffTextTrackMenuItem);
5480 // Create pseudo track info
5481 // Requires options['kind']
5485 label: options.kind + ' off',
5490 // MenuItem is selectable
5491 options.selectable = true;
5493 var _this = _possibleConstructorReturn(this, _TextTrackMenuItem.call(this, player, options));
5495 _this.selected(true);
5500 * Handle text track change
5502 * @param {EventTarget~Event} event
5503 * The event that caused this function to run
5507 OffTextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
5508 var tracks = this.player().textTracks();
5509 var selected = true;
5511 for (var i = 0, l = tracks.length; i < l; i++) {
5512 var track = tracks[i];
5514 if (track.kind === this.track.kind && track.mode === 'showing') {
5520 this.selected(selected);
5523 return OffTextTrackMenuItem;
5524 }(_textTrackMenuItem2['default']);
5526 _component2['default'].registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem);
5527 exports['default'] = OffTextTrackMenuItem;
5529 },{"31":31,"5":5}],29:[function(_dereq_,module,exports){
5532 exports.__esModule = true;
5534 var _textTrackButton = _dereq_(30);
5536 var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
5538 var _component = _dereq_(5);
5540 var _component2 = _interopRequireDefault(_component);
5542 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5544 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5546 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
5548 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
5549 * @file subtitles-button.js
5554 * The button component for toggling and selecting subtitles
5556 * @extends TextTrackButton
5558 var SubtitlesButton = function (_TextTrackButton) {
5559 _inherits(SubtitlesButton, _TextTrackButton);
5562 * Creates an instance of this class.
5564 * @param {Player} player
5565 * The `Player` that this class should be attached to.
5567 * @param {Object} [options]
5568 * The key/value store of player options.
5570 * @param {Component~ReadyCallback} [ready]
5571 * The function to call when this component is ready.
5573 function SubtitlesButton(player, options, ready) {
5574 _classCallCheck(this, SubtitlesButton);
5576 var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
5578 _this.el_.setAttribute('aria-label', 'Subtitles Menu');
5583 * Builds the default DOM `className`.
5586 * The DOM `className` for this object.
5590 SubtitlesButton.prototype.buildCSSClass = function buildCSSClass() {
5591 return 'vjs-subtitles-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
5594 return SubtitlesButton;
5595 }(_textTrackButton2['default']);
5598 * `kind` of TextTrack to look for to associate it with this menu.
5605 SubtitlesButton.prototype.kind_ = 'subtitles';
5608 * The text that should display over the `SubtitlesButton`s controls. Added for localization.
5613 SubtitlesButton.prototype.controlText_ = 'Subtitles';
5615 _component2['default'].registerComponent('SubtitlesButton', SubtitlesButton);
5616 exports['default'] = SubtitlesButton;
5618 },{"30":30,"5":5}],30:[function(_dereq_,module,exports){
5621 exports.__esModule = true;
5623 var _trackButton = _dereq_(36);
5625 var _trackButton2 = _interopRequireDefault(_trackButton);
5627 var _component = _dereq_(5);
5629 var _component2 = _interopRequireDefault(_component);
5631 var _textTrackMenuItem = _dereq_(31);
5633 var _textTrackMenuItem2 = _interopRequireDefault(_textTrackMenuItem);
5635 var _offTextTrackMenuItem = _dereq_(28);
5637 var _offTextTrackMenuItem2 = _interopRequireDefault(_offTextTrackMenuItem);
5639 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5641 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5643 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
5645 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
5646 * @file text-track-button.js
5651 * The base class for buttons that toggle specific text track types (e.g. subtitles)
5653 * @extends MenuButton
5655 var TextTrackButton = function (_TrackButton) {
5656 _inherits(TextTrackButton, _TrackButton);
5659 * Creates an instance of this class.
5661 * @param {Player} player
5662 * The `Player` that this class should be attached to.
5664 * @param {Object} [options={}]
5665 * The key/value store of player options.
5667 function TextTrackButton(player) {
5668 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
5670 _classCallCheck(this, TextTrackButton);
5672 options.tracks = player.textTracks();
5674 return _possibleConstructorReturn(this, _TrackButton.call(this, player, options));
5678 * Create a menu item for each text track
5680 * @param {TextTrackMenuItem[]} [items=[]]
5681 * Existing array of items to use during creation
5683 * @return {TextTrackMenuItem[]}
5684 * Array of menu items that were created
5688 TextTrackButton.prototype.createItems = function createItems() {
5689 var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
5691 // Add an OFF menu item to turn all tracks off
5692 items.push(new _offTextTrackMenuItem2['default'](this.player_, { kind: this.kind_ }));
5694 var tracks = this.player_.textTracks();
5700 for (var i = 0; i < tracks.length; i++) {
5701 var track = tracks[i];
5703 // only add tracks that are of the appropriate kind and have a label
5704 if (track.kind === this.kind_) {
5705 items.push(new _textTrackMenuItem2['default'](this.player_, {
5707 // MenuItem is selectable
5716 return TextTrackButton;
5717 }(_trackButton2['default']);
5719 _component2['default'].registerComponent('TextTrackButton', TextTrackButton);
5720 exports['default'] = TextTrackButton;
5722 },{"28":28,"31":31,"36":36,"5":5}],31:[function(_dereq_,module,exports){
5725 exports.__esModule = true;
5727 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
5729 var _menuItem = _dereq_(48);
5731 var _menuItem2 = _interopRequireDefault(_menuItem);
5733 var _component = _dereq_(5);
5735 var _component2 = _interopRequireDefault(_component);
5737 var _fn = _dereq_(83);
5739 var Fn = _interopRequireWildcard(_fn);
5741 var _window = _dereq_(95);
5743 var _window2 = _interopRequireDefault(_window);
5745 var _document = _dereq_(94);
5747 var _document2 = _interopRequireDefault(_document);
5749 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5751 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5753 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5755 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
5757 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
5758 * @file text-track-menu-item.js
5763 * The specific menu item type for selecting a language within a text track kind
5767 var TextTrackMenuItem = function (_MenuItem) {
5768 _inherits(TextTrackMenuItem, _MenuItem);
5771 * Creates an instance of this class.
5773 * @param {Player} player
5774 * The `Player` that this class should be attached to.
5776 * @param {Object} [options]
5777 * The key/value store of player options.
5779 function TextTrackMenuItem(player, options) {
5780 _classCallCheck(this, TextTrackMenuItem);
5782 var track = options.track;
5783 var tracks = player.textTracks();
5785 // Modify options for parent MenuItem class's init.
5786 options.label = track.label || track.language || 'Unknown';
5787 options.selected = track['default'] || track.mode === 'showing';
5789 var _this = _possibleConstructorReturn(this, _MenuItem.call(this, player, options));
5791 _this.track = track;
5795 var changeHandler = Fn.bind(_this, _this.handleTracksChange);
5797 tracks.addEventListener('change', changeHandler);
5798 _this.on('dispose', function () {
5799 tracks.removeEventListener('change', changeHandler);
5804 // iOS7 doesn't dispatch change events to TextTrackLists when an
5805 // associated track's mode changes. Without something like
5806 // Object.observe() (also not present on iOS7), it's not
5807 // possible to detect changes to the mode attribute and polyfill
5808 // the change event. As a poor substitute, we manually dispatch
5809 // change events whenever the controls modify the mode.
5810 if (tracks && tracks.onchange === undefined) {
5814 _this.on(['tap', 'click'], function () {
5815 if (_typeof(_window2['default'].Event) !== 'object') {
5816 // Android 2.3 throws an Illegal Constructor error for window.Event
5818 event = new _window2['default'].Event('change');
5820 // continue regardless of error
5825 event = _document2['default'].createEvent('Event');
5826 event.initEvent('change', true, true);
5829 tracks.dispatchEvent(event);
5837 * This gets called when an `TextTrackMenuItem` is "clicked". See
5838 * {@link ClickableComponent} for more detailed information on what a click can be.
5840 * @param {EventTarget~Event} event
5841 * The `keydown`, `tap`, or `click` event that caused this function to be
5849 TextTrackMenuItem.prototype.handleClick = function handleClick(event) {
5850 var kind = this.track.kind;
5851 var tracks = this.player_.textTracks();
5853 _MenuItem.prototype.handleClick.call(this, event);
5859 for (var i = 0; i < tracks.length; i++) {
5860 var track = tracks[i];
5862 if (track.kind !== kind) {
5866 if (track === this.track) {
5867 track.mode = 'showing';
5869 track.mode = 'disabled';
5875 * Handle text track list change
5877 * @param {EventTarget~Event} event
5878 * The `change` event that caused this function to be called.
5880 * @listens TextTrackList#change
5884 TextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) {
5885 this.selected(this.track.mode === 'showing');
5888 return TextTrackMenuItem;
5889 }(_menuItem2['default']);
5891 _component2['default'].registerComponent('TextTrackMenuItem', TextTrackMenuItem);
5892 exports['default'] = TextTrackMenuItem;
5894 },{"48":48,"5":5,"83":83,"94":94,"95":95}],32:[function(_dereq_,module,exports){
5897 exports.__esModule = true;
5899 var _component = _dereq_(5);
5901 var _component2 = _interopRequireDefault(_component);
5903 var _dom = _dereq_(81);
5905 var Dom = _interopRequireWildcard(_dom);
5907 var _formatTime = _dereq_(84);
5909 var _formatTime2 = _interopRequireDefault(_formatTime);
5911 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
5913 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
5915 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5917 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
5919 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
5920 * @file current-time-display.js
5925 * Displays the current time
5927 * @extends Component
5929 var CurrentTimeDisplay = function (_Component) {
5930 _inherits(CurrentTimeDisplay, _Component);
5933 * Creates an instance of this class.
5935 * @param {Player} player
5936 * The `Player` that this class should be attached to.
5938 * @param {Object} [options]
5939 * The key/value store of player options.
5941 function CurrentTimeDisplay(player, options) {
5942 _classCallCheck(this, CurrentTimeDisplay);
5944 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
5946 _this.on(player, 'timeupdate', _this.updateContent);
5951 * Create the `Component`'s DOM element
5954 * The element that was created.
5958 CurrentTimeDisplay.prototype.createEl = function createEl() {
5959 var el = _Component.prototype.createEl.call(this, 'div', {
5960 className: 'vjs-current-time vjs-time-control vjs-control'
5963 this.contentEl_ = Dom.createEl('div', {
5964 className: 'vjs-current-time-display',
5965 // label the current time for screen reader users
5966 innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00'
5968 // tell screen readers not to automatically read the time as it changes
5972 el.appendChild(this.contentEl_);
5977 * Update current time display
5979 * @param {EventTarget~Event} [event]
5980 * The `timeupdate` event that caused this function to run.
5982 * @listens Player#timeupdate
5986 CurrentTimeDisplay.prototype.updateContent = function updateContent(event) {
5987 // Allows for smooth scrubbing, when player can't keep up.
5988 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime();
5989 var localizedText = this.localize('Current Time');
5990 var formattedTime = (0, _formatTime2['default'])(time, this.player_.duration());
5992 if (formattedTime !== this.formattedTime_) {
5993 this.formattedTime_ = formattedTime;
5994 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime;
5998 return CurrentTimeDisplay;
5999 }(_component2['default']);
6001 _component2['default'].registerComponent('CurrentTimeDisplay', CurrentTimeDisplay);
6002 exports['default'] = CurrentTimeDisplay;
6004 },{"5":5,"81":81,"84":84}],33:[function(_dereq_,module,exports){
6007 exports.__esModule = true;
6009 var _component = _dereq_(5);
6011 var _component2 = _interopRequireDefault(_component);
6013 var _dom = _dereq_(81);
6015 var Dom = _interopRequireWildcard(_dom);
6017 var _formatTime = _dereq_(84);
6019 var _formatTime2 = _interopRequireDefault(_formatTime);
6021 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6023 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6025 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6027 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6029 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6030 * @file duration-display.js
6035 * Displays the duration
6037 * @extends Component
6039 var DurationDisplay = function (_Component) {
6040 _inherits(DurationDisplay, _Component);
6043 * Creates an instance of this class.
6045 * @param {Player} player
6046 * The `Player` that this class should be attached to.
6048 * @param {Object} [options]
6049 * The key/value store of player options.
6051 function DurationDisplay(player, options) {
6052 _classCallCheck(this, DurationDisplay);
6054 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
6056 _this.on(player, 'durationchange', _this.updateContent);
6058 // Also listen for timeupdate and loadedmetadata because removing those
6059 // listeners could have broken dependent applications/libraries. These
6060 // can likely be removed for 6.0.
6061 _this.on(player, 'timeupdate', _this.updateContent);
6062 _this.on(player, 'loadedmetadata', _this.updateContent);
6067 * Create the `Component`'s DOM element
6070 * The element that was created.
6074 DurationDisplay.prototype.createEl = function createEl() {
6075 var el = _Component.prototype.createEl.call(this, 'div', {
6076 className: 'vjs-duration vjs-time-control vjs-control'
6079 this.contentEl_ = Dom.createEl('div', {
6080 className: 'vjs-duration-display',
6081 // label the duration time for screen reader users
6082 innerHTML: '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span> 0:00'
6084 // tell screen readers not to automatically read the time as it changes
6088 el.appendChild(this.contentEl_);
6093 * Update duration time display.
6095 * @param {EventTarget~Event} [event]
6096 * The `durationchange`, `timeupdate`, or `loadedmetadata` event that caused
6097 * this function to be called.
6099 * @listens Player#durationchange
6100 * @listens Player#timeupdate
6101 * @listens Player#loadedmetadata
6105 DurationDisplay.prototype.updateContent = function updateContent(event) {
6106 var duration = this.player_.duration();
6108 if (duration && this.duration_ !== duration) {
6109 this.duration_ = duration;
6110 var localizedText = this.localize('Duration Time');
6111 var formattedTime = (0, _formatTime2['default'])(duration);
6113 // label the duration time for screen reader users
6114 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime;
6118 return DurationDisplay;
6119 }(_component2['default']);
6121 _component2['default'].registerComponent('DurationDisplay', DurationDisplay);
6122 exports['default'] = DurationDisplay;
6124 },{"5":5,"81":81,"84":84}],34:[function(_dereq_,module,exports){
6127 exports.__esModule = true;
6129 var _component = _dereq_(5);
6131 var _component2 = _interopRequireDefault(_component);
6133 var _dom = _dereq_(81);
6135 var Dom = _interopRequireWildcard(_dom);
6137 var _formatTime = _dereq_(84);
6139 var _formatTime2 = _interopRequireDefault(_formatTime);
6141 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6143 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6145 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6147 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6149 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6150 * @file remaining-time-display.js
6155 * Displays the time left in the video
6157 * @extends Component
6159 var RemainingTimeDisplay = function (_Component) {
6160 _inherits(RemainingTimeDisplay, _Component);
6163 * Creates an instance of this class.
6165 * @param {Player} player
6166 * The `Player` that this class should be attached to.
6168 * @param {Object} [options]
6169 * The key/value store of player options.
6171 function RemainingTimeDisplay(player, options) {
6172 _classCallCheck(this, RemainingTimeDisplay);
6174 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
6176 _this.on(player, 'timeupdate', _this.updateContent);
6177 _this.on(player, 'durationchange', _this.updateContent);
6182 * Create the `Component`'s DOM element
6185 * The element that was created.
6189 RemainingTimeDisplay.prototype.createEl = function createEl() {
6190 var el = _Component.prototype.createEl.call(this, 'div', {
6191 className: 'vjs-remaining-time vjs-time-control vjs-control'
6194 this.contentEl_ = Dom.createEl('div', {
6195 className: 'vjs-remaining-time-display',
6196 // label the remaining time for screen reader users
6197 innerHTML: '<span class="vjs-control-text">' + this.localize('Remaining Time') + '</span> -0:00'
6199 // tell screen readers not to automatically read the time as it changes
6203 el.appendChild(this.contentEl_);
6208 * Update remaining time display.
6210 * @param {EventTarget~Event} [event]
6211 * The `timeupdate` or `durationchange` event that caused this to run.
6213 * @listens Player#timeupdate
6214 * @listens Player#durationchange
6218 RemainingTimeDisplay.prototype.updateContent = function updateContent(event) {
6219 if (this.player_.duration()) {
6220 var localizedText = this.localize('Remaining Time');
6221 var formattedTime = (0, _formatTime2['default'])(this.player_.remainingTime());
6223 if (formattedTime !== this.formattedTime_) {
6224 this.formattedTime_ = formattedTime;
6225 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> -' + formattedTime;
6229 // Allows for smooth scrubbing, when player can't keep up.
6230 // var time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime();
6231 // this.contentEl_.innerHTML = vjs.formatTime(time, this.player_.duration());
6234 return RemainingTimeDisplay;
6235 }(_component2['default']);
6237 _component2['default'].registerComponent('RemainingTimeDisplay', RemainingTimeDisplay);
6238 exports['default'] = RemainingTimeDisplay;
6240 },{"5":5,"81":81,"84":84}],35:[function(_dereq_,module,exports){
6243 exports.__esModule = true;
6245 var _component = _dereq_(5);
6247 var _component2 = _interopRequireDefault(_component);
6249 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6251 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6253 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6255 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6256 * @file time-divider.js
6261 * The separator between the current time and duration.
6262 * Can be hidden if it's not needed in the design.
6264 * @extends Component
6266 var TimeDivider = function (_Component) {
6267 _inherits(TimeDivider, _Component);
6269 function TimeDivider() {
6270 _classCallCheck(this, TimeDivider);
6272 return _possibleConstructorReturn(this, _Component.apply(this, arguments));
6276 * Create the component's DOM element
6279 * The element that was created.
6281 TimeDivider.prototype.createEl = function createEl() {
6282 return _Component.prototype.createEl.call(this, 'div', {
6283 className: 'vjs-time-control vjs-time-divider',
6284 innerHTML: '<div><span>/</span></div>'
6289 }(_component2['default']);
6291 _component2['default'].registerComponent('TimeDivider', TimeDivider);
6292 exports['default'] = TimeDivider;
6294 },{"5":5}],36:[function(_dereq_,module,exports){
6297 exports.__esModule = true;
6299 var _menuButton = _dereq_(47);
6301 var _menuButton2 = _interopRequireDefault(_menuButton);
6303 var _component = _dereq_(5);
6305 var _component2 = _interopRequireDefault(_component);
6307 var _fn = _dereq_(83);
6309 var Fn = _interopRequireWildcard(_fn);
6311 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6313 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6315 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6317 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6319 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6320 * @file track-button.js
6325 * The base class for buttons that toggle specific track types (e.g. subtitles).
6327 * @extends MenuButton
6329 var TrackButton = function (_MenuButton) {
6330 _inherits(TrackButton, _MenuButton);
6333 * Creates an instance of this class.
6335 * @param {Player} player
6336 * The `Player` that this class should be attached to.
6338 * @param {Object} [options]
6339 * The key/value store of player options.
6341 function TrackButton(player, options) {
6342 _classCallCheck(this, TrackButton);
6344 var tracks = options.tracks;
6346 var _this = _possibleConstructorReturn(this, _MenuButton.call(this, player, options));
6348 if (_this.items.length <= 1) {
6353 return _possibleConstructorReturn(_this);
6356 var updateHandler = Fn.bind(_this, _this.update);
6358 tracks.addEventListener('removetrack', updateHandler);
6359 tracks.addEventListener('addtrack', updateHandler);
6361 _this.player_.on('dispose', function () {
6362 tracks.removeEventListener('removetrack', updateHandler);
6363 tracks.removeEventListener('addtrack', updateHandler);
6369 }(_menuButton2['default']);
6371 _component2['default'].registerComponent('TrackButton', TrackButton);
6372 exports['default'] = TrackButton;
6374 },{"47":47,"5":5,"83":83}],37:[function(_dereq_,module,exports){
6377 exports.__esModule = true;
6379 var _slider = _dereq_(57);
6381 var _slider2 = _interopRequireDefault(_slider);
6383 var _component = _dereq_(5);
6385 var _component2 = _interopRequireDefault(_component);
6387 var _fn = _dereq_(83);
6389 var Fn = _interopRequireWildcard(_fn);
6393 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6395 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6397 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6399 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6401 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6402 * @file volume-bar.js
6406 // Required children
6410 * The bar that contains the volume level and can be clicked on to adjust the level
6414 var VolumeBar = function (_Slider) {
6415 _inherits(VolumeBar, _Slider);
6418 * Creates an instance of this class.
6420 * @param {Player} player
6421 * The `Player` that this class should be attached to.
6423 * @param {Object} [options]
6424 * The key/value store of player options.
6426 function VolumeBar(player, options) {
6427 _classCallCheck(this, VolumeBar);
6429 var _this = _possibleConstructorReturn(this, _Slider.call(this, player, options));
6431 _this.on(player, 'volumechange', _this.updateARIAAttributes);
6432 player.ready(Fn.bind(_this, _this.updateARIAAttributes));
6437 * Create the `Component`'s DOM element
6440 * The element that was created.
6444 VolumeBar.prototype.createEl = function createEl() {
6445 return _Slider.prototype.createEl.call(this, 'div', {
6446 className: 'vjs-volume-bar vjs-slider-bar'
6448 'aria-label': 'volume level'
6453 * Handle movement events on the {@link VolumeMenuButton}.
6455 * @param {EventTarget~Event} event
6456 * The event that caused this function to run.
6458 * @listens mousemove
6462 VolumeBar.prototype.handleMouseMove = function handleMouseMove(event) {
6464 this.player_.volume(this.calculateDistance(event));
6468 * If the player is muted unmute it.
6472 VolumeBar.prototype.checkMuted = function checkMuted() {
6473 if (this.player_.muted()) {
6474 this.player_.muted(false);
6479 * Get percent of volume level
6482 * Volume level percent as a decimal number.
6486 VolumeBar.prototype.getPercent = function getPercent() {
6487 if (this.player_.muted()) {
6490 return this.player_.volume();
6494 * Increase volume level for keyboard users
6498 VolumeBar.prototype.stepForward = function stepForward() {
6500 this.player_.volume(this.player_.volume() + 0.1);
6504 * Decrease volume level for keyboard users
6508 VolumeBar.prototype.stepBack = function stepBack() {
6510 this.player_.volume(this.player_.volume() - 0.1);
6514 * Update ARIA accessibility attributes
6516 * @param {EventTarget~Event} [event]
6517 * The `volumechange` event that caused this function to run.
6519 * @listens Player#volumechange
6523 VolumeBar.prototype.updateARIAAttributes = function updateARIAAttributes(event) {
6524 // Current value of volume bar as a percentage
6525 var volume = (this.player_.volume() * 100).toFixed(2);
6527 this.el_.setAttribute('aria-valuenow', volume);
6528 this.el_.setAttribute('aria-valuetext', volume + '%');
6532 }(_slider2['default']);
6535 * Default options for the `VolumeBar`
6542 VolumeBar.prototype.options_ = {
6543 children: ['volumeLevel'],
6544 barName: 'volumeLevel'
6548 * Call the update event for this Slider when this event happens on the player.
6552 VolumeBar.prototype.playerEvent = 'volumechange';
6554 _component2['default'].registerComponent('VolumeBar', VolumeBar);
6555 exports['default'] = VolumeBar;
6557 },{"39":39,"5":5,"57":57,"83":83}],38:[function(_dereq_,module,exports){
6560 exports.__esModule = true;
6562 var _component = _dereq_(5);
6564 var _component2 = _interopRequireDefault(_component);
6568 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6570 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6572 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6574 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6575 * @file volume-control.js
6579 // Required children
6583 * The component for controlling the volume level
6585 * @extends Component
6587 var VolumeControl = function (_Component) {
6588 _inherits(VolumeControl, _Component);
6591 * Creates an instance of this class.
6593 * @param {Player} player
6594 * The `Player` that this class should be attached to.
6596 * @param {Object} [options={}]
6597 * The key/value store of player options.
6599 function VolumeControl(player, options) {
6600 _classCallCheck(this, VolumeControl);
6602 // hide volume controls when they're not supported by the current tech
6603 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
6605 if (player.tech_ && player.tech_.featuresVolumeControl === false) {
6606 _this.addClass('vjs-hidden');
6608 _this.on(player, 'loadstart', function () {
6609 if (player.tech_.featuresVolumeControl === false) {
6610 this.addClass('vjs-hidden');
6612 this.removeClass('vjs-hidden');
6619 * Create the `Component`'s DOM element
6622 * The element that was created.
6626 VolumeControl.prototype.createEl = function createEl() {
6627 return _Component.prototype.createEl.call(this, 'div', {
6628 className: 'vjs-volume-control vjs-control'
6632 return VolumeControl;
6633 }(_component2['default']);
6636 * Default options for the `VolumeControl`
6643 VolumeControl.prototype.options_ = {
6644 children: ['volumeBar']
6647 _component2['default'].registerComponent('VolumeControl', VolumeControl);
6648 exports['default'] = VolumeControl;
6650 },{"37":37,"5":5}],39:[function(_dereq_,module,exports){
6653 exports.__esModule = true;
6655 var _component = _dereq_(5);
6657 var _component2 = _interopRequireDefault(_component);
6659 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6661 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6663 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6665 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6666 * @file volume-level.js
6671 * Shows volume level
6673 * @extends Component
6675 var VolumeLevel = function (_Component) {
6676 _inherits(VolumeLevel, _Component);
6678 function VolumeLevel() {
6679 _classCallCheck(this, VolumeLevel);
6681 return _possibleConstructorReturn(this, _Component.apply(this, arguments));
6685 * Create the `Component`'s DOM element
6688 * The element that was created.
6690 VolumeLevel.prototype.createEl = function createEl() {
6691 return _Component.prototype.createEl.call(this, 'div', {
6692 className: 'vjs-volume-level',
6693 innerHTML: '<span class="vjs-control-text"></span>'
6698 }(_component2['default']);
6700 _component2['default'].registerComponent('VolumeLevel', VolumeLevel);
6701 exports['default'] = VolumeLevel;
6703 },{"5":5}],40:[function(_dereq_,module,exports){
6706 exports.__esModule = true;
6708 var _fn = _dereq_(83);
6710 var Fn = _interopRequireWildcard(_fn);
6712 var _component = _dereq_(5);
6714 var _component2 = _interopRequireDefault(_component);
6716 var _popup = _dereq_(54);
6718 var _popup2 = _interopRequireDefault(_popup);
6720 var _popupButton = _dereq_(53);
6722 var _popupButton2 = _interopRequireDefault(_popupButton);
6724 var _muteToggle = _dereq_(11);
6726 var _muteToggle2 = _interopRequireDefault(_muteToggle);
6728 var _volumeBar = _dereq_(37);
6730 var _volumeBar2 = _interopRequireDefault(_volumeBar);
6732 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6734 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
6736 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6738 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6740 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6741 * @file volume-menu-button.js
6746 * Button for volume popup
6748 * @extends PopupButton
6750 var VolumeMenuButton = function (_PopupButton) {
6751 _inherits(VolumeMenuButton, _PopupButton);
6754 * Creates an instance of this class.
6756 * @param {Player} player
6757 * The `Player` that this class should be attached to.
6759 * @param {Object} [options={}]
6760 * The key/value store of player options.
6762 function VolumeMenuButton(player) {
6763 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6765 _classCallCheck(this, VolumeMenuButton);
6767 // Default to inline
6768 if (options.inline === undefined) {
6769 options.inline = true;
6772 // If the vertical option isn't passed at all, default to true.
6773 if (options.vertical === undefined) {
6774 // If an inline volumeMenuButton is used, we should default to using
6775 // a horizontal slider for obvious reasons.
6776 if (options.inline) {
6777 options.vertical = false;
6779 options.vertical = true;
6783 // The vertical option needs to be set on the volumeBar as well,
6784 // since that will need to be passed along to the VolumeBar constructor
6785 options.volumeBar = options.volumeBar || {};
6786 options.volumeBar.vertical = !!options.vertical;
6788 // Same listeners as MuteToggle
6789 var _this = _possibleConstructorReturn(this, _PopupButton.call(this, player, options));
6791 _this.on(player, 'volumechange', _this.volumeUpdate);
6792 _this.on(player, 'loadstart', _this.volumeUpdate);
6794 // hide mute toggle if the current tech doesn't support volume control
6795 function updateVisibility() {
6796 if (player.tech_ && player.tech_.featuresVolumeControl === false) {
6797 this.addClass('vjs-hidden');
6799 this.removeClass('vjs-hidden');
6803 updateVisibility.call(_this);
6804 _this.on(player, 'loadstart', updateVisibility);
6806 _this.on(_this.volumeBar, ['slideractive', 'focus'], function () {
6807 this.addClass('vjs-slider-active');
6810 _this.on(_this.volumeBar, ['sliderinactive', 'blur'], function () {
6811 this.removeClass('vjs-slider-active');
6814 _this.on(_this.volumeBar, ['focus'], function () {
6815 this.addClass('vjs-lock-showing');
6818 _this.on(_this.volumeBar, ['blur'], function () {
6819 this.removeClass('vjs-lock-showing');
6825 * Builds the default DOM `className`.
6828 * The DOM `className` for this object.
6832 VolumeMenuButton.prototype.buildCSSClass = function buildCSSClass() {
6833 var orientationClass = '';
6835 if (this.options_.vertical) {
6836 orientationClass = 'vjs-volume-menu-button-vertical';
6838 orientationClass = 'vjs-volume-menu-button-horizontal';
6841 return 'vjs-volume-menu-button ' + _PopupButton.prototype.buildCSSClass.call(this) + ' ' + orientationClass;
6845 * Create the VolumeMenuButton popup
6848 * The popup that was created
6852 VolumeMenuButton.prototype.createPopup = function createPopup() {
6853 var popup = new _popup2['default'](this.player_, {
6854 contentElType: 'div'
6857 var vb = new _volumeBar2['default'](this.player_, this.options_.volumeBar);
6861 this.menuContent = popup;
6862 this.volumeBar = vb;
6864 this.attachVolumeBarEvents();
6870 * This gets called when an `VolumeMenuButton` is "clicked". See
6871 * {@link ClickableComponent} for more detailed information on what a click can be.
6873 * @param {EventTarget~Event} [event]
6874 * The `keydown`, `tap`, or `click` event that caused this function to be
6882 VolumeMenuButton.prototype.handleClick = function handleClick(event) {
6883 _muteToggle2['default'].prototype.handleClick.call(this);
6884 _PopupButton.prototype.handleClick.call(this);
6888 * Add events listeners to the created `VolumeBar`.
6892 VolumeMenuButton.prototype.attachVolumeBarEvents = function attachVolumeBarEvents() {
6893 this.menuContent.on(['mousedown', 'touchdown'], Fn.bind(this, this.handleMouseDown));
6897 * Handle the `mousedown` and `touchdown` events on the `VolumeBar`
6899 * @param {EventTarget~Event} [event]
6900 * The `mousedown` or `touchdown` event that caused this to run.
6902 * @listens mousedown
6903 * @listens touchdown
6907 VolumeMenuButton.prototype.handleMouseDown = function handleMouseDown(event) {
6908 this.on(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
6909 this.on(this.el_.ownerDocument, ['mouseup', 'touchend'], this.handleMouseUp);
6913 * Handle the `mouseup` and `touchend` events on the `VolumeBar`
6915 * @param {EventTarget~Event} [event]
6916 * The `mouseup` or `touchend` event that caused this to run.
6923 VolumeMenuButton.prototype.handleMouseUp = function handleMouseUp(event) {
6924 this.off(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove));
6927 return VolumeMenuButton;
6928 }(_popupButton2['default']);
6931 * @borrows MuteToggle#update as VolumeMenuButton#volumeUpdate
6935 VolumeMenuButton.prototype.volumeUpdate = _muteToggle2['default'].prototype.update;
6938 * The text that should display over the `VolumeMenuButton`s controls. Added for localization.
6943 VolumeMenuButton.prototype.controlText_ = 'Mute';
6945 _component2['default'].registerComponent('VolumeMenuButton', VolumeMenuButton);
6946 exports['default'] = VolumeMenuButton;
6948 },{"11":11,"37":37,"5":5,"53":53,"54":54,"83":83}],41:[function(_dereq_,module,exports){
6951 exports.__esModule = true;
6953 var _component = _dereq_(5);
6955 var _component2 = _interopRequireDefault(_component);
6957 var _modalDialog = _dereq_(50);
6959 var _modalDialog2 = _interopRequireDefault(_modalDialog);
6961 var _mergeOptions = _dereq_(87);
6963 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
6965 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6967 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
6969 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
6971 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
6972 * @file error-display.js
6977 * A display that indicates an error has occurred. This means that the video
6980 * @extends ModalDialog
6982 var ErrorDisplay = function (_ModalDialog) {
6983 _inherits(ErrorDisplay, _ModalDialog);
6986 * Creates an instance of this class.
6988 * @param {Player} player
6989 * The `Player` that this class should be attached to.
6991 * @param {Object} [options]
6992 * The key/value store of player options.
6994 function ErrorDisplay(player, options) {
6995 _classCallCheck(this, ErrorDisplay);
6997 var _this = _possibleConstructorReturn(this, _ModalDialog.call(this, player, options));
6999 _this.on(player, 'error', _this.open);
7004 * Builds the default DOM `className`.
7007 * The DOM `className` for this object.
7009 * @deprecated Since version 5.
7013 ErrorDisplay.prototype.buildCSSClass = function buildCSSClass() {
7014 return 'vjs-error-display ' + _ModalDialog.prototype.buildCSSClass.call(this);
7018 * Gets the localized error message based on the `Player`s error.
7021 * The `Player`s error message localized or an empty string.
7025 ErrorDisplay.prototype.content = function content() {
7026 var error = this.player().error();
7028 return error ? this.localize(error.message) : '';
7031 return ErrorDisplay;
7032 }(_modalDialog2['default']);
7035 * The default options for an `ErrorDisplay`.
7041 ErrorDisplay.prototype.options_ = (0, _mergeOptions2['default'])(_modalDialog2['default'].prototype.options_, {
7047 _component2['default'].registerComponent('ErrorDisplay', ErrorDisplay);
7048 exports['default'] = ErrorDisplay;
7050 },{"5":5,"50":50,"87":87}],42:[function(_dereq_,module,exports){
7053 exports.__esModule = true;
7055 var _events = _dereq_(82);
7057 var Events = _interopRequireWildcard(_events);
7059 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7062 * `EventTarget` is a class that can have the same API as the DOM `EventTarget`. It
7063 * adds shorthand functions that wrap around lengthy functions. For example:
7064 * the `on` function is a wrapper around `addEventListener`.
7066 * @see [EventTarget Spec]{@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget}
7067 * @class EventTarget
7069 var EventTarget = function EventTarget() {};
7072 * A Custom DOM event.
7074 * @typedef {Object} EventTarget~Event
7075 * @see [Properties]{@link https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent}
7079 * All event listeners should follow the following format.
7081 * @callback EventTarget~EventListener
7082 * @this {EventTarget}
7084 * @param {EventTarget~Event} event
7085 * the event that triggered this function
7087 * @param {Object} [hash]
7088 * hash of data sent during the event
7092 * An object containing event names as keys and booleans as values.
7094 * > NOTE: If an event name is set to a true value here {@link EventTarget#trigger}
7095 * will have extra functionality. See that function for more information.
7097 * @property EventTarget.prototype.allowedEvents_
7101 * @file src/js/event-target.js
7103 EventTarget.prototype.allowedEvents_ = {};
7106 * Adds an `event listener` to an instance of an `EventTarget`. An `event listener` is a
7107 * function that will get called when an event with a certain name gets triggered.
7109 * @param {string|string[]} type
7110 * An event name or an array of event names.
7112 * @param {EventTarget~EventListener} fn
7113 * The function to call with `EventTarget`s
7115 EventTarget.prototype.on = function (type, fn) {
7116 // Remove the addEventListener alias before calling Events.on
7117 // so we don't get into an infinite type loop
7118 var ael = this.addEventListener;
7120 this.addEventListener = function () {};
7121 Events.on(this, type, fn);
7122 this.addEventListener = ael;
7126 * An alias of {@link EventTarget#on}. Allows `EventTarget` to mimic
7127 * the standard DOM API.
7130 * @see {@link EventTarget#on}
7132 EventTarget.prototype.addEventListener = EventTarget.prototype.on;
7135 * Removes an `event listener` for a specific event from an instance of `EventTarget`.
7136 * This makes it so that the `event listener` will no longer get called when the
7137 * named event happens.
7139 * @param {string|string[]} type
7140 * An event name or an array of event names.
7142 * @param {EventTarget~EventListener} fn
7143 * The function to remove.
7145 EventTarget.prototype.off = function (type, fn) {
7146 Events.off(this, type, fn);
7150 * An alias of {@link EventTarget#off}. Allows `EventTarget` to mimic
7151 * the standard DOM API.
7154 * @see {@link EventTarget#off}
7156 EventTarget.prototype.removeEventListener = EventTarget.prototype.off;
7159 * This function will add an `event listener` that gets triggered only once. After the
7160 * first trigger it will get removed. This is like adding an `event listener`
7161 * with {@link EventTarget#on} that calls {@link EventTarget#off} on itself.
7163 * @param {string|string[]} type
7164 * An event name or an array of event names.
7166 * @param {EventTarget~EventListener} fn
7167 * The function to be called once for each event name.
7169 EventTarget.prototype.one = function (type, fn) {
7170 // Remove the addEventListener alialing Events.on
7171 // so we don't get into an infinite type loop
7172 var ael = this.addEventListener;
7174 this.addEventListener = function () {};
7175 Events.one(this, type, fn);
7176 this.addEventListener = ael;
7180 * This function causes an event to happen. This will then cause any `event listeners`
7181 * that are waiting for that event, to get called. If there are no `event listeners`
7182 * for an event then nothing will happen.
7184 * If the name of the `Event` that is being triggered is in `EventTarget.allowedEvents_`.
7185 * Trigger will also call the `on` + `uppercaseEventName` function.
7188 * 'click' is in `EventTarget.allowedEvents_`, so, trigger will attempt to call
7189 * `onClick` if it exists.
7191 * @param {string|EventTarget~Event|Object} event
7192 * The name of the event, an `Event`, or an object with a key of type set to
7195 EventTarget.prototype.trigger = function (event) {
7196 var type = event.type || event;
7198 if (typeof event === 'string') {
7199 event = { type: type };
7201 event = Events.fixEvent(event);
7203 if (this.allowedEvents_[type] && this['on' + type]) {
7204 this['on' + type](event);
7207 Events.trigger(this, event);
7211 * An alias of {@link EventTarget#trigger}. Allows `EventTarget` to mimic
7212 * the standard DOM API.
7215 * @see {@link EventTarget#trigger}
7217 EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger;
7219 exports['default'] = EventTarget;
7221 },{"82":82}],43:[function(_dereq_,module,exports){
7224 exports.__esModule = true;
7226 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
7228 var _log = _dereq_(86);
7230 var _log2 = _interopRequireDefault(_log);
7232 var _obj = _dereq_(88);
7234 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7242 * A combination of node inherits and babel's inherits (after transpile).
7243 * Both work the same but node adds `super_` to the subClass
7244 * and Babel adds the superClass as __proto__. Both seem useful.
7246 * @param {Object} subClass
7247 * The class to inherit to
7249 * @param {Object} superClass
7250 * The class to inherit from
7254 var _inherits = function _inherits(subClass, superClass) {
7255 if (typeof superClass !== 'function' && superClass !== null) {
7256 throw new TypeError('Super expression must either be null or a function, not ' + (typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass)));
7259 subClass.prototype = Object.create(superClass && superClass.prototype, {
7270 subClass.super_ = superClass;
7275 * Function for subclassing using the same inheritance that
7276 * videojs uses internally
7278 * @param {Object} superClass
7279 * The class to inherit from
7281 * @param {Object} [subClassMethods={}]
7282 * The class to inherit to
7285 * The new object with subClassMethods that inherited superClass.
7287 var extendFn = function extendFn(superClass) {
7288 var subClassMethods = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7290 var subClass = function subClass() {
7291 superClass.apply(this, arguments);
7296 if ((0, _obj.isObject)(subClassMethods)) {
7297 if (typeof subClassMethods.init === 'function') {
7298 _log2['default'].warn('Constructor logic via init() is deprecated; please use constructor() instead.');
7299 subClassMethods.constructor = subClassMethods.init;
7301 if (subClassMethods.constructor !== Object.prototype.constructor) {
7302 subClass = subClassMethods.constructor;
7304 methods = subClassMethods;
7305 } else if (typeof subClassMethods === 'function') {
7306 subClass = subClassMethods;
7309 _inherits(subClass, superClass);
7311 // Extend subObj's prototype with functions and other properties from props
7312 for (var name in methods) {
7313 if (methods.hasOwnProperty(name)) {
7314 subClass.prototype[name] = methods[name];
7321 exports['default'] = extendFn;
7323 },{"86":86,"88":88}],44:[function(_dereq_,module,exports){
7326 exports.__esModule = true;
7328 var _document = _dereq_(94);
7330 var _document2 = _interopRequireDefault(_document);
7332 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7335 * Store the browser-specific methods for the fullscreen API.
7338 * @see [Specification]{@link https://fullscreen.spec.whatwg.org}
7339 * @see [Map Approach From Screenfull.js]{@link https://github.com/sindresorhus/screenfull.js}
7341 var FullscreenApi = {};
7343 // browser API methods
7345 * @file fullscreen-api.js
7346 * @module fullscreen-api
7349 var apiMap = [['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'],
7351 ['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'],
7352 // Old WebKit (Safari 5.1)
7353 ['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'],
7355 ['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'],
7357 ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']];
7359 var specApi = apiMap[0];
7360 var browserApi = void 0;
7362 // determine the supported set of functions
7363 for (var i = 0; i < apiMap.length; i++) {
7364 // check for exitFullscreen function
7365 if (apiMap[i][1] in _document2['default']) {
7366 browserApi = apiMap[i];
7371 // map the browser API names to the spec API names
7373 for (var _i = 0; _i < browserApi.length; _i++) {
7374 FullscreenApi[specApi[_i]] = browserApi[_i];
7378 exports['default'] = FullscreenApi;
7380 },{"94":94}],45:[function(_dereq_,module,exports){
7383 exports.__esModule = true;
7385 var _component = _dereq_(5);
7387 var _component2 = _interopRequireDefault(_component);
7389 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7391 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
7393 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
7395 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
7396 * @file loading-spinner.js
7401 * A loading spinner for use during waiting/loading events.
7403 * @extends Component
7405 var LoadingSpinner = function (_Component) {
7406 _inherits(LoadingSpinner, _Component);
7408 function LoadingSpinner() {
7409 _classCallCheck(this, LoadingSpinner);
7411 return _possibleConstructorReturn(this, _Component.apply(this, arguments));
7415 * Create the `LoadingSpinner`s DOM element.
7418 * The dom element that gets created.
7420 LoadingSpinner.prototype.createEl = function createEl() {
7421 return _Component.prototype.createEl.call(this, 'div', {
7422 className: 'vjs-loading-spinner',
7427 return LoadingSpinner;
7428 }(_component2['default']);
7430 _component2['default'].registerComponent('LoadingSpinner', LoadingSpinner);
7431 exports['default'] = LoadingSpinner;
7433 },{"5":5}],46:[function(_dereq_,module,exports){
7436 exports.__esModule = true;
7438 var _obj = _dereq_(88);
7441 * A Custom `MediaError` class which mimics the standard HTML5 `MediaError` class.
7443 * @param {number|string|Object|MediaError} value
7444 * This can be of multiple types:
7445 * - number: should be a standard error code
7446 * - string: an error message (the code will be 0)
7447 * - Object: arbitrary properties
7448 * - `MediaError` (native): used to populate a video.js `MediaError` object
7449 * - `MediaError` (video.js): will return itself if it's already a
7450 * video.js `MediaError` object.
7452 * @see [MediaError Spec]{@link https://dev.w3.org/html5/spec-author-view/video.html#mediaerror}
7453 * @see [Encrypted MediaError Spec]{@link https://www.w3.org/TR/2013/WD-encrypted-media-20130510/#error-codes}
7457 function MediaError(value) {
7459 // Allow redundant calls to this constructor to avoid having `instanceof`
7460 // checks peppered around the code.
7461 if (value instanceof MediaError) {
7465 if (typeof value === 'number') {
7467 } else if (typeof value === 'string') {
7468 // default code is zero, so this is a custom error
7469 this.message = value;
7470 } else if ((0, _obj.isObject)(value)) {
7472 // We assign the `code` property manually because native `MediaError` objects
7473 // do not expose it as an own/enumerable property of the object.
7474 if (typeof value.code === 'number') {
7475 this.code = value.code;
7478 (0, _obj.assign)(this, value);
7481 if (!this.message) {
7482 this.message = MediaError.defaultMessages[this.code] || '';
7487 * The error code that refers two one of the defined `MediaError` types
7492 * @file media-error.js
7494 MediaError.prototype.code = 0;
7497 * An optional message that to show with the error. Message is not part of the HTML5
7498 * video spec but allows for more informative custom errors.
7502 MediaError.prototype.message = '';
7505 * An optional status code that can be set by plugins to allow even more detail about
7506 * the error. For example a plugin might provide a specific HTTP status code and an
7507 * error message for that code. Then when the plugin gets that error this class will
7508 * know how to display an error message for it. This allows a custom message to show
7509 * up on the `Player` error overlay.
7513 MediaError.prototype.status = null;
7516 * Errors indexed by the W3C standard. The order **CANNOT CHANGE**! See the
7517 * specification listed under {@link MediaError} for more information.
7521 * @property {string} 0 - MEDIA_ERR_CUSTOM
7522 * @property {string} 1 - MEDIA_ERR_CUSTOM
7523 * @property {string} 2 - MEDIA_ERR_ABORTED
7524 * @property {string} 3 - MEDIA_ERR_NETWORK
7525 * @property {string} 4 - MEDIA_ERR_SRC_NOT_SUPPORTED
7526 * @property {string} 5 - MEDIA_ERR_ENCRYPTED
7528 MediaError.errorTypes = ['MEDIA_ERR_CUSTOM', 'MEDIA_ERR_ABORTED', 'MEDIA_ERR_NETWORK', 'MEDIA_ERR_DECODE', 'MEDIA_ERR_SRC_NOT_SUPPORTED', 'MEDIA_ERR_ENCRYPTED'];
7531 * The default `MediaError` messages based on the {@link MediaError.errorTypes}.
7536 MediaError.defaultMessages = {
7537 1: 'You aborted the media playback',
7538 2: 'A network error caused the media download to fail part-way.',
7539 3: 'The media playback was aborted due to a corruption problem or because the media used features your browser did not support.',
7540 4: 'The media could not be loaded, either because the server or network failed or because the format is not supported.',
7541 5: 'The media is encrypted and we do not have the keys to decrypt it.'
7544 // Add types as properties on MediaError
7545 // e.g. MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
7546 for (var errNum = 0; errNum < MediaError.errorTypes.length; errNum++) {
7547 MediaError[MediaError.errorTypes[errNum]] = errNum;
7548 // values should be accessible on both the class and instance
7549 MediaError.prototype[MediaError.errorTypes[errNum]] = errNum;
7552 // jsdocs for instance/static members added above
7553 // instance methods use `#` and static methods use `.`
7555 * W3C error code for any custom error.
7557 * @member MediaError#MEDIA_ERR_CUSTOM
7558 * @constant {number}
7562 * W3C error code for any custom error.
7564 * @member MediaError.MEDIA_ERR_CUSTOM
7565 * @constant {number}
7570 * W3C error code for media error aborted.
7572 * @member MediaError#MEDIA_ERR_ABORTED
7573 * @constant {number}
7577 * W3C error code for media error aborted.
7579 * @member MediaError.MEDIA_ERR_ABORTED
7580 * @constant {number}
7585 * W3C error code for any network error.
7587 * @member MediaError#MEDIA_ERR_NETWORK
7588 * @constant {number}
7592 * W3C error code for any network error.
7594 * @member MediaError.MEDIA_ERR_NETWORK
7595 * @constant {number}
7600 * W3C error code for any decoding error.
7602 * @member MediaError#MEDIA_ERR_DECODE
7603 * @constant {number}
7607 * W3C error code for any decoding error.
7609 * @member MediaError.MEDIA_ERR_DECODE
7610 * @constant {number}
7615 * W3C error code for any time that a source is not supported.
7617 * @member MediaError#MEDIA_ERR_SRC_NOT_SUPPORTED
7618 * @constant {number}
7622 * W3C error code for any time that a source is not supported.
7624 * @member MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED
7625 * @constant {number}
7630 * W3C error code for any time that a source is encrypted.
7632 * @member MediaError#MEDIA_ERR_ENCRYPTED
7633 * @constant {number}
7637 * W3C error code for any time that a source is encrypted.
7639 * @member MediaError.MEDIA_ERR_ENCRYPTED
7640 * @constant {number}
7644 exports['default'] = MediaError;
7646 },{"88":88}],47:[function(_dereq_,module,exports){
7649 exports.__esModule = true;
7651 var _clickableComponent = _dereq_(3);
7653 var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
7655 var _component = _dereq_(5);
7657 var _component2 = _interopRequireDefault(_component);
7659 var _menu = _dereq_(49);
7661 var _menu2 = _interopRequireDefault(_menu);
7663 var _dom = _dereq_(81);
7665 var Dom = _interopRequireWildcard(_dom);
7667 var _fn = _dereq_(83);
7669 var Fn = _interopRequireWildcard(_fn);
7671 var _toTitleCase = _dereq_(91);
7673 var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
7675 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
7677 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
7679 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
7681 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
7683 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
7684 * @file menu-button.js
7689 * A `MenuButton` class for any popup {@link Menu}.
7691 * @extends ClickableComponent
7693 var MenuButton = function (_ClickableComponent) {
7694 _inherits(MenuButton, _ClickableComponent);
7697 * Creates an instance of this class.
7699 * @param {Player} player
7700 * The `Player` that this class should be attached to.
7702 * @param {Object} [options={}]
7703 * The key/value store of player options.
7705 function MenuButton(player) {
7706 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7708 _classCallCheck(this, MenuButton);
7710 var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
7714 _this.enabled_ = true;
7716 _this.el_.setAttribute('aria-haspopup', 'true');
7717 _this.el_.setAttribute('role', 'menuitem');
7718 _this.on('keydown', _this.handleSubmenuKeyPress);
7723 * Update the menu based on the current state of its items.
7727 MenuButton.prototype.update = function update() {
7728 var menu = this.createMenu();
7731 this.removeChild(this.menu);
7735 this.addChild(menu);
7738 * Track the state of the menu button
7743 this.buttonPressed_ = false;
7744 this.el_.setAttribute('aria-expanded', 'false');
7746 if (this.items && this.items.length === 0) {
7748 } else if (this.items && this.items.length > 1) {
7754 * Create the menu and add all items to it.
7757 * The constructed menu
7761 MenuButton.prototype.createMenu = function createMenu() {
7762 var menu = new _menu2['default'](this.player_);
7764 // Add a title list item to the top
7765 if (this.options_.title) {
7766 var title = Dom.createEl('li', {
7767 className: 'vjs-menu-title',
7768 innerHTML: (0, _toTitleCase2['default'])(this.options_.title),
7772 menu.children_.unshift(title);
7773 Dom.insertElFirst(title, menu.contentEl());
7776 this.items = this.createItems();
7779 // Add menu items to the menu
7780 for (var i = 0; i < this.items.length; i++) {
7781 menu.addItem(this.items[i]);
7789 * Create the list of menu items. Specific to each subclass.
7795 MenuButton.prototype.createItems = function createItems() {};
7798 * Create the `MenuButtons`s DOM element.
7801 * The element that gets created.
7805 MenuButton.prototype.createEl = function createEl() {
7806 return _ClickableComponent.prototype.createEl.call(this, 'div', {
7807 className: this.buildCSSClass()
7812 * Builds the default DOM `className`.
7815 * The DOM `className` for this object.
7819 MenuButton.prototype.buildCSSClass = function buildCSSClass() {
7820 var menuButtonClass = 'vjs-menu-button';
7822 // If the inline option is passed, we want to use different styles altogether.
7823 if (this.options_.inline === true) {
7824 menuButtonClass += '-inline';
7826 menuButtonClass += '-popup';
7829 return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this);
7833 * Handle a click on a `MenuButton`.
7834 * See {@link ClickableComponent#handleClick} for instances where this is called.
7836 * @param {EventTarget~Event} event
7837 * The `keydown`, `tap`, or `click` event that caused this function to be
7845 MenuButton.prototype.handleClick = function handleClick(event) {
7846 // When you click the button it adds focus, which will show the menu.
7847 // So we'll remove focus when the mouse leaves the button. Focus is needed
7848 // for tab navigation.
7850 this.one(this.menu.contentEl(), 'mouseleave', Fn.bind(this, function (e) {
7851 this.unpressButton();
7854 if (this.buttonPressed_) {
7855 this.unpressButton();
7862 * Handle tab, escape, down arrow, and up arrow keys for `MenuButton`. See
7863 * {@link ClickableComponent#handleKeyPress} for instances where this is called.
7865 * @param {EventTarget~Event} event
7866 * The `keydown` event that caused this function to be called.
7872 MenuButton.prototype.handleKeyPress = function handleKeyPress(event) {
7874 // Escape (27) key or Tab (9) key unpress the 'button'
7875 if (event.which === 27 || event.which === 9) {
7876 if (this.buttonPressed_) {
7877 this.unpressButton();
7879 // Don't preventDefault for Tab key - we still want to lose focus
7880 if (event.which !== 9) {
7881 event.preventDefault();
7883 // Up (38) key or Down (40) key press the 'button'
7884 } else if (event.which === 38 || event.which === 40) {
7885 if (!this.buttonPressed_) {
7887 event.preventDefault();
7890 _ClickableComponent.prototype.handleKeyPress.call(this, event);
7895 * Handle a `keydown` event on a sub-menu. The listener for this is added in
7898 * @param {EventTarget~Event} event
7905 MenuButton.prototype.handleSubmenuKeyPress = function handleSubmenuKeyPress(event) {
7907 // Escape (27) key or Tab (9) key unpress the 'button'
7908 if (event.which === 27 || event.which === 9) {
7909 if (this.buttonPressed_) {
7910 this.unpressButton();
7912 // Don't preventDefault for Tab key - we still want to lose focus
7913 if (event.which !== 9) {
7914 event.preventDefault();
7920 * Put the current `MenuButton` into a pressed state.
7924 MenuButton.prototype.pressButton = function pressButton() {
7925 if (this.enabled_) {
7926 this.buttonPressed_ = true;
7927 this.menu.lockShowing();
7928 this.el_.setAttribute('aria-expanded', 'true');
7929 // set the focus into the submenu
7935 * Take the current `MenuButton` out of a pressed state.
7939 MenuButton.prototype.unpressButton = function unpressButton() {
7940 if (this.enabled_) {
7941 this.buttonPressed_ = false;
7942 this.menu.unlockShowing();
7943 this.el_.setAttribute('aria-expanded', 'false');
7944 // Set focus back to this menu button
7950 * Disable the `MenuButton`. Don't allow it to be clicked.
7952 * @return {MenuButton}
7953 * Returns itself; method can be chained.
7957 MenuButton.prototype.disable = function disable() {
7958 // Unpress, but don't force focus on this button
7959 this.buttonPressed_ = false;
7960 this.menu.unlockShowing();
7961 this.el_.setAttribute('aria-expanded', 'false');
7963 this.enabled_ = false;
7965 return _ClickableComponent.prototype.disable.call(this);
7969 * Enable the `MenuButton`. Allow it to be clicked.
7971 * @return {MenuButton}
7972 * Returns itself; method can be chained.
7976 MenuButton.prototype.enable = function enable() {
7977 this.enabled_ = true;
7979 return _ClickableComponent.prototype.enable.call(this);
7983 }(_clickableComponent2['default']);
7985 _component2['default'].registerComponent('MenuButton', MenuButton);
7986 exports['default'] = MenuButton;
7988 },{"3":3,"49":49,"5":5,"81":81,"83":83,"91":91}],48:[function(_dereq_,module,exports){
7991 exports.__esModule = true;
7993 var _clickableComponent = _dereq_(3);
7995 var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
7997 var _component = _dereq_(5);
7999 var _component2 = _interopRequireDefault(_component);
8001 var _obj = _dereq_(88);
8003 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8005 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8007 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
8009 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
8010 * @file menu-item.js
8015 * The component for a menu item. `<li>`
8017 * @extends ClickableComponent
8019 var MenuItem = function (_ClickableComponent) {
8020 _inherits(MenuItem, _ClickableComponent);
8023 * Creates an instance of the this class.
8025 * @param {Player} player
8026 * The `Player` that this class should be attached to.
8028 * @param {Object} [options={}]
8029 * The key/value store of player options.
8032 function MenuItem(player, options) {
8033 _classCallCheck(this, MenuItem);
8035 var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
8037 _this.selectable = options.selectable;
8039 _this.selected(options.selected);
8041 if (_this.selectable) {
8042 // TODO: May need to be either menuitemcheckbox or menuitemradio,
8043 // and may need logical grouping of menu items.
8044 _this.el_.setAttribute('role', 'menuitemcheckbox');
8046 _this.el_.setAttribute('role', 'menuitem');
8052 * Create the `MenuItem's DOM element
8054 * @param {string} [type=li]
8055 * Element's node type, not actually used, always set to `li`.
8057 * @param {Object} [props={}]
8058 * An object of properties that should be set on the element
8060 * @param {Object} [attrs={}]
8061 * An object of attributes that should be set on the element
8064 * The element that gets created.
8068 MenuItem.prototype.createEl = function createEl(type, props, attrs) {
8069 return _ClickableComponent.prototype.createEl.call(this, 'li', (0, _obj.assign)({
8070 className: 'vjs-menu-item',
8071 innerHTML: this.localize(this.options_.label),
8077 * Any click on a `MenuItem` puts int into the selected state.
8078 * See {@link ClickableComponent#handleClick} for instances where this is called.
8080 * @param {EventTarget~Event} event
8081 * The `keydown`, `tap`, or `click` event that caused this function to be
8089 MenuItem.prototype.handleClick = function handleClick(event) {
8090 this.selected(true);
8094 * Set the state for this menu item as selected or not.
8096 * @param {boolean} selected
8097 * if the menu item is selected or not
8101 MenuItem.prototype.selected = function selected(_selected) {
8102 if (this.selectable) {
8104 this.addClass('vjs-selected');
8105 this.el_.setAttribute('aria-checked', 'true');
8106 // aria-checked isn't fully supported by browsers/screen readers,
8107 // so indicate selected state to screen reader in the control text.
8108 this.controlText(', selected');
8110 this.removeClass('vjs-selected');
8111 this.el_.setAttribute('aria-checked', 'false');
8112 // Indicate un-selected state to screen reader
8113 // Note that a space clears out the selected state text
8114 this.controlText(' ');
8120 }(_clickableComponent2['default']);
8122 _component2['default'].registerComponent('MenuItem', MenuItem);
8123 exports['default'] = MenuItem;
8125 },{"3":3,"5":5,"88":88}],49:[function(_dereq_,module,exports){
8128 exports.__esModule = true;
8130 var _component = _dereq_(5);
8132 var _component2 = _interopRequireDefault(_component);
8134 var _dom = _dereq_(81);
8136 var Dom = _interopRequireWildcard(_dom);
8138 var _fn = _dereq_(83);
8140 var Fn = _interopRequireWildcard(_fn);
8142 var _events = _dereq_(82);
8144 var Events = _interopRequireWildcard(_events);
8146 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
8148 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8150 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8152 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
8154 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
8160 * The Menu component is used to build popup menus, including subtitle and
8161 * captions selection menus.
8163 * @extends Component
8165 var Menu = function (_Component) {
8166 _inherits(Menu, _Component);
8169 * Create an instance of this class.
8171 * @param {Player} player
8172 * the player that this component should attach to
8174 * @param {Object} [options]
8175 * Object of option names and values
8178 function Menu(player, options) {
8179 _classCallCheck(this, Menu);
8181 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
8183 _this.focusedChild_ = -1;
8185 _this.on('keydown', _this.handleKeyPress);
8190 * Add a {@link MenuItem} to the menu.
8192 * @param {Object|string} component
8193 * The name or instance of the `MenuItem` to add.
8198 Menu.prototype.addItem = function addItem(component) {
8199 this.addChild(component);
8200 component.on('click', Fn.bind(this, function (event) {
8201 this.unlockShowing();
8202 // TODO: Need to set keyboard focus back to the menuButton
8207 * Create the `Menu`s DOM element.
8210 * the element that was created
8214 Menu.prototype.createEl = function createEl() {
8215 var contentElType = this.options_.contentElType || 'ul';
8217 this.contentEl_ = Dom.createEl(contentElType, {
8218 className: 'vjs-menu-content'
8221 this.contentEl_.setAttribute('role', 'menu');
8223 var el = _Component.prototype.createEl.call(this, 'div', {
8224 append: this.contentEl_,
8225 className: 'vjs-menu'
8228 el.setAttribute('role', 'presentation');
8229 el.appendChild(this.contentEl_);
8231 // Prevent clicks from bubbling up. Needed for Menu Buttons,
8232 // where a click on the parent is significant
8233 Events.on(el, 'click', function (event) {
8234 event.preventDefault();
8235 event.stopImmediatePropagation();
8242 * Handle a `keydown` event on this menu. This listener is added in the constructor.
8244 * @param {EventTarget~Event} event
8245 * A `keydown` event that happened on the menu.
8251 Menu.prototype.handleKeyPress = function handleKeyPress(event) {
8252 // Left and Down Arrows
8253 if (event.which === 37 || event.which === 40) {
8254 event.preventDefault();
8257 // Up and Right Arrows
8258 } else if (event.which === 38 || event.which === 39) {
8259 event.preventDefault();
8265 * Move to next (lower) menu item for keyboard users.
8269 Menu.prototype.stepForward = function stepForward() {
8272 if (this.focusedChild_ !== undefined) {
8273 stepChild = this.focusedChild_ + 1;
8275 this.focus(stepChild);
8279 * Move to previous (higher) menu item for keyboard users.
8283 Menu.prototype.stepBack = function stepBack() {
8286 if (this.focusedChild_ !== undefined) {
8287 stepChild = this.focusedChild_ - 1;
8289 this.focus(stepChild);
8293 * Set focus on a {@link MenuItem} in the `Menu`.
8295 * @param {Object|string} [item=0]
8296 * Index of child item set focus on.
8300 Menu.prototype.focus = function focus() {
8301 var item = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
8303 var children = this.children().slice();
8304 var haveTitle = children.length && children[0].className && /vjs-menu-title/.test(children[0].className);
8310 if (children.length > 0) {
8313 } else if (item >= children.length) {
8314 item = children.length - 1;
8317 this.focusedChild_ = item;
8319 children[item].el_.focus();
8324 }(_component2['default']);
8326 _component2['default'].registerComponent('Menu', Menu);
8327 exports['default'] = Menu;
8329 },{"5":5,"81":81,"82":82,"83":83}],50:[function(_dereq_,module,exports){
8332 exports.__esModule = true;
8334 var _dom = _dereq_(81);
8336 var Dom = _interopRequireWildcard(_dom);
8338 var _fn = _dereq_(83);
8340 var Fn = _interopRequireWildcard(_fn);
8342 var _component = _dereq_(5);
8344 var _component2 = _interopRequireDefault(_component);
8346 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8348 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
8350 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8352 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
8354 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
8355 * @file modal-dialog.js
8359 var MODAL_CLASS_NAME = 'vjs-modal-dialog';
8363 * The `ModalDialog` displays over the video and its controls, which blocks
8364 * interaction with the player until it is closed.
8366 * Modal dialogs include a "Close" button and will close when that button
8367 * is activated - or when ESC is pressed anywhere.
8369 * @extends Component
8372 var ModalDialog = function (_Component) {
8373 _inherits(ModalDialog, _Component);
8376 * Create an instance of this class.
8378 * @param {Player} player
8379 * The `Player` that this class should be attached to.
8381 * @param {Object} [options]
8382 * The key/value store of player options.
8384 * @param {Mixed} [options.content=undefined]
8385 * Provide customized content for this modal.
8387 * @param {string} [options.description]
8388 * A text description for the modal, primarily for accessibility.
8390 * @param {boolean} [options.fillAlways=false]
8391 * Normally, modals are automatically filled only the first time
8392 * they open. This tells the modal to refresh its content
8393 * every time it opens.
8395 * @param {string} [options.label]
8396 * A text label for the modal, primarily for accessibility.
8398 * @param {boolean} [options.temporary=true]
8399 * If `true`, the modal can only be opened once; it will be
8400 * disposed as soon as it's closed.
8402 * @param {boolean} [options.uncloseable=false]
8403 * If `true`, the user will not be able to close the modal
8404 * through the UI in the normal ways. Programmatic closing is
8407 function ModalDialog(player, options) {
8408 _classCallCheck(this, ModalDialog);
8410 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
8412 _this.opened_ = _this.hasBeenOpened_ = _this.hasBeenFilled_ = false;
8414 _this.closeable(!_this.options_.uncloseable);
8415 _this.content(_this.options_.content);
8417 // Make sure the contentEl is defined AFTER any children are initialized
8418 // because we only want the contents of the modal in the contentEl
8419 // (not the UI elements like the close button).
8420 _this.contentEl_ = Dom.createEl('div', {
8421 className: MODAL_CLASS_NAME + '-content'
8426 _this.descEl_ = Dom.createEl('p', {
8427 className: MODAL_CLASS_NAME + '-description vjs-offscreen',
8428 id: _this.el().getAttribute('aria-describedby')
8431 Dom.textContent(_this.descEl_, _this.description());
8432 _this.el_.appendChild(_this.descEl_);
8433 _this.el_.appendChild(_this.contentEl_);
8438 * Create the `ModalDialog`'s DOM element
8441 * The DOM element that gets created.
8445 ModalDialog.prototype.createEl = function createEl() {
8446 return _Component.prototype.createEl.call(this, 'div', {
8447 className: this.buildCSSClass(),
8450 'aria-describedby': this.id() + '_description',
8451 'aria-hidden': 'true',
8452 'aria-label': this.label(),
8458 * Builds the default DOM `className`.
8461 * The DOM `className` for this object.
8465 ModalDialog.prototype.buildCSSClass = function buildCSSClass() {
8466 return MODAL_CLASS_NAME + ' vjs-hidden ' + _Component.prototype.buildCSSClass.call(this);
8470 * Handles `keydown` events on the document, looking for ESC, which closes
8473 * @param {EventTarget~Event} e
8474 * The keypress that triggered this event.
8480 ModalDialog.prototype.handleKeyPress = function handleKeyPress(e) {
8481 if (e.which === ESC && this.closeable()) {
8487 * Returns the label string for this modal. Primarily used for accessibility.
8490 * the localized or raw label of this modal.
8494 ModalDialog.prototype.label = function label() {
8495 return this.options_.label || this.localize('Modal Window');
8499 * Returns the description string for this modal. Primarily used for
8503 * The localized or raw description of this modal.
8507 ModalDialog.prototype.description = function description() {
8508 var desc = this.options_.description || this.localize('This is a modal window.');
8510 // Append a universal closeability message if the modal is closeable.
8511 if (this.closeable()) {
8512 desc += ' ' + this.localize('This modal can be closed by pressing the Escape key or activating the close button.');
8521 * @fires ModalDialog#beforemodalopen
8522 * @fires ModalDialog#modalopen
8524 * @return {ModalDialog}
8525 * Returns itself; method can be chained.
8529 ModalDialog.prototype.open = function open() {
8530 if (!this.opened_) {
8531 var player = this.player();
8534 * Fired just before a `ModalDialog` is opened.
8536 * @event ModalDialog#beforemodalopen
8537 * @type {EventTarget~Event}
8539 this.trigger('beforemodalopen');
8540 this.opened_ = true;
8542 // Fill content if the modal has never opened before and
8543 // never been filled.
8544 if (this.options_.fillAlways || !this.hasBeenOpened_ && !this.hasBeenFilled_) {
8548 // If the player was playing, pause it and take note of its previously
8550 this.wasPlaying_ = !player.paused();
8552 if (this.wasPlaying_) {
8556 if (this.closeable()) {
8557 this.on(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress));
8560 player.controls(false);
8562 this.el().setAttribute('aria-hidden', 'false');
8565 * Fired just after a `ModalDialog` is opened.
8567 * @event ModalDialog#modalopen
8568 * @type {EventTarget~Event}
8570 this.trigger('modalopen');
8571 this.hasBeenOpened_ = true;
8577 * If the `ModalDialog` is currently open or closed.
8579 * @param {boolean} [value]
8580 * If given, it will open (`true`) or close (`false`) the modal.
8583 * the current open state of the modaldialog
8587 ModalDialog.prototype.opened = function opened(value) {
8588 if (typeof value === 'boolean') {
8589 this[value ? 'open' : 'close']();
8591 return this.opened_;
8595 * Closes the modal, does nothing if the `ModalDialog` is
8598 * @fires ModalDialog#beforemodalclose
8599 * @fires ModalDialog#modalclose
8601 * @return {ModalDialog}
8602 * Returns itself; method can be chained.
8606 ModalDialog.prototype.close = function close() {
8608 var player = this.player();
8611 * Fired just before a `ModalDialog` is closed.
8613 * @event ModalDialog#beforemodalclose
8614 * @type {EventTarget~Event}
8616 this.trigger('beforemodalclose');
8617 this.opened_ = false;
8619 if (this.wasPlaying_) {
8623 if (this.closeable()) {
8624 this.off(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress));
8627 player.controls(true);
8629 this.el().setAttribute('aria-hidden', 'true');
8632 * Fired just after a `ModalDialog` is closed.
8634 * @event ModalDialog#modalclose
8635 * @type {EventTarget~Event}
8637 this.trigger('modalclose');
8639 if (this.options_.temporary) {
8647 * Check to see if the `ModalDialog` is closeable via the UI.
8649 * @param {boolean} [value]
8650 * If given as a boolean, it will set the `closeable` option.
8653 * Returns the final value of the closable option.
8657 ModalDialog.prototype.closeable = function closeable(value) {
8658 if (typeof value === 'boolean') {
8659 var closeable = this.closeable_ = !!value;
8660 var close = this.getChild('closeButton');
8662 // If this is being made closeable and has no close button, add one.
8663 if (closeable && !close) {
8665 // The close button should be a child of the modal - not its
8666 // content element, so temporarily change the content element.
8667 var temp = this.contentEl_;
8669 this.contentEl_ = this.el_;
8670 close = this.addChild('closeButton', { controlText: 'Close Modal Dialog' });
8671 this.contentEl_ = temp;
8672 this.on(close, 'close', this.close);
8675 // If this is being made uncloseable and has a close button, remove it.
8676 if (!closeable && close) {
8677 this.off(close, 'close', this.close);
8678 this.removeChild(close);
8682 return this.closeable_;
8686 * Fill the modal's content element with the modal's "content" option.
8687 * The content element will be emptied before this change takes place.
8689 * @return {ModalDialog}
8690 * Returns itself; method can be chained.
8694 ModalDialog.prototype.fill = function fill() {
8695 return this.fillWith(this.content());
8699 * Fill the modal's content element with arbitrary content.
8700 * The content element will be emptied before this change takes place.
8702 * @fires ModalDialog#beforemodalfill
8703 * @fires ModalDialog#modalfill
8705 * @param {Mixed} [content]
8706 * The same rules apply to this as apply to the `content` option.
8708 * @return {ModalDialog}
8709 * Returns itself; method can be chained.
8713 ModalDialog.prototype.fillWith = function fillWith(content) {
8714 var contentEl = this.contentEl();
8715 var parentEl = contentEl.parentNode;
8716 var nextSiblingEl = contentEl.nextSibling;
8719 * Fired just before a `ModalDialog` is filled with content.
8721 * @event ModalDialog#beforemodalfill
8722 * @type {EventTarget~Event}
8724 this.trigger('beforemodalfill');
8725 this.hasBeenFilled_ = true;
8727 // Detach the content element from the DOM before performing
8728 // manipulation to avoid modifying the live DOM multiple times.
8729 parentEl.removeChild(contentEl);
8731 Dom.insertContent(contentEl, content);
8733 * Fired just after a `ModalDialog` is filled with content.
8735 * @event ModalDialog#modalfill
8736 * @type {EventTarget~Event}
8738 this.trigger('modalfill');
8740 // Re-inject the re-filled content element.
8741 if (nextSiblingEl) {
8742 parentEl.insertBefore(contentEl, nextSiblingEl);
8744 parentEl.appendChild(contentEl);
8751 * Empties the content element. This happens anytime the modal is filled.
8753 * @fires ModalDialog#beforemodalempty
8754 * @fires ModalDialog#modalempty
8756 * @return {ModalDialog}
8757 * Returns itself; method can be chained.
8761 ModalDialog.prototype.empty = function empty() {
8763 * Fired just before a `ModalDialog` is emptied.
8765 * @event ModalDialog#beforemodalempty
8766 * @type {EventTarget~Event}
8768 this.trigger('beforemodalempty');
8769 Dom.emptyEl(this.contentEl());
8772 * Fired just after a `ModalDialog` is emptied.
8774 * @event ModalDialog#modalempty
8775 * @type {EventTarget~Event}
8777 this.trigger('modalempty');
8782 * Gets or sets the modal content, which gets normalized before being
8783 * rendered into the DOM.
8785 * This does not update the DOM or fill the modal, but it is called during
8788 * @param {Mixed} [value]
8789 * If defined, sets the internal content value to be used on the
8790 * next call(s) to `fill`. This value is normalized before being
8791 * inserted. To "clear" the internal content value, pass `null`.
8794 * The current content of the modal dialog
8798 ModalDialog.prototype.content = function content(value) {
8799 if (typeof value !== 'undefined') {
8800 this.content_ = value;
8802 return this.content_;
8806 }(_component2['default']);
8809 * Default options for `ModalDialog` default options.
8816 ModalDialog.prototype.options_ = {
8820 _component2['default'].registerComponent('ModalDialog', ModalDialog);
8821 exports['default'] = ModalDialog;
8823 },{"5":5,"81":81,"83":83}],51:[function(_dereq_,module,exports){
8826 exports.__esModule = true;
8828 var _component = _dereq_(5);
8830 var _component2 = _interopRequireDefault(_component);
8832 var _document = _dereq_(94);
8834 var _document2 = _interopRequireDefault(_document);
8836 var _window = _dereq_(95);
8838 var _window2 = _interopRequireDefault(_window);
8840 var _events = _dereq_(82);
8842 var Events = _interopRequireWildcard(_events);
8844 var _dom = _dereq_(81);
8846 var Dom = _interopRequireWildcard(_dom);
8848 var _fn = _dereq_(83);
8850 var Fn = _interopRequireWildcard(_fn);
8852 var _guid = _dereq_(85);
8854 var Guid = _interopRequireWildcard(_guid);
8856 var _browser = _dereq_(78);
8858 var browser = _interopRequireWildcard(_browser);
8860 var _log = _dereq_(86);
8862 var _log2 = _interopRequireDefault(_log);
8864 var _toTitleCase = _dereq_(91);
8866 var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
8868 var _timeRanges = _dereq_(90);
8870 var _buffer = _dereq_(79);
8872 var _stylesheet = _dereq_(89);
8874 var stylesheet = _interopRequireWildcard(_stylesheet);
8876 var _fullscreenApi = _dereq_(44);
8878 var _fullscreenApi2 = _interopRequireDefault(_fullscreenApi);
8880 var _mediaError = _dereq_(46);
8882 var _mediaError2 = _interopRequireDefault(_mediaError);
8884 var _tuple = _dereq_(97);
8886 var _tuple2 = _interopRequireDefault(_tuple);
8888 var _obj = _dereq_(88);
8890 var _mergeOptions = _dereq_(87);
8892 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
8894 var _textTrackListConverter = _dereq_(69);
8896 var _textTrackListConverter2 = _interopRequireDefault(_textTrackListConverter);
8898 var _modalDialog = _dereq_(50);
8900 var _modalDialog2 = _interopRequireDefault(_modalDialog);
8902 var _tech = _dereq_(62);
8904 var _tech2 = _interopRequireDefault(_tech);
8906 var _audioTrackList = _dereq_(63);
8908 var _audioTrackList2 = _interopRequireDefault(_audioTrackList);
8910 var _videoTrackList = _dereq_(76);
8912 var _videoTrackList2 = _interopRequireDefault(_videoTrackList);
8936 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
8938 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
8940 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8942 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
8944 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
8947 // Subclasses Component
8950 // The following imports are used only to ensure that the corresponding modules
8951 // are always included in the video.js package. Importing the modules will
8952 // execute them and they will register themselves with video.js.
8955 // Import Html5 tech, at least for disposing the original video tag.
8958 // The following tech events are simply re-triggered
8959 // on the player when they happen
8960 var TECH_EVENTS_RETRIGGER = [
8962 * Fired while the user agent is downloading media data.
8964 * @event Player#progress
8965 * @type {EventTarget~Event}
8968 * Retrigger the `progress` event that was triggered by the {@link Tech}.
8971 * @method Player#handleTechProgress_
8972 * @fires Player#progress
8973 * @listens Tech#progress
8978 * Fires when the loading of an audio/video is aborted.
8980 * @event Player#abort
8981 * @type {EventTarget~Event}
8984 * Retrigger the `abort` event that was triggered by the {@link Tech}.
8987 * @method Player#handleTechAbort_
8988 * @fires Player#abort
8989 * @listens Tech#abort
8994 * Fires when the browser is intentionally not getting media data.
8996 * @event Player#suspend
8997 * @type {EventTarget~Event}
9000 * Retrigger the `suspend` event that was triggered by the {@link Tech}.
9003 * @method Player#handleTechSuspend_
9004 * @fires Player#suspend
9005 * @listens Tech#suspend
9010 * Fires when the current playlist is empty.
9012 * @event Player#emptied
9013 * @type {EventTarget~Event}
9016 * Retrigger the `emptied` event that was triggered by the {@link Tech}.
9019 * @method Player#handleTechEmptied_
9020 * @fires Player#emptied
9021 * @listens Tech#emptied
9025 * Fires when the browser is trying to get media data, but data is not available.
9027 * @event Player#stalled
9028 * @type {EventTarget~Event}
9031 * Retrigger the `stalled` event that was triggered by the {@link Tech}.
9034 * @method Player#handleTechStalled_
9035 * @fires Player#stalled
9036 * @listens Tech#stalled
9041 * Fires when the browser has loaded meta data for the audio/video.
9043 * @event Player#loadedmetadata
9044 * @type {EventTarget~Event}
9047 * Retrigger the `stalled` event that was triggered by the {@link Tech}.
9050 * @method Player#handleTechLoadedmetadata_
9051 * @fires Player#loadedmetadata
9052 * @listens Tech#loadedmetadata
9057 * Fires when the browser has loaded the current frame of the audio/video.
9059 * @event player#loadeddata
9063 * Retrigger the `loadeddata` event that was triggered by the {@link Tech}.
9066 * @method Player#handleTechLoaddeddata_
9067 * @fires Player#loadeddata
9068 * @listens Tech#loadeddata
9073 * Fires when the current playback position has changed.
9075 * @event player#timeupdate
9079 * Retrigger the `timeupdate` event that was triggered by the {@link Tech}.
9082 * @method Player#handleTechTimeUpdate_
9083 * @fires Player#timeupdate
9084 * @listens Tech#timeupdate
9089 * Fires when the playing speed of the audio/video is changed
9091 * @event player#ratechange
9095 * Retrigger the `ratechange` event that was triggered by the {@link Tech}.
9098 * @method Player#handleTechRatechange_
9099 * @fires Player#ratechange
9100 * @listens Tech#ratechange
9105 * Fires when the volume has been changed
9107 * @event player#volumechange
9111 * Retrigger the `volumechange` event that was triggered by the {@link Tech}.
9114 * @method Player#handleTechVolumechange_
9115 * @fires Player#volumechange
9116 * @listens Tech#volumechange
9121 * Fires when the text track has been changed
9123 * @event player#texttrackchange
9127 * Retrigger the `texttrackchange` event that was triggered by the {@link Tech}.
9130 * @method Player#handleTechTexttrackchange_
9131 * @fires Player#texttrackchange
9132 * @listens Tech#texttrackchange
9137 * An instance of the `Player` class is created when any of the Video.js setup methods
9138 * are used to initialize a video.
9140 * After an instance has been created it can be accessed globally in two ways:
9141 * 1. By calling `videojs('example_video_1');`
9142 * 2. By using it directly via `videojs.players.example_video_1;`
9144 * @extends Component
9147 var Player = function (_Component) {
9148 _inherits(Player, _Component);
9151 * Create an instance of this class.
9153 * @param {Element} tag
9154 * The original video DOM element used for configuring options.
9156 * @param {Object} [options]
9157 * Object of option names and values.
9159 * @param {Component~ReadyCallback} [ready]
9160 * Ready callback function.
9162 function Player(tag, options, ready) {
9163 _classCallCheck(this, Player);
9165 // Make sure tag ID exists
9166 tag.id = tag.id || 'vjs_video_' + Guid.newGUID();
9169 // The options argument overrides options set in the video tag
9170 // which overrides globally set options.
9171 // This latter part coincides with the load order
9172 // (tag must exist before Player)
9173 options = (0, _obj.assign)(Player.getTagSettings(tag), options);
9175 // Delay the initialization of children because we need to set up
9176 // player properties first, and can't use `this` before `super()`
9177 options.initChildren = false;
9179 // Same with creating the element
9180 options.createEl = false;
9182 // we don't want the player to report touch activity on itself
9183 // see enableTouchActivity in Component
9184 options.reportTouchActivity = false;
9186 // If language is not set, get the closest lang attribute
9187 if (!options.language) {
9188 if (typeof tag.closest === 'function') {
9189 var closest = tag.closest('[lang]');
9192 options.language = closest.getAttribute('lang');
9197 while (element && element.nodeType === 1) {
9198 if (Dom.getElAttributes(element).hasOwnProperty('lang')) {
9199 options.language = element.getAttribute('lang');
9202 element = element.parentNode;
9207 // Run base component initializing with new options
9209 // if the global option object was accidentally blown away by
9210 // someone, bail early with an informative error
9211 var _this = _possibleConstructorReturn(this, _Component.call(this, null, options, ready));
9213 if (!_this.options_ || !_this.options_.techOrder || !_this.options_.techOrder.length) {
9214 throw new Error('No techOrder specified. Did you overwrite ' + 'videojs.options instead of just changing the ' + 'properties you want to override?');
9217 // Store the original tag used to set options
9220 // Store the tag attributes used to restore html5 element
9221 _this.tagAttributes = tag && Dom.getElAttributes(tag);
9223 // Update current language
9224 _this.language(_this.options_.language);
9226 // Update Supported Languages
9227 if (options.languages) {
9229 // Normalise player option languages to lowercase
9230 var languagesToLower = {};
9232 Object.getOwnPropertyNames(options.languages).forEach(function (name) {
9233 languagesToLower[name.toLowerCase()] = options.languages[name];
9235 _this.languages_ = languagesToLower;
9238 _this.languages_ = Player.prototype.options_.languages;
9241 // Cache for video property values.
9245 _this.poster_ = options.poster || '';
9248 _this.controls_ = !!options.controls;
9250 // Original tag settings stored in options
9251 // now remove immediately so native controls don't flash.
9252 // May be turned back on by HTML5 tech if nativeControlsForTouch is true
9253 tag.controls = false;
9256 * Store the internal state of scrubbing
9259 * @return {Boolean} True if the user is scrubbing
9261 _this.scrubbing_ = false;
9263 _this.el_ = _this.createEl();
9265 // We also want to pass the original player options to each component and plugin
9266 // as well so they don't need to reach back into the player for options later.
9267 // We also need to do another copy of this.options_ so we don't end up with
9268 // an infinite loop.
9269 var playerOptionsCopy = (0, _mergeOptions2['default'])(_this.options_);
9272 if (options.plugins) {
9274 var plugins = options.plugins;
9276 Object.getOwnPropertyNames(plugins).forEach(function (name) {
9277 if (typeof this[name] === 'function') {
9278 this[name](plugins[name]);
9280 _log2['default'].error('Unable to find plugin:', name);
9286 _this.options_.playerOptions = playerOptionsCopy;
9288 _this.initChildren();
9290 // Set isAudio based on whether or not an audio tag was used
9291 _this.isAudio(tag.nodeName.toLowerCase() === 'audio');
9293 // Update controls className. Can't do this when the controls are initially
9294 // set because the element doesn't exist yet.
9295 if (_this.controls()) {
9296 _this.addClass('vjs-controls-enabled');
9298 _this.addClass('vjs-controls-disabled');
9301 // Set ARIA label and region role depending on player type
9302 _this.el_.setAttribute('role', 'region');
9303 if (_this.isAudio()) {
9304 _this.el_.setAttribute('aria-label', 'audio player');
9306 _this.el_.setAttribute('aria-label', 'video player');
9309 if (_this.isAudio()) {
9310 _this.addClass('vjs-audio');
9313 if (_this.flexNotSupported_()) {
9314 _this.addClass('vjs-no-flex');
9317 // TODO: Make this smarter. Toggle user state between touching/mousing
9318 // using events, since devices can have both touch and mouse events.
9319 // if (browser.TOUCH_ENABLED) {
9320 // this.addClass('vjs-touch-enabled');
9323 // iOS Safari has broken hover handling
9324 if (!browser.IS_IOS) {
9325 _this.addClass('vjs-workinghover');
9328 // Make player easily findable by ID
9329 Player.players[_this.id_] = _this;
9331 // When the player is first initialized, trigger activity so components
9332 // like the control bar show themselves if needed
9333 _this.userActive(true);
9334 _this.reportUserActivity();
9335 _this.listenForUserActivity_();
9337 _this.on('fullscreenchange', _this.handleFullscreenChange_);
9338 _this.on('stageclick', _this.handleStageClick_);
9343 * Destroys the video player and does any necessary cleanup.
9345 * This is especially helpful if you are dynamically adding and removing videos
9348 * @fires Player#dispose
9352 Player.prototype.dispose = function dispose() {
9354 * Called when the player is being disposed of.
9356 * @event Player#dispose
9357 * @type {EventTarget~Event}
9359 this.trigger('dispose');
9360 // prevent dispose from being called twice
9361 this.off('dispose');
9363 if (this.styleEl_ && this.styleEl_.parentNode) {
9364 this.styleEl_.parentNode.removeChild(this.styleEl_);
9367 // Kill reference to this player
9368 Player.players[this.id_] = null;
9370 if (this.tag && this.tag.player) {
9371 this.tag.player = null;
9374 if (this.el_ && this.el_.player) {
9375 this.el_.player = null;
9379 this.tech_.dispose();
9382 _Component.prototype.dispose.call(this);
9386 * Create the `Player`'s DOM element.
9389 * The DOM element that gets created.
9393 Player.prototype.createEl = function createEl() {
9396 var playerElIngest = this.playerElIngest_ = tag.parentNode && tag.parentNode.hasAttribute('data-vjs-player');
9398 if (playerElIngest) {
9399 el = this.el_ = tag.parentNode;
9401 el = this.el_ = _Component.prototype.createEl.call(this, 'div');
9404 // Remove width/height attrs from tag so CSS can make it 100% width/height
9405 tag.removeAttribute('width');
9406 tag.removeAttribute('height');
9408 // Copy over all the attributes from the tag, including ID and class
9409 // ID will now reference player box, not the video tag
9410 var attrs = Dom.getElAttributes(tag);
9412 Object.getOwnPropertyNames(attrs).forEach(function (attr) {
9413 // workaround so we don't totally break IE7
9414 // http://stackoverflow.com/questions/3653444/css-styles-not-applied-on-dynamic-elements-in-internet-explorer-7
9415 if (attr === 'class') {
9416 el.className += ' ' + attrs[attr];
9418 el.setAttribute(attr, attrs[attr]);
9422 // Update tag id/class for use as HTML5 playback tech
9423 // Might think we should do this after embedding in container so .vjs-tech class
9424 // doesn't flash 100% width/height, but class only applies with .video-js parent
9425 tag.playerId = tag.id;
9426 tag.id += '_html5_api';
9427 tag.className = 'vjs-tech';
9429 // Make player findable on elements
9430 tag.player = el.player = this;
9431 // Default state of video is paused
9432 this.addClass('vjs-paused');
9434 // Add a style element in the player that we'll use to set the width/height
9435 // of the player in a way that's still overridable by CSS, just like the
9437 if (_window2['default'].VIDEOJS_NO_DYNAMIC_STYLE !== true) {
9438 this.styleEl_ = stylesheet.createStyleElement('vjs-styles-dimensions');
9439 var defaultsStyleEl = Dom.$('.vjs-styles-defaults');
9440 var head = Dom.$('head');
9442 head.insertBefore(this.styleEl_, defaultsStyleEl ? defaultsStyleEl.nextSibling : head.firstChild);
9445 // Pass in the width/height/aspectRatio options which will update the style el
9446 this.width(this.options_.width);
9447 this.height(this.options_.height);
9448 this.fluid(this.options_.fluid);
9449 this.aspectRatio(this.options_.aspectRatio);
9451 // Hide any links within the video/audio tag, because IE doesn't hide them completely.
9452 var links = tag.getElementsByTagName('a');
9454 for (var i = 0; i < links.length; i++) {
9455 var linkEl = links.item(i);
9457 Dom.addElClass(linkEl, 'vjs-hidden');
9458 linkEl.setAttribute('hidden', 'hidden');
9461 // insertElFirst seems to cause the networkState to flicker from 3 to 2, so
9462 // keep track of the original for later so we can know if the source originally failed
9463 tag.initNetworkState_ = tag.networkState;
9465 // Wrap video tag in div (el/box) container
9466 if (tag.parentNode && !playerElIngest) {
9467 tag.parentNode.insertBefore(el, tag);
9470 // insert the tag as the first child of the player element
9471 // then manually add it to the children array so that this.addChild
9472 // will work properly for other components
9474 // Breaks iPhone, fixed in HTML5 setup.
9475 Dom.insertElFirst(tag, el);
9476 this.children_.unshift(tag);
9484 * A getter/setter for the `Player`'s width.
9486 * @param {number} [value]
9487 * The value to set the `Player's width to.
9490 * The current width of the `Player`.
9494 Player.prototype.width = function width(value) {
9495 return this.dimension('width', value);
9499 * A getter/setter for the `Player`'s height.
9501 * @param {number} [value]
9502 * The value to set the `Player's height to.
9505 * The current height of the `Player`.
9509 Player.prototype.height = function height(value) {
9510 return this.dimension('height', value);
9514 * A getter/setter for the `Player`'s width & height.
9516 * @param {string} dimension
9517 * This string can be:
9521 * @param {number} [value]
9522 * Value for dimension specified in the first argument.
9524 * @return {Player|number}
9525 * - Returns itself when setting; method can be chained.
9526 * - The dimension arguments value when getting (width/height).
9530 Player.prototype.dimension = function dimension(_dimension, value) {
9531 var privDimension = _dimension + '_';
9533 if (value === undefined) {
9534 return this[privDimension] || 0;
9538 // If an empty string is given, reset the dimension to be automatic
9539 this[privDimension] = undefined;
9541 var parsedVal = parseFloat(value);
9543 if (isNaN(parsedVal)) {
9544 _log2['default'].error('Improper value "' + value + '" supplied for for ' + _dimension);
9548 this[privDimension] = parsedVal;
9551 this.updateStyleEl_();
9556 * A getter/setter/toggler for the vjs-fluid `className` on the `Player`.
9558 * @param {boolean} [bool]
9559 * - A value of true adds the class.
9560 * - A value of false removes the class.
9561 * - No value will toggle the fluid class.
9563 * @return {boolean|undefined}
9564 * - The value of fluid when getting.
9565 * - `undefined` when setting.
9569 Player.prototype.fluid = function fluid(bool) {
9570 if (bool === undefined) {
9571 return !!this.fluid_;
9574 this.fluid_ = !!bool;
9577 this.addClass('vjs-fluid');
9579 this.removeClass('vjs-fluid');
9582 this.updateStyleEl_();
9586 * Get/Set the aspect ratio
9588 * @param {string} [ratio]
9589 * Aspect ratio for player
9591 * @return {string|undefined}
9592 * returns the current aspect ratio when getting
9596 * A getter/setter for the `Player`'s aspect ratio.
9598 * @param {string} [ratio]
9599 * The value to set the `Player's aspect ratio to.
9601 * @return {string|undefined}
9602 * - The current aspect ratio of the `Player` when getting.
9603 * - undefined when setting
9607 Player.prototype.aspectRatio = function aspectRatio(ratio) {
9608 if (ratio === undefined) {
9609 return this.aspectRatio_;
9612 // Check for width:height format
9613 if (!/^\d+\:\d+$/.test(ratio)) {
9614 throw new Error('Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.');
9616 this.aspectRatio_ = ratio;
9618 // We're assuming if you set an aspect ratio you want fluid mode,
9619 // because in fixed mode you could calculate width and height yourself.
9622 this.updateStyleEl_();
9626 * Update styles of the `Player` element (height, width and aspect ratio).
9629 * @listens Tech#loadedmetadata
9633 Player.prototype.updateStyleEl_ = function updateStyleEl_() {
9634 if (_window2['default'].VIDEOJS_NO_DYNAMIC_STYLE === true) {
9635 var _width = typeof this.width_ === 'number' ? this.width_ : this.options_.width;
9636 var _height = typeof this.height_ === 'number' ? this.height_ : this.options_.height;
9637 var techEl = this.tech_ && this.tech_.el();
9641 techEl.width = _width;
9644 techEl.height = _height;
9652 var height = void 0;
9653 var aspectRatio = void 0;
9654 var idClass = void 0;
9656 // The aspect ratio is either used directly or to calculate width and height.
9657 if (this.aspectRatio_ !== undefined && this.aspectRatio_ !== 'auto') {
9658 // Use any aspectRatio that's been specifically set
9659 aspectRatio = this.aspectRatio_;
9660 } else if (this.videoWidth() > 0) {
9661 // Otherwise try to get the aspect ratio from the video metadata
9662 aspectRatio = this.videoWidth() + ':' + this.videoHeight();
9664 // Or use a default. The video element's is 2:1, but 16:9 is more common.
9665 aspectRatio = '16:9';
9668 // Get the ratio as a decimal we can use to calculate dimensions
9669 var ratioParts = aspectRatio.split(':');
9670 var ratioMultiplier = ratioParts[1] / ratioParts[0];
9672 if (this.width_ !== undefined) {
9673 // Use any width that's been specifically set
9674 width = this.width_;
9675 } else if (this.height_ !== undefined) {
9676 // Or calculate the width from the aspect ratio if a height has been set
9677 width = this.height_ / ratioMultiplier;
9679 // Or use the video's metadata, or use the video el's default of 300
9680 width = this.videoWidth() || 300;
9683 if (this.height_ !== undefined) {
9684 // Use any height that's been specifically set
9685 height = this.height_;
9687 // Otherwise calculate the height from the ratio and the width
9688 height = width * ratioMultiplier;
9691 // Ensure the CSS class is valid by starting with an alpha character
9692 if (/^[^a-zA-Z]/.test(this.id())) {
9693 idClass = 'dimensions-' + this.id();
9695 idClass = this.id() + '-dimensions';
9698 // Ensure the right class is still on the player for the style element
9699 this.addClass(idClass);
9701 stylesheet.setTextContent(this.styleEl_, '\n .' + idClass + ' {\n width: ' + width + 'px;\n height: ' + height + 'px;\n }\n\n .' + idClass + '.vjs-fluid {\n padding-top: ' + ratioMultiplier * 100 + '%;\n }\n ');
9705 * Load/Create an instance of playback {@link Tech} including element
9706 * and API methods. Then append the `Tech` element in `Player` as a child.
9708 * @param {string} techName
9709 * name of the playback technology
9711 * @param {string} source
9718 Player.prototype.loadTech_ = function loadTech_(techName, source) {
9721 // Pause and remove current playback technology
9726 // get rid of the HTML5 video tag as soon as we are using another tech
9727 if (techName !== 'Html5' && this.tag) {
9728 _tech2['default'].getTech('Html5').disposeMediaElement(this.tag);
9729 this.tag.player = null;
9733 this.techName_ = techName;
9735 // Turn off API access because we're loading a new tech that might load asynchronously
9736 this.isReady_ = false;
9738 // Grab tech-specific options from player options and add source and parent element to use.
9739 var techOptions = (0, _obj.assign)({
9741 'nativeControlsForTouch': this.options_.nativeControlsForTouch,
9742 'playerId': this.id(),
9743 'techId': this.id() + '_' + techName + '_api',
9744 'videoTracks': this.videoTracks_,
9745 'textTracks': this.textTracks_,
9746 'audioTracks': this.audioTracks_,
9747 'autoplay': this.options_.autoplay,
9748 'preload': this.options_.preload,
9749 'loop': this.options_.loop,
9750 'muted': this.options_.muted,
9751 'poster': this.poster(),
9752 'language': this.language(),
9753 'playerElIngest': this.playerElIngest_ || false,
9754 'vtt.js': this.options_['vtt.js']
9755 }, this.options_[techName.toLowerCase()]);
9758 techOptions.tag = this.tag;
9762 this.currentType_ = source.type;
9764 if (source.src === this.cache_.src && this.cache_.currentTime > 0) {
9765 techOptions.startTime = this.cache_.currentTime;
9768 this.cache_.sources = null;
9769 this.cache_.source = source;
9770 this.cache_.src = source.src;
9773 // Initialize tech instance
9774 var TechComponent = _tech2['default'].getTech(techName);
9776 // Support old behavior of techs being registered as components.
9777 // Remove once that deprecated behavior is removed.
9778 if (!TechComponent) {
9779 TechComponent = _component2['default'].getComponent(techName);
9781 this.tech_ = new TechComponent(techOptions);
9783 // player.triggerReady is always async, so don't need this to be async
9784 this.tech_.ready(Fn.bind(this, this.handleTechReady_), true);
9786 _textTrackListConverter2['default'].jsonToTextTracks(this.textTracksJson_ || [], this.tech_);
9788 // Listen to all HTML5-defined events and trigger them on the player
9789 TECH_EVENTS_RETRIGGER.forEach(function (event) {
9790 _this2.on(_this2.tech_, event, _this2['handleTech' + (0, _toTitleCase2['default'])(event) + '_']);
9792 this.on(this.tech_, 'loadstart', this.handleTechLoadStart_);
9793 this.on(this.tech_, 'waiting', this.handleTechWaiting_);
9794 this.on(this.tech_, 'canplay', this.handleTechCanPlay_);
9795 this.on(this.tech_, 'canplaythrough', this.handleTechCanPlayThrough_);
9796 this.on(this.tech_, 'playing', this.handleTechPlaying_);
9797 this.on(this.tech_, 'ended', this.handleTechEnded_);
9798 this.on(this.tech_, 'seeking', this.handleTechSeeking_);
9799 this.on(this.tech_, 'seeked', this.handleTechSeeked_);
9800 this.on(this.tech_, 'play', this.handleTechPlay_);
9801 this.on(this.tech_, 'firstplay', this.handleTechFirstPlay_);
9802 this.on(this.tech_, 'pause', this.handleTechPause_);
9803 this.on(this.tech_, 'durationchange', this.handleTechDurationChange_);
9804 this.on(this.tech_, 'fullscreenchange', this.handleTechFullscreenChange_);
9805 this.on(this.tech_, 'error', this.handleTechError_);
9806 this.on(this.tech_, 'loadedmetadata', this.updateStyleEl_);
9807 this.on(this.tech_, 'posterchange', this.handleTechPosterChange_);
9808 this.on(this.tech_, 'textdata', this.handleTechTextData_);
9810 this.usingNativeControls(this.techGet_('controls'));
9812 if (this.controls() && !this.usingNativeControls()) {
9813 this.addTechControlsListeners_();
9816 // Add the tech element in the DOM if it was not already there
9817 // Make sure to not insert the original video element if using Html5
9818 if (this.tech_.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) {
9819 Dom.insertElFirst(this.tech_.el(), this.el());
9822 // Get rid of the original video tag reference after the first tech is loaded
9824 this.tag.player = null;
9830 * Unload and dispose of the current playback {@link Tech}.
9836 Player.prototype.unloadTech_ = function unloadTech_() {
9837 // Save the current text tracks so that we can reuse the same text tracks with the next tech
9838 this.videoTracks_ = this.videoTracks();
9839 this.textTracks_ = this.textTracks();
9840 this.audioTracks_ = this.audioTracks();
9841 this.textTracksJson_ = _textTrackListConverter2['default'].textTracksToJson(this.tech_);
9843 this.isReady_ = false;
9845 this.tech_.dispose();
9851 * Return a reference to the current {@link Tech}, but only if given an object with the
9852 * `IWillNotUseThisInPlugins` property having a true value. This is try and prevent misuse
9853 * of techs by plugins.
9855 * @param {Object} safety
9856 * An object that must contain `{IWillNotUseThisInPlugins: true}`
9858 * @param {boolean} safety.IWillNotUseThisInPlugins
9859 * Must be set to true or else this function will throw an error.
9866 Player.prototype.tech = function tech(safety) {
9867 if (safety && safety.IWillNotUseThisInPlugins) {
9870 var errorText = '\n Please make sure that you are not using this inside of a plugin.\n To disable this alert and error, please pass in an object with\n `IWillNotUseThisInPlugins` to the `tech` method. See\n https://github.com/videojs/video.js/issues/2617 for more info.\n ';
9872 _window2['default'].alert(errorText);
9873 throw new Error(errorText);
9877 * Set up click and touch listeners for the playback element
9879 * - On desktops: a click on the video itself will toggle playback
9880 * - On mobile devices: a click on the video toggles controls
9881 * which is done by toggling the user state between active and
9883 * - A tap can signal that a user has become active or has become inactive
9884 * e.g. a quick tap on an iPhone movie should reveal the controls. Another
9885 * quick tap should hide them again (signaling the user is in an inactive
9887 * - In addition to this, we still want the user to be considered inactive after
9888 * a few seconds of inactivity.
9890 * > Note: the only part of iOS interaction we can't mimic with this setup
9891 * is a touch and hold on the video element counting as activity in order to
9892 * keep the controls showing, but that shouldn't be an issue. A touch and hold
9893 * on any controls will still keep the user active
9899 Player.prototype.addTechControlsListeners_ = function addTechControlsListeners_() {
9900 // Make sure to remove all the previous listeners in case we are called multiple times.
9901 this.removeTechControlsListeners_();
9903 // Some browsers (Chrome & IE) don't trigger a click on a flash swf, but do
9904 // trigger mousedown/up.
9905 // http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object
9906 // Any touch events are set to block the mousedown event from happening
9907 this.on(this.tech_, 'mousedown', this.handleTechClick_);
9909 // If the controls were hidden we don't want that to change without a tap event
9910 // so we'll check if the controls were already showing before reporting user
9912 this.on(this.tech_, 'touchstart', this.handleTechTouchStart_);
9913 this.on(this.tech_, 'touchmove', this.handleTechTouchMove_);
9914 this.on(this.tech_, 'touchend', this.handleTechTouchEnd_);
9916 // The tap listener needs to come after the touchend listener because the tap
9917 // listener cancels out any reportedUserActivity when setting userActive(false)
9918 this.on(this.tech_, 'tap', this.handleTechTap_);
9922 * Remove the listeners used for click and tap controls. This is needed for
9923 * toggling to controls disabled, where a tap/touch should do nothing.
9929 Player.prototype.removeTechControlsListeners_ = function removeTechControlsListeners_() {
9930 // We don't want to just use `this.off()` because there might be other needed
9931 // listeners added by techs that extend this.
9932 this.off(this.tech_, 'tap', this.handleTechTap_);
9933 this.off(this.tech_, 'touchstart', this.handleTechTouchStart_);
9934 this.off(this.tech_, 'touchmove', this.handleTechTouchMove_);
9935 this.off(this.tech_, 'touchend', this.handleTechTouchEnd_);
9936 this.off(this.tech_, 'mousedown', this.handleTechClick_);
9940 * Player waits for the tech to be ready
9946 Player.prototype.handleTechReady_ = function handleTechReady_() {
9947 this.triggerReady();
9949 // Keep the same volume as before
9950 if (this.cache_.volume) {
9951 this.techCall_('setVolume', this.cache_.volume);
9954 // Look if the tech found a higher resolution poster while loading
9955 this.handleTechPosterChange_();
9957 // Update the duration if available
9958 this.handleTechDurationChange_();
9960 // Chrome and Safari both have issues with autoplay.
9961 // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
9962 // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
9963 // This fixes both issues. Need to wait for API, so it updates displays correctly
9964 if ((this.src() || this.currentSrc()) && this.tag && this.options_.autoplay && this.paused()) {
9966 // Chrome Fix. Fixed in Chrome v16.
9967 delete this.tag.poster;
9969 (0, _log2['default'])('deleting tag.poster throws in some browsers', e);
9976 * Retrigger the `loadstart` event that was triggered by the {@link Tech}. This
9977 * function will also trigger {@link Player#firstplay} if it is the first loadstart
9980 * @fires Player#loadstart
9981 * @fires Player#firstplay
9982 * @listens Tech#loadstart
9987 Player.prototype.handleTechLoadStart_ = function handleTechLoadStart_() {
9988 // TODO: Update to use `emptied` event instead. See #1277.
9990 this.removeClass('vjs-ended');
9991 this.removeClass('vjs-seeking');
9993 // reset the error state
9996 // If it's already playing we want to trigger a firstplay event now.
9997 // The firstplay event relies on both the play and loadstart events
9998 // which can happen in any order for a new source
9999 if (!this.paused()) {
10001 * Fired when the user agent begins looking for media data
10003 * @event Player#loadstart
10004 * @type {EventTarget~Event}
10006 this.trigger('loadstart');
10007 this.trigger('firstplay');
10009 // reset the hasStarted state
10010 this.hasStarted(false);
10011 this.trigger('loadstart');
10016 * Add/remove the vjs-has-started class
10018 * @fires Player#firstplay
10020 * @param {boolean} hasStarted
10021 * - true: adds the class
10022 * - false: remove the class
10024 * @return {boolean}
10025 * the boolean value of hasStarted
10029 Player.prototype.hasStarted = function hasStarted(_hasStarted) {
10030 if (_hasStarted !== undefined) {
10031 // only update if this is a new value
10032 if (this.hasStarted_ !== _hasStarted) {
10033 this.hasStarted_ = _hasStarted;
10035 this.addClass('vjs-has-started');
10036 // trigger the firstplay event if this newly has played
10037 this.trigger('firstplay');
10039 this.removeClass('vjs-has-started');
10044 return !!this.hasStarted_;
10048 * Fired whenever the media begins or resumes playback
10050 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play}
10051 * @fires Player#play
10052 * @listens Tech#play
10057 Player.prototype.handleTechPlay_ = function handleTechPlay_() {
10058 this.removeClass('vjs-ended');
10059 this.removeClass('vjs-paused');
10060 this.addClass('vjs-playing');
10062 // hide the poster when the user hits play
10063 this.hasStarted(true);
10065 * Triggered whenever an {@link Tech#play} event happens. Indicates that
10066 * playback has started or resumed.
10068 * @event Player#play
10069 * @type {EventTarget~Event}
10071 this.trigger('play');
10075 * Retrigger the `waiting` event that was triggered by the {@link Tech}.
10077 * @fires Player#waiting
10078 * @listens Tech#waiting
10083 Player.prototype.handleTechWaiting_ = function handleTechWaiting_() {
10086 this.addClass('vjs-waiting');
10088 * A readyState change on the DOM element has caused playback to stop.
10090 * @event Player#waiting
10091 * @type {EventTarget~Event}
10093 this.trigger('waiting');
10094 this.one('timeupdate', function () {
10095 return _this3.removeClass('vjs-waiting');
10100 * Retrigger the `canplay` event that was triggered by the {@link Tech}.
10101 * > Note: This is not consistent between browsers. See #1351
10103 * @fires Player#canplay
10104 * @listens Tech#canplay
10109 Player.prototype.handleTechCanPlay_ = function handleTechCanPlay_() {
10110 this.removeClass('vjs-waiting');
10112 * The media has a readyState of HAVE_FUTURE_DATA or greater.
10114 * @event Player#canplay
10115 * @type {EventTarget~Event}
10117 this.trigger('canplay');
10121 * Retrigger the `canplaythrough` event that was triggered by the {@link Tech}.
10123 * @fires Player#canplaythrough
10124 * @listens Tech#canplaythrough
10129 Player.prototype.handleTechCanPlayThrough_ = function handleTechCanPlayThrough_() {
10130 this.removeClass('vjs-waiting');
10132 * The media has a readyState of HAVE_ENOUGH_DATA or greater. This means that the
10133 * entire media file can be played without buffering.
10135 * @event Player#canplaythrough
10136 * @type {EventTarget~Event}
10138 this.trigger('canplaythrough');
10142 * Retrigger the `playing` event that was triggered by the {@link Tech}.
10144 * @fires Player#playing
10145 * @listens Tech#playing
10150 Player.prototype.handleTechPlaying_ = function handleTechPlaying_() {
10151 this.removeClass('vjs-waiting');
10153 * The media is no longer blocked from playback, and has started playing.
10155 * @event Player#playing
10156 * @type {EventTarget~Event}
10158 this.trigger('playing');
10162 * Retrigger the `seeking` event that was triggered by the {@link Tech}.
10164 * @fires Player#seeking
10165 * @listens Tech#seeking
10170 Player.prototype.handleTechSeeking_ = function handleTechSeeking_() {
10171 this.addClass('vjs-seeking');
10173 * Fired whenever the player is jumping to a new time
10175 * @event Player#seeking
10176 * @type {EventTarget~Event}
10178 this.trigger('seeking');
10182 * Retrigger the `seeked` event that was triggered by the {@link Tech}.
10184 * @fires Player#seeked
10185 * @listens Tech#seeked
10190 Player.prototype.handleTechSeeked_ = function handleTechSeeked_() {
10191 this.removeClass('vjs-seeking');
10193 * Fired when the player has finished jumping to a new time
10195 * @event Player#seeked
10196 * @type {EventTarget~Event}
10198 this.trigger('seeked');
10202 * Retrigger the `firstplay` event that was triggered by the {@link Tech}.
10204 * @fires Player#firstplay
10205 * @listens Tech#firstplay
10206 * @deprecated As of 6.0 passing the `starttime` option to the player will be deprecated
10211 Player.prototype.handleTechFirstPlay_ = function handleTechFirstPlay_() {
10212 // If the first starttime attribute is specified
10213 // then we will start at the given offset in seconds
10214 if (this.options_.starttime) {
10215 _log2['default'].warn('Passing the `starttime` option to the player will be deprecated in 6.0');
10216 this.currentTime(this.options_.starttime);
10219 this.addClass('vjs-has-started');
10221 * Fired the first time a video is played. Not part of the HLS spec, and this is
10222 * probably not the best implementation yet, so use sparingly. If you don't have a
10223 * reason to prevent playback, use `myPlayer.one('play');` instead.
10225 * @event Player#firstplay
10226 * @type {EventTarget~Event}
10228 this.trigger('firstplay');
10232 * Retrigger the `pause` event that was triggered by the {@link Tech}.
10234 * @fires Player#pause
10235 * @listens Tech#pause
10240 Player.prototype.handleTechPause_ = function handleTechPause_() {
10241 this.removeClass('vjs-playing');
10242 this.addClass('vjs-paused');
10244 * Fired whenever the media has been paused
10246 * @event Player#pause
10247 * @type {EventTarget~Event}
10249 this.trigger('pause');
10253 * Retrigger the `ended` event that was triggered by the {@link Tech}.
10255 * @fires Player#ended
10256 * @listens Tech#ended
10261 Player.prototype.handleTechEnded_ = function handleTechEnded_() {
10262 this.addClass('vjs-ended');
10263 if (this.options_.loop) {
10264 this.currentTime(0);
10266 } else if (!this.paused()) {
10271 * Fired when the end of the media resource is reached (currentTime == duration)
10273 * @event Player#ended
10274 * @type {EventTarget~Event}
10276 this.trigger('ended');
10280 * Fired when the duration of the media resource is first known or changed
10282 * @listens Tech#durationchange
10287 Player.prototype.handleTechDurationChange_ = function handleTechDurationChange_() {
10288 this.duration(this.techGet_('duration'));
10292 * Handle a click on the media element to play/pause
10294 * @param {EventTarget~Event} event
10295 * the event that caused this function to trigger
10297 * @listens Tech#mousedown
10302 Player.prototype.handleTechClick_ = function handleTechClick_(event) {
10303 // We're using mousedown to detect clicks thanks to Flash, but mousedown
10304 // will also be triggered with right-clicks, so we need to prevent that
10305 if (event.button !== 0) {
10309 // When controls are disabled a click should not toggle playback because
10310 // the click is considered a control
10311 if (this.controls()) {
10312 if (this.paused()) {
10321 * Handle a tap on the media element. It will toggle the user
10322 * activity state, which hides and shows the controls.
10324 * @listens Tech#tap
10329 Player.prototype.handleTechTap_ = function handleTechTap_() {
10330 this.userActive(!this.userActive());
10334 * Handle touch to start
10336 * @listens Tech#touchstart
10341 Player.prototype.handleTechTouchStart_ = function handleTechTouchStart_() {
10342 this.userWasActive = this.userActive();
10346 * Handle touch to move
10348 * @listens Tech#touchmove
10353 Player.prototype.handleTechTouchMove_ = function handleTechTouchMove_() {
10354 if (this.userWasActive) {
10355 this.reportUserActivity();
10360 * Handle touch to end
10362 * @param {EventTarget~Event} event
10363 * the touchend event that triggered
10366 * @listens Tech#touchend
10371 Player.prototype.handleTechTouchEnd_ = function handleTechTouchEnd_(event) {
10372 // Stop the mouse events from also happening
10373 event.preventDefault();
10377 * Fired when the player switches in or out of fullscreen mode
10380 * @listens Player#fullscreenchange
10384 Player.prototype.handleFullscreenChange_ = function handleFullscreenChange_() {
10385 if (this.isFullscreen()) {
10386 this.addClass('vjs-fullscreen');
10388 this.removeClass('vjs-fullscreen');
10393 * native click events on the SWF aren't triggered on IE11, Win8.1RT
10394 * use stageclick events triggered from inside the SWF instead
10397 * @listens stageclick
10401 Player.prototype.handleStageClick_ = function handleStageClick_() {
10402 this.reportUserActivity();
10406 * Handle Tech Fullscreen Change
10408 * @param {EventTarget~Event} event
10409 * the fullscreenchange event that triggered this function
10411 * @param {Object} data
10412 * the data that was sent with the event
10415 * @listens Tech#fullscreenchange
10416 * @fires Player#fullscreenchange
10420 Player.prototype.handleTechFullscreenChange_ = function handleTechFullscreenChange_(event, data) {
10422 this.isFullscreen(data.isFullscreen);
10425 * Fired when going in and out of fullscreen.
10427 * @event Player#fullscreenchange
10428 * @type {EventTarget~Event}
10430 this.trigger('fullscreenchange');
10434 * Fires when an error occurred during the loading of an audio/video.
10437 * @listens Tech#error
10441 Player.prototype.handleTechError_ = function handleTechError_() {
10442 var error = this.tech_.error();
10448 * Retrigger the `textdata` event that was triggered by the {@link Tech}.
10450 * @fires Player#textdata
10451 * @listens Tech#textdata
10456 Player.prototype.handleTechTextData_ = function handleTechTextData_() {
10459 if (arguments.length > 1) {
10460 data = arguments[1];
10464 * Fires when we get a textdata event from tech
10466 * @event Player#textdata
10467 * @type {EventTarget~Event}
10469 this.trigger('textdata', data);
10473 * Get object for cached values.
10476 * get the current object cache
10480 Player.prototype.getCache = function getCache() {
10481 return this.cache_;
10485 * Pass values to the playback tech
10487 * @param {string} [method]
10488 * the method to call
10490 * @param {Object} arg
10491 * the argument to pass
10497 Player.prototype.techCall_ = function techCall_(method, arg) {
10498 // If it's not ready yet, call method when it is
10499 if (this.tech_ && !this.tech_.isReady_) {
10500 this.tech_.ready(function () {
10504 // Otherwise call method now
10508 this.tech_[method](arg);
10511 (0, _log2['default'])(e);
10518 * Get calls can't wait for the tech, and sometimes don't need to.
10520 * @param {string} method
10523 * @return {Function|undefined}
10524 * the method or undefined
10530 Player.prototype.techGet_ = function techGet_(method) {
10531 if (this.tech_ && this.tech_.isReady_) {
10533 // Flash likes to die and reload when you hide or reposition it.
10534 // In these cases the object methods go away and we get errors.
10535 // When that happens we'll catch the errors and inform tech that it's not ready any more.
10537 return this.tech_[method]();
10539 // When building additional tech libs, an expected method may not be defined yet
10540 if (this.tech_[method] === undefined) {
10541 (0, _log2['default'])('Video.js: ' + method + ' method not defined for ' + this.techName_ + ' playback technology.', e);
10543 // When a method isn't available on the object it throws a TypeError
10544 } else if (e.name === 'TypeError') {
10545 (0, _log2['default'])('Video.js: ' + method + ' unavailable on ' + this.techName_ + ' playback technology element.', e);
10546 this.tech_.isReady_ = false;
10548 (0, _log2['default'])(e);
10558 * start media playback
10561 * A reference to the player object this function was called on
10565 Player.prototype.play = function play() {
10566 // Only calls the tech's play if we already have a src loaded
10567 if (this.src() || this.currentSrc()) {
10568 this.techCall_('play');
10570 this.tech_.one('loadstart', function () {
10579 * Pause the video playback
10582 * A reference to the player object this function was called on
10586 Player.prototype.pause = function pause() {
10587 this.techCall_('pause');
10592 * Check if the player is paused or has yet to play
10594 * @return {boolean}
10595 * - false: if the media is currently playing
10596 * - true: if media is not currently playing
10600 Player.prototype.paused = function paused() {
10601 // The initial state of paused should be true (in Safari it's actually false)
10602 return this.techGet_('paused') === false ? false : true;
10606 * Returns whether or not the user is "scrubbing". Scrubbing is
10607 * when the user has clicked the progress bar handle and is
10608 * dragging it along the progress bar.
10610 * @param {boolean} [isScrubbing]
10611 * whether the user is or is not scrubbing
10613 * @return {boolean|Player}
10614 * A instance of the player that called this function when setting,
10615 * and the value of scrubbing when getting
10619 Player.prototype.scrubbing = function scrubbing(isScrubbing) {
10620 if (isScrubbing !== undefined) {
10621 this.scrubbing_ = !!isScrubbing;
10624 this.addClass('vjs-scrubbing');
10626 this.removeClass('vjs-scrubbing');
10632 return this.scrubbing_;
10636 * Get or set the current time (in seconds)
10638 * @param {number|string} [seconds]
10639 * The time to seek to in seconds
10641 * @return {Player|number}
10642 * - the current time in seconds when getting
10643 * - a reference to the current player object when
10648 Player.prototype.currentTime = function currentTime(seconds) {
10649 if (seconds !== undefined) {
10651 this.techCall_('setCurrentTime', seconds);
10656 // cache last currentTime and return. default to 0 seconds
10658 // Caching the currentTime is meant to prevent a massive amount of reads on the tech's
10659 // currentTime when scrubbing, but may not provide much performance benefit after all.
10660 // Should be tested. Also something has to read the actual current time or the cache will
10661 // never get updated.
10662 this.cache_.currentTime = this.techGet_('currentTime') || 0;
10663 return this.cache_.currentTime;
10667 * Normally gets the length in time of the video in seconds;
10668 * in all but the rarest use cases an argument will NOT be passed to the method
10670 * > **NOTE**: The video must have started loading before the duration can be
10671 * known, and in the case of Flash, may not be known until the video starts
10674 * @fires Player#durationchange
10676 * @param {number} [seconds]
10677 * The duration of the video to set in seconds
10679 * @return {number|Player}
10680 * - The duration of the video in seconds when getting
10681 * - A reference to the player that called this function
10686 Player.prototype.duration = function duration(seconds) {
10687 if (seconds === undefined) {
10688 return this.cache_.duration || 0;
10691 seconds = parseFloat(seconds) || 0;
10693 // Standardize on Inifity for signaling video is live
10695 seconds = Infinity;
10698 if (seconds !== this.cache_.duration) {
10699 // Cache the last set value for optimized scrubbing (esp. Flash)
10700 this.cache_.duration = seconds;
10702 if (seconds === Infinity) {
10703 this.addClass('vjs-live');
10705 this.removeClass('vjs-live');
10708 * @event Player#durationchange
10709 * @type {EventTarget~Event}
10711 this.trigger('durationchange');
10718 * Calculates how much time is left in the video. Not part
10719 * of the native video API.
10722 * The time remaining in seconds
10726 Player.prototype.remainingTime = function remainingTime() {
10727 return this.duration() - this.currentTime();
10731 // Kind of like an array of portions of the video that have been downloaded.
10734 * Get a TimeRange object with an array of the times of the video
10735 * that have been downloaded. If you just want the percent of the
10736 * video that's been downloaded, use bufferedPercent.
10738 * @see [Buffered Spec]{@link http://dev.w3.org/html5/spec/video.html#dom-media-buffered}
10740 * @return {TimeRange}
10741 * A mock TimeRange object (following HTML spec)
10745 Player.prototype.buffered = function buffered() {
10746 var buffered = this.techGet_('buffered');
10748 if (!buffered || !buffered.length) {
10749 buffered = (0, _timeRanges.createTimeRange)(0, 0);
10756 * Get the percent (as a decimal) of the video that's been downloaded.
10757 * This method is not a part of the native HTML video API.
10760 * A decimal between 0 and 1 representing the percent
10761 * that is buffered 0 being 0% and 1 being 100%
10765 Player.prototype.bufferedPercent = function bufferedPercent() {
10766 return (0, _buffer.bufferedPercent)(this.buffered(), this.duration());
10770 * Get the ending time of the last buffered time range
10771 * This is used in the progress bar to encapsulate all time ranges.
10774 * The end of the last buffered time range
10778 Player.prototype.bufferedEnd = function bufferedEnd() {
10779 var buffered = this.buffered();
10780 var duration = this.duration();
10781 var end = buffered.end(buffered.length - 1);
10783 if (end > duration) {
10791 * Get or set the current volume of the media
10793 * @param {number} [percentAsDecimal]
10794 * The new volume as a decimal percent:
10795 * - 0 is muted/0%/off
10796 * - 1.0 is 100%/full
10797 * - 0.5 is half volume or 50%
10799 * @return {Player|number}
10800 * a reference to the calling player when setting and the
10801 * current volume as a percent when getting
10805 Player.prototype.volume = function volume(percentAsDecimal) {
10808 if (percentAsDecimal !== undefined) {
10809 // Force value to between 0 and 1
10810 vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal)));
10811 this.cache_.volume = vol;
10812 this.techCall_('setVolume', vol);
10817 // Default to 1 when returning current volume.
10818 vol = parseFloat(this.techGet_('volume'));
10819 return isNaN(vol) ? 1 : vol;
10823 * Get the current muted state, or turn mute on or off
10825 * @param {boolean} [muted]
10827 * - false to unmute
10829 * @return {boolean|Player}
10830 * - true if mute is on and getting
10831 * - false if mute is off and getting
10832 * - A reference to the current player when setting
10836 Player.prototype.muted = function muted(_muted) {
10837 if (_muted !== undefined) {
10838 this.techCall_('setMuted', _muted);
10841 return this.techGet_('muted') || false;
10845 * Check if current tech can support native fullscreen
10846 * (e.g. with built in controls like iOS, so not our flash swf)
10848 * @return {boolean}
10849 * if native fullscreen is supported
10853 Player.prototype.supportsFullScreen = function supportsFullScreen() {
10854 return this.techGet_('supportsFullScreen') || false;
10858 * Check if the player is in fullscreen mode or tell the player that it
10859 * is or is not in fullscreen mode.
10861 * > NOTE: As of the latest HTML5 spec, isFullscreen is no longer an official
10862 * property and instead document.fullscreenElement is used. But isFullscreen is
10863 * still a valuable property for internal player workings.
10865 * @param {boolean} [isFS]
10866 * Set the players current fullscreen state
10868 * @return {boolean|Player}
10869 * - true if fullscreen is on and getting
10870 * - false if fullscreen is off and getting
10871 * - A reference to the current player when setting
10875 Player.prototype.isFullscreen = function isFullscreen(isFS) {
10876 if (isFS !== undefined) {
10877 this.isFullscreen_ = !!isFS;
10880 return !!this.isFullscreen_;
10884 * Increase the size of the video to full screen
10885 * In some browsers, full screen is not supported natively, so it enters
10886 * "full window mode", where the video fills the browser window.
10887 * In browsers and devices that support native full screen, sometimes the
10888 * browser's default controls will be shown, and not the Video.js custom skin.
10889 * This includes most mobile devices (iOS, Android) and older versions of
10892 * @fires Player#fullscreenchange
10894 * A reference to the current player
10898 Player.prototype.requestFullscreen = function requestFullscreen() {
10899 var fsApi = _fullscreenApi2['default'];
10901 this.isFullscreen(true);
10903 if (fsApi.requestFullscreen) {
10904 // the browser supports going fullscreen at the element level so we can
10905 // take the controls fullscreen as well as the video
10907 // Trigger fullscreenchange event after change
10908 // We have to specifically add this each time, and remove
10909 // when canceling fullscreen. Otherwise if there's multiple
10910 // players on a page, they would all be reacting to the same fullscreen
10912 Events.on(_document2['default'], fsApi.fullscreenchange, Fn.bind(this, function documentFullscreenChange(e) {
10913 this.isFullscreen(_document2['default'][fsApi.fullscreenElement]);
10915 // If cancelling fullscreen, remove event listener.
10916 if (this.isFullscreen() === false) {
10917 Events.off(_document2['default'], fsApi.fullscreenchange, documentFullscreenChange);
10920 * @event Player#fullscreenchange
10921 * @type {EventTarget~Event}
10923 this.trigger('fullscreenchange');
10926 this.el_[fsApi.requestFullscreen]();
10927 } else if (this.tech_.supportsFullScreen()) {
10928 // we can't take the video.js controls fullscreen but we can go fullscreen
10929 // with native controls
10930 this.techCall_('enterFullScreen');
10932 // fullscreen isn't supported so we'll just stretch the video element to
10933 // fill the viewport
10934 this.enterFullWindow();
10936 * @event Player#fullscreenchange
10937 * @type {EventTarget~Event}
10939 this.trigger('fullscreenchange');
10946 * Return the video to its normal size after having been in full screen mode
10948 * @fires Player#fullscreenchange
10951 * A reference to the current player
10955 Player.prototype.exitFullscreen = function exitFullscreen() {
10956 var fsApi = _fullscreenApi2['default'];
10958 this.isFullscreen(false);
10960 // Check for browser element fullscreen support
10961 if (fsApi.requestFullscreen) {
10962 _document2['default'][fsApi.exitFullscreen]();
10963 } else if (this.tech_.supportsFullScreen()) {
10964 this.techCall_('exitFullScreen');
10966 this.exitFullWindow();
10968 * @event Player#fullscreenchange
10969 * @type {EventTarget~Event}
10971 this.trigger('fullscreenchange');
10978 * When fullscreen isn't supported we can stretch the
10979 * video container to as wide as the browser will let us.
10981 * @fires Player#enterFullWindow
10985 Player.prototype.enterFullWindow = function enterFullWindow() {
10986 this.isFullWindow = true;
10988 // Storing original doc overflow value to return to when fullscreen is off
10989 this.docOrigOverflow = _document2['default'].documentElement.style.overflow;
10991 // Add listener for esc key to exit fullscreen
10992 Events.on(_document2['default'], 'keydown', Fn.bind(this, this.fullWindowOnEscKey));
10994 // Hide any scroll bars
10995 _document2['default'].documentElement.style.overflow = 'hidden';
10997 // Apply fullscreen styles
10998 Dom.addElClass(_document2['default'].body, 'vjs-full-window');
11001 * @event Player#enterFullWindow
11002 * @type {EventTarget~Event}
11004 this.trigger('enterFullWindow');
11008 * Check for call to either exit full window or
11009 * full screen on ESC key
11011 * @param {string} event
11012 * Event to check for key press
11016 Player.prototype.fullWindowOnEscKey = function fullWindowOnEscKey(event) {
11017 if (event.keyCode === 27) {
11018 if (this.isFullscreen() === true) {
11019 this.exitFullscreen();
11021 this.exitFullWindow();
11029 * @fires Player#exitFullWindow
11033 Player.prototype.exitFullWindow = function exitFullWindow() {
11034 this.isFullWindow = false;
11035 Events.off(_document2['default'], 'keydown', this.fullWindowOnEscKey);
11037 // Unhide scroll bars.
11038 _document2['default'].documentElement.style.overflow = this.docOrigOverflow;
11040 // Remove fullscreen styles
11041 Dom.removeElClass(_document2['default'].body, 'vjs-full-window');
11043 // Resize the box, controller, and poster to original sizes
11044 // this.positionAll();
11046 * @event Player#exitFullWindow
11047 * @type {EventTarget~Event}
11049 this.trigger('exitFullWindow');
11053 * Check whether the player can play a given mimetype
11055 * @see https://www.w3.org/TR/2011/WD-html5-20110113/video.html#dom-navigator-canplaytype
11057 * @param {string} type
11058 * The mimetype to check
11061 * 'probably', 'maybe', or '' (empty string)
11065 Player.prototype.canPlayType = function canPlayType(type) {
11068 // Loop through each playback technology in the options order
11069 for (var i = 0, j = this.options_.techOrder; i < j.length; i++) {
11070 var techName = (0, _toTitleCase2['default'])(j[i]);
11071 var tech = _tech2['default'].getTech(techName);
11073 // Support old behavior of techs being registered as components.
11074 // Remove once that deprecated behavior is removed.
11076 tech = _component2['default'].getComponent(techName);
11079 // Check if the current tech is defined before continuing
11081 _log2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.');
11085 // Check if the browser supports this technology
11086 if (tech.isSupported()) {
11087 can = tech.canPlayType(type);
11099 * Select source based on tech-order or source-order
11100 * Uses source-order selection if `options.sourceOrder` is truthy. Otherwise,
11101 * defaults to tech-order selection
11103 * @param {Array} sources
11104 * The sources for a media asset
11106 * @return {Object|boolean}
11107 * Object of source and tech order or false
11111 Player.prototype.selectSource = function selectSource(sources) {
11114 // Get only the techs specified in `techOrder` that exist and are supported by the
11115 // current platform
11116 var techs = this.options_.techOrder.map(_toTitleCase2['default']).map(function (techName) {
11117 // `Component.getComponent(...)` is for support of old behavior of techs
11118 // being registered as components.
11119 // Remove once that deprecated behavior is removed.
11120 return [techName, _tech2['default'].getTech(techName) || _component2['default'].getComponent(techName)];
11121 }).filter(function (_ref) {
11122 var techName = _ref[0],
11125 // Check if the current tech is defined before continuing
11127 // Check if the browser supports this technology
11128 return tech.isSupported();
11131 _log2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.');
11135 // Iterate over each `innerArray` element once per `outerArray` element and execute
11136 // `tester` with both. If `tester` returns a non-falsy value, exit early and return
11138 var findFirstPassingTechSourcePair = function findFirstPassingTechSourcePair(outerArray, innerArray, tester) {
11139 var found = void 0;
11141 outerArray.some(function (outerChoice) {
11142 return innerArray.some(function (innerChoice) {
11143 found = tester(outerChoice, innerChoice);
11154 var foundSourceAndTech = void 0;
11155 var flip = function flip(fn) {
11156 return function (a, b) {
11160 var finder = function finder(_ref2, source) {
11161 var techName = _ref2[0],
11164 if (tech.canPlaySource(source, _this4.options_[techName.toLowerCase()])) {
11165 return { source: source, tech: techName };
11169 // Depending on the truthiness of `options.sourceOrder`, we swap the order of techs and sources
11170 // to select from them based on their priority.
11171 if (this.options_.sourceOrder) {
11172 // Source-first ordering
11173 foundSourceAndTech = findFirstPassingTechSourcePair(sources, techs, flip(finder));
11175 // Tech-first ordering
11176 foundSourceAndTech = findFirstPassingTechSourcePair(techs, sources, finder);
11179 return foundSourceAndTech || false;
11183 * The source function updates the video source
11184 * There are three types of variables you can pass as the argument.
11185 * **URL string**: A URL to the the video file. Use this method if you are sure
11186 * the current playback technology (HTML5/Flash) can support the source you
11187 * provide. Currently only MP4 files can be used in both HTML5 and Flash.
11189 * @param {Tech~SourceObject|Tech~SourceObject[]} [source]
11190 * One SourceObject or an array of SourceObjects
11192 * @return {string|Player}
11193 * - The current video source when getting
11194 * - The player when setting
11198 Player.prototype.src = function src(source) {
11199 if (source === undefined) {
11200 return this.techGet_('src');
11203 var currentTech = _tech2['default'].getTech(this.techName_);
11205 // Support old behavior of techs being registered as components.
11206 // Remove once that deprecated behavior is removed.
11207 if (!currentTech) {
11208 currentTech = _component2['default'].getComponent(this.techName_);
11211 // case: Array of source objects to choose from and pick the best to play
11212 if (Array.isArray(source)) {
11213 this.sourceList_(source);
11215 // case: URL String (http://myvideo...)
11216 } else if (typeof source === 'string') {
11217 // create a source object from the string
11218 this.src({ src: source });
11220 // case: Source object { src: '', type: '' ... }
11221 } else if (source instanceof Object) {
11222 // check if the source has a type and the loaded tech cannot play the source
11223 // if there's no type we'll just try the current tech
11224 if (source.type && !currentTech.canPlaySource(source, this.options_[this.techName_.toLowerCase()])) {
11225 // create a source list with the current source and send through
11226 // the tech loop to check for a compatible technology
11227 this.sourceList_([source]);
11229 this.cache_.sources = null;
11230 this.cache_.source = source;
11231 this.cache_.src = source.src;
11233 this.currentType_ = source.type || '';
11235 // wait until the tech is ready to set the source
11236 this.ready(function () {
11238 // The setSource tech method was added with source handlers
11239 // so older techs won't support it
11240 // We need to check the direct prototype for the case where subclasses
11241 // of the tech do not support source handlers
11242 if (currentTech.prototype.hasOwnProperty('setSource')) {
11243 this.techCall_('setSource', source);
11245 this.techCall_('src', source.src);
11248 if (this.options_.preload === 'auto') {
11252 if (this.options_.autoplay) {
11256 // Set the source synchronously if possible (#2326)
11265 * Handle an array of source objects
11267 * @param {Tech~SourceObject[]} sources
11268 * Array of source objects
11274 Player.prototype.sourceList_ = function sourceList_(sources) {
11275 var sourceTech = this.selectSource(sources);
11278 if (sourceTech.tech === this.techName_) {
11279 // if this technology is already loaded, set the source
11280 this.src(sourceTech.source);
11282 // load this technology with the chosen source
11283 this.loadTech_(sourceTech.tech, sourceTech.source);
11286 this.cache_.sources = sources;
11288 // We need to wrap this in a timeout to give folks a chance to add error event handlers
11289 this.setTimeout(function () {
11290 this.error({ code: 4, message: this.localize(this.options_.notSupportedMessage) });
11293 // we could not find an appropriate tech, but let's still notify the delegate that this is it
11294 // this needs a better comment about why this is needed
11295 this.triggerReady();
11300 * Begin loading the src data.
11303 * A reference to the player
11307 Player.prototype.load = function load() {
11308 this.techCall_('load');
11313 * Reset the player. Loads the first tech in the techOrder,
11314 * and calls `reset` on the tech`.
11317 * A reference to the player
11321 Player.prototype.reset = function reset() {
11322 this.loadTech_((0, _toTitleCase2['default'])(this.options_.techOrder[0]), null);
11323 this.techCall_('reset');
11328 * Returns all of the current source objects.
11330 * @return {Tech~SourceObject[]}
11331 * The current source objects
11335 Player.prototype.currentSources = function currentSources() {
11336 var source = this.currentSource();
11339 // assume `{}` or `{ src }`
11340 if (Object.keys(source).length !== 0) {
11341 sources.push(source);
11344 return this.cache_.sources || sources;
11348 * Returns the current source object.
11350 * @return {Tech~SourceObject}
11351 * The current source object
11355 Player.prototype.currentSource = function currentSource() {
11357 var src = this.currentSrc();
11363 return this.cache_.source || source;
11367 * Returns the fully qualified URL of the current source value e.g. http://mysite.com/video.mp4
11368 * Can be used in conjunction with `currentType` to assist in rebuilding the current source object.
11371 * The current source
11375 Player.prototype.currentSrc = function currentSrc() {
11376 return this.techGet_('currentSrc') || this.cache_.src || '';
11380 * Get the current source type e.g. video/mp4
11381 * This can allow you rebuild the current source object so that you could load the same
11382 * source and tech later
11385 * The source MIME type
11389 Player.prototype.currentType = function currentType() {
11390 return this.currentType_ || '';
11394 * Get or set the preload attribute
11396 * @param {boolean} [value]
11397 * - true means that we should preload
11398 * - false maens that we should not preload
11400 * @return {string|Player}
11401 * - the preload attribute value when getting
11402 * - the player when setting
11406 Player.prototype.preload = function preload(value) {
11407 if (value !== undefined) {
11408 this.techCall_('setPreload', value);
11409 this.options_.preload = value;
11412 return this.techGet_('preload');
11416 * Get or set the autoplay attribute.
11418 * @param {boolean} [value]
11419 * - true means that we should autoplay
11420 * - false maens that we should not autoplay
11422 * @return {string|Player}
11423 * - the current value of autoplay
11424 * - the player when setting
11428 Player.prototype.autoplay = function autoplay(value) {
11429 if (value !== undefined) {
11430 this.techCall_('setAutoplay', value);
11431 this.options_.autoplay = value;
11434 return this.techGet_('autoplay', value);
11438 * Get or set the loop attribute on the video element.
11440 * @param {boolean} [value]
11441 * - true means that we should loop the video
11442 * - false means that we should not loop the video
11444 * @return {string|Player}
11445 * - the current value of loop when getting
11446 * - the player when setting
11450 Player.prototype.loop = function loop(value) {
11451 if (value !== undefined) {
11452 this.techCall_('setLoop', value);
11453 this.options_.loop = value;
11456 return this.techGet_('loop');
11460 * Get or set the poster image source url
11462 * @fires Player#posterchange
11464 * @param {string} [src]
11465 * Poster image source URL
11467 * @return {string|Player}
11468 * - the current value of poster when getting
11469 * - the player when setting
11473 Player.prototype.poster = function poster(src) {
11474 if (src === undefined) {
11475 return this.poster_;
11478 // The correct way to remove a poster is to set as an empty string
11479 // other falsey values will throw errors
11484 // update the internal poster variable
11485 this.poster_ = src;
11487 // update the tech's poster
11488 this.techCall_('setPoster', src);
11490 // alert components that the poster has been set
11492 * This event fires when the poster image is changed on the player.
11494 * @event Player#posterchange
11495 * @type {EventTarget~Event}
11497 this.trigger('posterchange');
11503 * Some techs (e.g. YouTube) can provide a poster source in an
11504 * asynchronous way. We want the poster component to use this
11505 * poster source so that it covers up the tech's controls.
11506 * (YouTube's play button). However we only want to use this
11507 * source if the player user hasn't set a poster through
11510 * @fires Player#posterchange
11511 * @listens Tech#posterchange
11516 Player.prototype.handleTechPosterChange_ = function handleTechPosterChange_() {
11517 if (!this.poster_ && this.tech_ && this.tech_.poster) {
11518 this.poster_ = this.tech_.poster() || '';
11520 // Let components know the poster has changed
11521 this.trigger('posterchange');
11526 * Get or set whether or not the controls are showing.
11528 * @fires Player#controlsenabled
11530 * @param {boolean} [bool]
11531 * - true to turn controls on
11532 * - false to turn controls off
11534 * @return {boolean|Player}
11535 * - the current value of controls when getting
11536 * - the player when setting
11540 Player.prototype.controls = function controls(bool) {
11541 if (bool !== undefined) {
11544 // Don't trigger a change event unless it actually changed
11545 if (this.controls_ !== bool) {
11546 this.controls_ = bool;
11548 if (this.usingNativeControls()) {
11549 this.techCall_('setControls', bool);
11553 this.removeClass('vjs-controls-disabled');
11554 this.addClass('vjs-controls-enabled');
11556 * @event Player#controlsenabled
11557 * @type {EventTarget~Event}
11559 this.trigger('controlsenabled');
11561 if (!this.usingNativeControls()) {
11562 this.addTechControlsListeners_();
11565 this.removeClass('vjs-controls-enabled');
11566 this.addClass('vjs-controls-disabled');
11568 * @event Player#controlsdisabled
11569 * @type {EventTarget~Event}
11571 this.trigger('controlsdisabled');
11573 if (!this.usingNativeControls()) {
11574 this.removeTechControlsListeners_();
11580 return !!this.controls_;
11584 * Toggle native controls on/off. Native controls are the controls built into
11585 * devices (e.g. default iPhone controls), Flash, or other techs
11586 * (e.g. Vimeo Controls)
11587 * **This should only be set by the current tech, because only the tech knows
11588 * if it can support native controls**
11590 * @fires Player#usingnativecontrols
11591 * @fires Player#usingcustomcontrols
11593 * @param {boolean} [bool]
11594 * - true to turn native controls on
11595 * - false to turn native controls off
11597 * @return {boolean|Player}
11598 * - the current value of native controls when getting
11599 * - the player when setting
11603 Player.prototype.usingNativeControls = function usingNativeControls(bool) {
11604 if (bool !== undefined) {
11607 // Don't trigger a change event unless it actually changed
11608 if (this.usingNativeControls_ !== bool) {
11609 this.usingNativeControls_ = bool;
11611 this.addClass('vjs-using-native-controls');
11614 * player is using the native device controls
11616 * @event Player#usingnativecontrols
11617 * @type {EventTarget~Event}
11619 this.trigger('usingnativecontrols');
11621 this.removeClass('vjs-using-native-controls');
11624 * player is using the custom HTML controls
11626 * @event Player#usingcustomcontrols
11627 * @type {EventTarget~Event}
11629 this.trigger('usingcustomcontrols');
11634 return !!this.usingNativeControls_;
11638 * Set or get the current MediaError
11640 * @fires Player#error
11642 * @param {MediaError|string|number} [err]
11643 * A MediaError or a string/number to be turned
11644 * into a MediaError
11646 * @return {MediaError|null|Player}
11647 * - The current MediaError when getting (or null)
11648 * - The player when setting
11652 Player.prototype.error = function error(err) {
11653 if (err === undefined) {
11654 return this.error_ || null;
11657 // restoring to default
11658 if (err === null) {
11660 this.removeClass('vjs-error');
11661 if (this.errorDisplay) {
11662 this.errorDisplay.close();
11667 this.error_ = new _mediaError2['default'](err);
11669 // add the vjs-error classname to the player
11670 this.addClass('vjs-error');
11672 // log the name of the error type and any message
11673 // ie8 just logs "[object object]" if you just log the error object
11674 _log2['default'].error('(CODE:' + this.error_.code + ' ' + _mediaError2['default'].errorTypes[this.error_.code] + ')', this.error_.message, this.error_);
11677 * @event Player#error
11678 * @type {EventTarget~Event}
11680 this.trigger('error');
11686 * Report user activity
11688 * @param {Object} event
11693 Player.prototype.reportUserActivity = function reportUserActivity(event) {
11694 this.userActivity_ = true;
11698 * Get/set if user is active
11700 * @fires Player#useractive
11701 * @fires Player#userinactive
11703 * @param {boolean} [bool]
11704 * - true if the user is active
11705 * - false if the user is inactive
11706 * @return {boolean|Player}
11707 * - the current value of userActive when getting
11708 * - the player when setting
11712 Player.prototype.userActive = function userActive(bool) {
11713 if (bool !== undefined) {
11715 if (bool !== this.userActive_) {
11716 this.userActive_ = bool;
11718 // If the user was inactive and is now active we want to reset the
11719 // inactivity timer
11720 this.userActivity_ = true;
11721 this.removeClass('vjs-user-inactive');
11722 this.addClass('vjs-user-active');
11724 * @event Player#useractive
11725 * @type {EventTarget~Event}
11727 this.trigger('useractive');
11729 // We're switching the state to inactive manually, so erase any other
11731 this.userActivity_ = false;
11733 // Chrome/Safari/IE have bugs where when you change the cursor it can
11734 // trigger a mousemove event. This causes an issue when you're hiding
11735 // the cursor when the user is inactive, and a mousemove signals user
11736 // activity. Making it impossible to go into inactive mode. Specifically
11737 // this happens in fullscreen when we really need to hide the cursor.
11739 // When this gets resolved in ALL browsers it can be removed
11740 // https://code.google.com/p/chromium/issues/detail?id=103041
11742 this.tech_.one('mousemove', function (e) {
11743 e.stopPropagation();
11744 e.preventDefault();
11748 this.removeClass('vjs-user-active');
11749 this.addClass('vjs-user-inactive');
11751 * @event Player#userinactive
11752 * @type {EventTarget~Event}
11754 this.trigger('userinactive');
11759 return this.userActive_;
11763 * Listen for user activity based on timeout value
11769 Player.prototype.listenForUserActivity_ = function listenForUserActivity_() {
11770 var mouseInProgress = void 0;
11771 var lastMoveX = void 0;
11772 var lastMoveY = void 0;
11773 var handleActivity = Fn.bind(this, this.reportUserActivity);
11775 var handleMouseMove = function handleMouseMove(e) {
11776 // #1068 - Prevent mousemove spamming
11777 // Chrome Bug: https://code.google.com/p/chromium/issues/detail?id=366970
11778 if (e.screenX !== lastMoveX || e.screenY !== lastMoveY) {
11779 lastMoveX = e.screenX;
11780 lastMoveY = e.screenY;
11785 var handleMouseDown = function handleMouseDown() {
11787 // For as long as the they are touching the device or have their mouse down,
11788 // we consider them active even if they're not moving their finger or mouse.
11789 // So we want to continue to update that they are active
11790 this.clearInterval(mouseInProgress);
11791 // Setting userActivity=true now and setting the interval to the same time
11792 // as the activityCheck interval (250) should ensure we never miss the
11793 // next activityCheck
11794 mouseInProgress = this.setInterval(handleActivity, 250);
11797 var handleMouseUp = function handleMouseUp(event) {
11799 // Stop the interval that maintains activity if the mouse/touch is down
11800 this.clearInterval(mouseInProgress);
11803 // Any mouse movement will be considered user activity
11804 this.on('mousedown', handleMouseDown);
11805 this.on('mousemove', handleMouseMove);
11806 this.on('mouseup', handleMouseUp);
11808 // Listen for keyboard navigation
11809 // Shouldn't need to use inProgress interval because of key repeat
11810 this.on('keydown', handleActivity);
11811 this.on('keyup', handleActivity);
11813 // Run an interval every 250 milliseconds instead of stuffing everything into
11814 // the mousemove/touchmove function itself, to prevent performance degradation.
11815 // `this.reportUserActivity` simply sets this.userActivity_ to true, which
11816 // then gets picked up by this loop
11817 // http://ejohn.org/blog/learning-from-twitter/
11818 var inactivityTimeout = void 0;
11820 this.setInterval(function () {
11821 // Check to see if mouse/touch activity has happened
11822 if (this.userActivity_) {
11823 // Reset the activity tracker
11824 this.userActivity_ = false;
11826 // If the user state was inactive, set the state to active
11827 this.userActive(true);
11829 // Clear any existing inactivity timeout to start the timer over
11830 this.clearTimeout(inactivityTimeout);
11832 var timeout = this.options_.inactivityTimeout;
11835 // In <timeout> milliseconds, if no more activity has occurred the
11836 // user will be considered inactive
11837 inactivityTimeout = this.setTimeout(function () {
11838 // Protect against the case where the inactivityTimeout can trigger just
11839 // before the next user activity is picked up by the activity check loop
11840 // causing a flicker
11841 if (!this.userActivity_) {
11842 this.userActive(false);
11851 * Gets or sets the current playback rate. A playback rate of
11852 * 1.0 represents normal speed and 0.5 would indicate half-speed
11853 * playback, for instance.
11855 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-playbackrate
11857 * @param {number} [rate]
11858 * New playback rate to set.
11860 * @return {number|Player}
11861 * - The current playback rate when getting or 1.0
11862 * - the player when setting
11866 Player.prototype.playbackRate = function playbackRate(rate) {
11867 if (rate !== undefined) {
11868 this.techCall_('setPlaybackRate', rate);
11872 if (this.tech_ && this.tech_.featuresPlaybackRate) {
11873 return this.techGet_('playbackRate');
11879 * Gets or sets the audio flag
11881 * @param {boolean} bool
11882 * - true signals that this is an audio player
11883 * - false signals that this is not an audio player
11885 * @return {Player|boolean}
11886 * - the current value of isAudio when getting
11887 * - the player if setting
11891 Player.prototype.isAudio = function isAudio(bool) {
11892 if (bool !== undefined) {
11893 this.isAudio_ = !!bool;
11897 return !!this.isAudio_;
11901 * Get the {@link VideoTrackList}
11903 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist
11905 * @return {VideoTrackList}
11906 * the current video track list
11910 Player.prototype.videoTracks = function videoTracks() {
11911 // if we have not yet loadTech_, we create videoTracks_
11912 // these will be passed to the tech during loading
11914 this.videoTracks_ = this.videoTracks_ || new _videoTrackList2['default']();
11915 return this.videoTracks_;
11918 return this.tech_.videoTracks();
11922 * Get the {@link AudioTrackList}
11924 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist
11926 * @return {AudioTrackList}
11927 * the current audio track list
11931 Player.prototype.audioTracks = function audioTracks() {
11932 // if we have not yet loadTech_, we create videoTracks_
11933 // these will be passed to the tech during loading
11935 this.audioTracks_ = this.audioTracks_ || new _audioTrackList2['default']();
11936 return this.audioTracks_;
11939 return this.tech_.audioTracks();
11943 * Get the {@link TextTrackList}
11945 * Text tracks are tracks of timed text events.
11946 * - Captions: text displayed over the video
11947 * for the hearing impaired
11948 * - Subtitles: text displayed over the video for
11949 * those who don't understand language in the video
11950 * - Chapters: text displayed in a menu allowing the user to jump
11951 * to particular points (chapters) in the video
11952 * - Descriptions: (not yet implemented) audio descriptions that are read back to
11953 * the user by a screen reading device
11955 * @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks
11957 * @return {TextTrackList|undefined}
11958 * The current TextTrackList or undefined if
11959 * or undefined if we don't have a tech
11963 Player.prototype.textTracks = function textTracks() {
11964 // cannot use techGet_ directly because it checks to see whether the tech is ready.
11965 // Flash is unlikely to be ready in time but textTracks should still work.
11967 return this.tech_.textTracks();
11972 * Get the "remote" {@link TextTrackList}. Remote Text Tracks
11973 * are tracks that were added to the HTML video element and can
11974 * be removed, whereas normal texttracks cannot be removed.
11977 * @return {TextTrackList|undefined}
11978 * The current remote text track list or undefined
11979 * if we don't have a tech
11983 Player.prototype.remoteTextTracks = function remoteTextTracks() {
11985 return this.tech_.remoteTextTracks();
11990 * Get the "remote" {@link HTMLTrackElementList}.
11991 * This gives the user all of the DOM elements that match up
11992 * with the remote {@link TextTrackList}.
11994 * @return {HTMLTrackElementList}
11995 * The current remote text track list elements
11996 * or undefined if we don't have a tech
12000 Player.prototype.remoteTextTrackEls = function remoteTextTrackEls() {
12002 return this.tech_.remoteTextTrackEls();
12007 * A helper method for adding a {@link TextTrack} to our
12008 * {@link TextTrackList}.
12010 * In addition to the W3C settings we allow adding additional info through options.
12012 * @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack
12014 * @param {string} [kind]
12015 * the kind of TextTrack you are adding
12017 * @param {string} [label]
12018 * the label to give the TextTrack label
12020 * @param {string} [language]
12021 * the language to set on the TextTrack
12023 * @return {TextTrack|undefined}
12024 * the TextTrack that was added or undefined
12025 * if there is no tech
12029 Player.prototype.addTextTrack = function addTextTrack(kind, label, language) {
12031 return this.tech_.addTextTrack(kind, label, language);
12036 * Create a remote {@link TextTrack} and an {@link HTMLTrackElement}. It will
12037 * automatically removed from the video element whenever the source changes, unless
12038 * manualCleanup is set to false.
12040 * @param {Object} options
12041 * Options to pass to {@link HTMLTrackElement} during creation. See
12042 * {@link HTMLTrackElement} for object properties that you should use.
12044 * @param {boolean} [manualCleanup=true] if set to false, the TextTrack will be
12046 * @return {HTMLTrackElement}
12047 * the HTMLTrackElement that was created and added
12048 * to the HTMLTrackElementList and the remote
12051 * @deprecated The default value of the "manualCleanup" parameter will default
12052 * to "false" in upcoming versions of Video.js
12056 Player.prototype.addRemoteTextTrack = function addRemoteTextTrack(options, manualCleanup) {
12058 return this.tech_.addRemoteTextTrack(options, manualCleanup);
12063 * Remove a remote {@link TextTrack} from the respective
12064 * {@link TextTrackList} and {@link HTMLTrackElementList}.
12066 * @param {Object} track
12067 * Remote {@link TextTrack} to remove
12069 * @return {undefined}
12070 * does not return anything
12074 Player.prototype.removeRemoteTextTrack = function removeRemoteTextTrack() {
12075 var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
12076 _ref3$track = _ref3.track,
12077 track = _ref3$track === undefined ? arguments[0] : _ref3$track;
12079 // destructure the input into an object with a track argument, defaulting to arguments[0]
12080 // default the whole argument to an empty object if nothing was passed in
12083 return this.tech_.removeRemoteTextTrack(track);
12091 * current video width
12095 Player.prototype.videoWidth = function videoWidth() {
12096 return this.tech_ && this.tech_.videoWidth && this.tech_.videoWidth() || 0;
12103 * current video height
12107 Player.prototype.videoHeight = function videoHeight() {
12108 return this.tech_ && this.tech_.videoHeight && this.tech_.videoHeight() || 0;
12111 // Methods to add support for
12112 // initialTime: function() { return this.techCall_('initialTime'); },
12113 // startOffsetTime: function() { return this.techCall_('startOffsetTime'); },
12114 // played: function() { return this.techCall_('played'); },
12115 // defaultPlaybackRate: function() { return this.techCall_('defaultPlaybackRate'); },
12116 // defaultMuted: function() { return this.techCall_('defaultMuted'); }
12119 * The player's language code
12120 * NOTE: The language should be set in the player options if you want the
12121 * the controls to be built with a specific language. Changing the language
12122 * later will not update controls text.
12124 * @param {string} [code]
12125 * the language code to set the player to
12127 * @return {string|Player}
12128 * - The current language code when getting
12129 * - A reference to the player when setting
12133 Player.prototype.language = function language(code) {
12134 if (code === undefined) {
12135 return this.language_;
12138 this.language_ = String(code).toLowerCase();
12143 * Get the player's language dictionary
12144 * Merge every time, because a newly added plugin might call videojs.addLanguage() at any time
12145 * Languages specified directly in the player options have precedence
12148 * An array of of supported languages
12152 Player.prototype.languages = function languages() {
12153 return (0, _mergeOptions2['default'])(Player.prototype.options_.languages, this.languages_);
12157 * returns a JavaScript object representing the current track
12158 * information. **DOES not return it as JSON**
12161 * Object representing the current of track info
12165 Player.prototype.toJSON = function toJSON() {
12166 var options = (0, _mergeOptions2['default'])(this.options_);
12167 var tracks = options.tracks;
12169 options.tracks = [];
12171 for (var i = 0; i < tracks.length; i++) {
12172 var track = tracks[i];
12174 // deep merge tracks and null out player so no circular references
12175 track = (0, _mergeOptions2['default'])(track);
12176 track.player = undefined;
12177 options.tracks[i] = track;
12184 * Creates a simple modal dialog (an instance of the {@link ModalDialog}
12185 * component) that immediately overlays the player with arbitrary
12186 * content and removes itself when closed.
12188 * @param {string|Function|Element|Array|null} content
12189 * Same as {@link ModalDialog#content}'s param of the same name.
12190 * The most straight-forward usage is to provide a string or DOM
12193 * @param {Object} [options]
12194 * Extra options which will be passed on to the {@link ModalDialog}.
12196 * @return {ModalDialog}
12197 * the {@link ModalDialog} that was created
12201 Player.prototype.createModal = function createModal(content, options) {
12204 options = options || {};
12205 options.content = content || '';
12207 var modal = new _modalDialog2['default'](this, options);
12209 this.addChild(modal);
12210 modal.on('dispose', function () {
12211 _this5.removeChild(modal);
12214 return modal.open();
12218 * Gets tag settings
12220 * @param {Element} tag
12224 * An object containing all of the settings
12229 Player.getTagSettings = function getTagSettings(tag) {
12230 var baseOptions = {
12235 var tagOptions = Dom.getElAttributes(tag);
12236 var dataSetup = tagOptions['data-setup'];
12238 if (Dom.hasElClass(tag, 'vjs-fluid')) {
12239 tagOptions.fluid = true;
12242 // Check if data-setup attr exists.
12243 if (dataSetup !== null) {
12244 // Parse options JSON
12245 // If empty string, make it a parsable json object.
12246 var _safeParseTuple = (0, _tuple2['default'])(dataSetup || '{}'),
12247 err = _safeParseTuple[0],
12248 data = _safeParseTuple[1];
12251 _log2['default'].error(err);
12253 (0, _obj.assign)(tagOptions, data);
12256 (0, _obj.assign)(baseOptions, tagOptions);
12258 // Get tag children settings
12259 if (tag.hasChildNodes()) {
12260 var children = tag.childNodes;
12262 for (var i = 0, j = children.length; i < j; i++) {
12263 var child = children[i];
12264 // Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
12265 var childName = child.nodeName.toLowerCase();
12267 if (childName === 'source') {
12268 baseOptions.sources.push(Dom.getElAttributes(child));
12269 } else if (childName === 'track') {
12270 baseOptions.tracks.push(Dom.getElAttributes(child));
12275 return baseOptions;
12279 * Determine whether or not flexbox is supported
12281 * @return {boolean}
12282 * - true if flexbox is supported
12283 * - false if flexbox is not supported
12287 Player.prototype.flexNotSupported_ = function flexNotSupported_() {
12288 var elem = _document2['default'].createElement('i');
12290 // Note: We don't actually use flexBasis (or flexOrder), but it's one of the more
12291 // common flex features that we can rely on when checking for flex support.
12292 return !('flexBasis' in elem.style || 'webkitFlexBasis' in elem.style || 'mozFlexBasis' in elem.style || 'msFlexBasis' in elem.style ||
12293 // IE10-specific (2012 flex spec)
12294 'msFlexOrder' in elem.style);
12298 }(_component2['default']);
12301 * Global player list
12307 Player.players = {};
12309 var navigator = _window2['default'].navigator;
12312 * Player instance options, surfaced using options
12313 * options = Player.prototype.options_
12314 * Make changes in options, not here.
12319 Player.prototype.options_ = {
12320 // Default order of fallback technology
12321 techOrder: ['html5', 'flash'],
12322 // techOrder: ['flash','html5'],
12327 // defaultVolume: 0.85,
12328 defaultVolume: 0.00,
12330 // default inactivity timeout
12331 inactivityTimeout: 2000,
12333 // default playback rates
12335 // Add playback rate selection by adding rates
12336 // 'playbackRates': [0.5, 1, 1.5, 2],
12338 // Included control sets
12339 children: ['mediaLoader', 'posterImage', 'textTrackDisplay', 'loadingSpinner', 'bigPlayButton', 'controlBar', 'errorDisplay', 'textTrackSettings'],
12341 language: navigator && (navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language) || 'en',
12343 // locales and their language translations
12346 // Default message to show when a video cannot be played.
12347 notSupportedMessage: 'No compatible source was found for this media.'
12352 * Returns whether or not the player is in the "ended" state.
12354 * @return {Boolean} True if the player is in the ended state, false if not.
12355 * @method Player#ended
12359 * Returns whether or not the player is in the "seeking" state.
12361 * @return {Boolean} True if the player is in the seeking state, false if not.
12362 * @method Player#seeking
12366 * Returns the TimeRanges of the media that are currently available
12369 * @return {TimeRanges} the seekable intervals of the media timeline
12370 * @method Player#seekable
12374 * Returns the current state of network activity for the element, from
12375 * the codes in the list below.
12376 * - NETWORK_EMPTY (numeric value 0)
12377 * The element has not yet been initialised. All attributes are in
12378 * their initial states.
12379 * - NETWORK_IDLE (numeric value 1)
12380 * The element's resource selection algorithm is active and has
12381 * selected a resource, but it is not actually using the network at
12383 * - NETWORK_LOADING (numeric value 2)
12384 * The user agent is actively trying to download data.
12385 * - NETWORK_NO_SOURCE (numeric value 3)
12386 * The element's resource selection algorithm is active, but it has
12387 * not yet found a resource to use.
12389 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#network-states
12390 * @return {number} the current network activity state
12391 * @method Player#networkState
12395 * Returns a value that expresses the current state of the element
12396 * with respect to rendering the current playback position, from the
12397 * codes in the list below.
12398 * - HAVE_NOTHING (numeric value 0)
12399 * No information regarding the media resource is available.
12400 * - HAVE_METADATA (numeric value 1)
12401 * Enough of the resource has been obtained that the duration of the
12402 * resource is available.
12403 * - HAVE_CURRENT_DATA (numeric value 2)
12404 * Data for the immediate current playback position is available.
12405 * - HAVE_FUTURE_DATA (numeric value 3)
12406 * Data for the immediate current playback position is available, as
12407 * well as enough data for the user agent to advance the current
12408 * playback position in the direction of playback.
12409 * - HAVE_ENOUGH_DATA (numeric value 4)
12410 * The user agent estimates that enough data is available for
12411 * playback to proceed uninterrupted.
12413 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-readystate
12414 * @return {number} the current playback rendering state
12415 * @method Player#readyState
12417 'readyState'].forEach(function (fn) {
12418 Player.prototype[fn] = function () {
12419 return this.techGet_(fn);
12423 TECH_EVENTS_RETRIGGER.forEach(function (event) {
12424 Player.prototype['handleTech' + (0, _toTitleCase2['default'])(event) + '_'] = function () {
12425 return this.trigger(event);
12430 * Fired when the player has initial duration and dimension information
12432 * @event Player#loadedmetadata
12433 * @type {EventTarget~Event}
12437 * Fired when the player has downloaded data at the current playback position
12439 * @event Player#loadeddata
12440 * @type {EventTarget~Event}
12444 * Fired when the current playback position has changed *
12445 * During playback this is fired every 15-250 milliseconds, depending on the
12446 * playback technology in use.
12448 * @event Player#timeupdate
12449 * @type {EventTarget~Event}
12453 * Fired when the volume changes
12455 * @event Player#volumechange
12456 * @type {EventTarget~Event}
12459 _component2['default'].registerComponent('Player', Player);
12460 exports['default'] = Player;
12462 },{"1":1,"4":4,"41":41,"44":44,"45":45,"46":46,"5":5,"50":50,"55":55,"59":59,"60":60,"61":61,"62":62,"63":63,"68":68,"69":69,"71":71,"76":76,"78":78,"79":79,"8":8,"81":81,"82":82,"83":83,"85":85,"86":86,"87":87,"88":88,"89":89,"90":90,"91":91,"94":94,"95":95,"97":97}],52:[function(_dereq_,module,exports){
12465 exports.__esModule = true;
12467 var _player = _dereq_(51);
12469 var _player2 = _interopRequireDefault(_player);
12471 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12474 * The method for registering a video.js plugin. {@link videojs:videojs.registerPlugin].
12476 * @param {string} name
12477 * The name of the plugin that is being registered
12479 * @param {plugins:PluginFn} init
12480 * The function that gets run when a `Player` initializes.
12482 var plugin = function plugin(name, init) {
12483 _player2['default'].prototype[name] = init;
12488 exports['default'] = plugin;
12490 },{"51":51}],53:[function(_dereq_,module,exports){
12493 exports.__esModule = true;
12495 var _clickableComponent = _dereq_(3);
12497 var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
12499 var _component = _dereq_(5);
12501 var _component2 = _interopRequireDefault(_component);
12503 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12505 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
12507 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
12509 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
12510 * @file popup-button.js
12515 * A button class for use with {@link Popup} controls
12517 * @extends ClickableComponent
12519 var PopupButton = function (_ClickableComponent) {
12520 _inherits(PopupButton, _ClickableComponent);
12523 * Create an instance of this class.
12525 * @param {Player} player
12526 * The `Player` that this class should be attached to.
12528 * @param {Object} [options]
12529 * The key/value store of player options.
12531 function PopupButton(player) {
12532 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
12534 _classCallCheck(this, PopupButton);
12536 var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
12543 * Update the `Popup` that this button is attached to.
12547 PopupButton.prototype.update = function update() {
12548 var popup = this.createPopup();
12551 this.removeChild(this.popup);
12554 this.popup = popup;
12555 this.addChild(popup);
12557 if (this.items && this.items.length === 0) {
12559 } else if (this.items && this.items.length > 1) {
12565 * Create a `Popup`. - Override with specific functionality for component
12571 PopupButton.prototype.createPopup = function createPopup() {};
12574 * Create the `PopupButton`s DOM element.
12576 * @return {Element}
12577 * The element that gets created.
12581 PopupButton.prototype.createEl = function createEl() {
12582 return _ClickableComponent.prototype.createEl.call(this, 'div', {
12583 className: this.buildCSSClass()
12588 * Builds the default DOM `className`.
12591 * The DOM `className` for this object.
12595 PopupButton.prototype.buildCSSClass = function buildCSSClass() {
12596 var menuButtonClass = 'vjs-menu-button';
12598 // If the inline option is passed, we want to use different styles altogether.
12599 if (this.options_.inline === true) {
12600 menuButtonClass += '-inline';
12602 menuButtonClass += '-popup';
12605 return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this);
12608 return PopupButton;
12609 }(_clickableComponent2['default']);
12611 _component2['default'].registerComponent('PopupButton', PopupButton);
12612 exports['default'] = PopupButton;
12614 },{"3":3,"5":5}],54:[function(_dereq_,module,exports){
12617 exports.__esModule = true;
12619 var _component = _dereq_(5);
12621 var _component2 = _interopRequireDefault(_component);
12623 var _dom = _dereq_(81);
12625 var Dom = _interopRequireWildcard(_dom);
12627 var _fn = _dereq_(83);
12629 var Fn = _interopRequireWildcard(_fn);
12631 var _events = _dereq_(82);
12633 var Events = _interopRequireWildcard(_events);
12635 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12637 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12639 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
12641 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
12643 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
12649 * The Popup component is used to build pop up controls.
12651 * @extends Component
12653 var Popup = function (_Component) {
12654 _inherits(Popup, _Component);
12657 _classCallCheck(this, Popup);
12659 return _possibleConstructorReturn(this, _Component.apply(this, arguments));
12663 * Add a popup item to the popup
12665 * @param {Object|string} component
12666 * Component or component type to add
12669 Popup.prototype.addItem = function addItem(component) {
12670 this.addChild(component);
12671 component.on('click', Fn.bind(this, function () {
12672 this.unlockShowing();
12677 * Create the `PopupButton`s DOM element.
12679 * @return {Element}
12680 * The element that gets created.
12684 Popup.prototype.createEl = function createEl() {
12685 var contentElType = this.options_.contentElType || 'ul';
12687 this.contentEl_ = Dom.createEl(contentElType, {
12688 className: 'vjs-menu-content'
12691 var el = _Component.prototype.createEl.call(this, 'div', {
12692 append: this.contentEl_,
12693 className: 'vjs-menu'
12696 el.appendChild(this.contentEl_);
12698 // Prevent clicks from bubbling up. Needed for Popup Buttons,
12699 // where a click on the parent is significant
12700 Events.on(el, 'click', function (event) {
12701 event.preventDefault();
12702 event.stopImmediatePropagation();
12709 }(_component2['default']);
12711 _component2['default'].registerComponent('Popup', Popup);
12712 exports['default'] = Popup;
12714 },{"5":5,"81":81,"82":82,"83":83}],55:[function(_dereq_,module,exports){
12717 exports.__esModule = true;
12719 var _clickableComponent = _dereq_(3);
12721 var _clickableComponent2 = _interopRequireDefault(_clickableComponent);
12723 var _component = _dereq_(5);
12725 var _component2 = _interopRequireDefault(_component);
12727 var _fn = _dereq_(83);
12729 var Fn = _interopRequireWildcard(_fn);
12731 var _dom = _dereq_(81);
12733 var Dom = _interopRequireWildcard(_dom);
12735 var _browser = _dereq_(78);
12737 var browser = _interopRequireWildcard(_browser);
12739 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12741 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12743 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
12745 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
12747 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
12748 * @file poster-image.js
12753 * A `ClickableComponent` that handles showing the poster image for the player.
12755 * @extends ClickableComponent
12757 var PosterImage = function (_ClickableComponent) {
12758 _inherits(PosterImage, _ClickableComponent);
12761 * Create an instance of this class.
12763 * @param {Player} player
12764 * The `Player` that this class should attach to.
12766 * @param {Object} [options]
12767 * The key/value store of player options.
12769 function PosterImage(player, options) {
12770 _classCallCheck(this, PosterImage);
12772 var _this = _possibleConstructorReturn(this, _ClickableComponent.call(this, player, options));
12775 player.on('posterchange', Fn.bind(_this, _this.update));
12780 * Clean up and dispose of the `PosterImage`.
12784 PosterImage.prototype.dispose = function dispose() {
12785 this.player().off('posterchange', this.update);
12786 _ClickableComponent.prototype.dispose.call(this);
12790 * Create the `PosterImage`s DOM element.
12792 * @return {Element}
12793 * The element that gets created.
12797 PosterImage.prototype.createEl = function createEl() {
12798 var el = Dom.createEl('div', {
12799 className: 'vjs-poster',
12801 // Don't want poster to be tabbable.
12805 // To ensure the poster image resizes while maintaining its original aspect
12806 // ratio, use a div with `background-size` when available. For browsers that
12807 // do not support `background-size` (e.g. IE8), fall back on using a regular
12809 if (!browser.BACKGROUND_SIZE_SUPPORTED) {
12810 this.fallbackImg_ = Dom.createEl('img');
12811 el.appendChild(this.fallbackImg_);
12818 * An {@link EventTarget~EventListener} for {@link Player#posterchange} events.
12820 * @listens Player#posterchange
12822 * @param {EventTarget~Event} [event]
12823 * The `Player#posterchange` event that triggered this function.
12827 PosterImage.prototype.update = function update(event) {
12828 var url = this.player().poster();
12832 // If there's no poster source we should display:none on this component
12833 // so it's not still clickable or right-clickable
12842 * Set the source of the `PosterImage` depending on the display method.
12844 * @param {string} url
12845 * The URL to the source for the `PosterImage`.
12849 PosterImage.prototype.setSrc = function setSrc(url) {
12850 if (this.fallbackImg_) {
12851 this.fallbackImg_.src = url;
12853 var backgroundImage = '';
12855 // Any falsey values should stay as an empty string, otherwise
12856 // this will throw an extra error
12858 backgroundImage = 'url("' + url + '")';
12861 this.el_.style.backgroundImage = backgroundImage;
12866 * An {@link EventTarget~EventListener} for clicks on the `PosterImage`. See
12867 * {@link ClickableComponent#handleClick} for instances where this will be triggered.
12873 * @param {EventTarget~Event} event
12874 + The `click`, `tap` or `keydown` event that caused this function to be called.
12878 PosterImage.prototype.handleClick = function handleClick(event) {
12879 // We don't want a click to trigger playback when controls are disabled
12880 // but CSS should be hiding the poster to prevent that from happening
12881 if (this.player_.paused()) {
12882 this.player_.play();
12884 this.player_.pause();
12888 return PosterImage;
12889 }(_clickableComponent2['default']);
12891 _component2['default'].registerComponent('PosterImage', PosterImage);
12892 exports['default'] = PosterImage;
12894 },{"3":3,"5":5,"78":78,"81":81,"83":83}],56:[function(_dereq_,module,exports){
12897 exports.__esModule = true;
12898 exports.hasLoaded = exports.autoSetupTimeout = exports.autoSetup = undefined;
12900 var _dom = _dereq_(81);
12902 var Dom = _interopRequireWildcard(_dom);
12904 var _events = _dereq_(82);
12906 var Events = _interopRequireWildcard(_events);
12908 var _document = _dereq_(94);
12910 var _document2 = _interopRequireDefault(_document);
12912 var _window = _dereq_(95);
12914 var _window2 = _interopRequireDefault(_window);
12916 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12918 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
12921 * @file setup.js - Functions for setting up a player without
12922 * user interaction based on the data-setup `attribute` of the video tag.
12926 var _windowLoaded = false;
12927 var videojs = void 0;
12930 * Set up any tags that have a data-setup `attribute` when the player is started.
12932 var autoSetup = function autoSetup() {
12934 // Protect against breakage in non-browser environments.
12935 if (!Dom.isReal()) {
12939 // One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
12940 // var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
12941 // var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
12942 // var mediaEls = vids.concat(audios);
12944 // Because IE8 doesn't support calling slice on a node list, we need to loop
12945 // through each list of elements to build up a new, combined list of elements.
12946 var vids = _document2['default'].getElementsByTagName('video');
12947 var audios = _document2['default'].getElementsByTagName('audio');
12950 if (vids && vids.length > 0) {
12951 for (var i = 0, e = vids.length; i < e; i++) {
12952 mediaEls.push(vids[i]);
12956 if (audios && audios.length > 0) {
12957 for (var _i = 0, _e = audios.length; _i < _e; _i++) {
12958 mediaEls.push(audios[_i]);
12962 // Check if any media elements exist
12963 if (mediaEls && mediaEls.length > 0) {
12965 for (var _i2 = 0, _e2 = mediaEls.length; _i2 < _e2; _i2++) {
12966 var mediaEl = mediaEls[_i2];
12968 // Check if element exists, has getAttribute func.
12969 // IE seems to consider typeof el.getAttribute == 'object' instead of
12970 // 'function' like expected, at least when loading the player immediately.
12971 if (mediaEl && mediaEl.getAttribute) {
12973 // Make sure this player hasn't already been set up.
12974 if (mediaEl.player === undefined) {
12975 var options = mediaEl.getAttribute('data-setup');
12977 // Check if data-setup attr exists.
12978 // We only auto-setup if they've added the data-setup attr.
12979 if (options !== null) {
12980 // Create new video.js instance.
12985 // If getAttribute isn't defined, we need to wait for the DOM.
12987 autoSetupTimeout(1);
12992 // No videos were found, so keep looping unless page is finished loading.
12993 } else if (!_windowLoaded) {
12994 autoSetupTimeout(1);
12999 * Wait until the page is loaded before running autoSetup. This will be called in
13000 * autoSetup if `hasLoaded` returns false.
13002 * @param {number} wait
13003 * How long to wait in ms
13005 * @param {videojs} [vjs]
13006 * The videojs library function
13008 function autoSetupTimeout(wait, vjs) {
13013 _window2['default'].setTimeout(autoSetup, wait);
13016 if (Dom.isReal() && _document2['default'].readyState === 'complete') {
13017 _windowLoaded = true;
13020 * Listen for the load event on window, and set _windowLoaded to true.
13024 Events.one(_window2['default'], 'load', function () {
13025 _windowLoaded = true;
13030 * check if the document has been loaded
13032 var hasLoaded = function hasLoaded() {
13033 return _windowLoaded;
13036 exports.autoSetup = autoSetup;
13037 exports.autoSetupTimeout = autoSetupTimeout;
13038 exports.hasLoaded = hasLoaded;
13040 },{"81":81,"82":82,"94":94,"95":95}],57:[function(_dereq_,module,exports){
13043 exports.__esModule = true;
13045 var _component = _dereq_(5);
13047 var _component2 = _interopRequireDefault(_component);
13049 var _dom = _dereq_(81);
13051 var Dom = _interopRequireWildcard(_dom);
13053 var _obj = _dereq_(88);
13055 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
13057 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
13059 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
13061 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
13063 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
13069 * The base functionality for a slider. Can be vertical or horizontal.
13070 * For instance the volume bar or the seek bar on a video is a slider.
13072 * @extends Component
13074 var Slider = function (_Component) {
13075 _inherits(Slider, _Component);
13078 * Create an instance of this class
13080 * @param {Player} player
13081 * The `Player` that this class should be attached to.
13083 * @param {Object} [options]
13084 * The key/value store of player options.
13086 function Slider(player, options) {
13087 _classCallCheck(this, Slider);
13089 // Set property names to bar to match with the child Slider class is looking for
13090 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
13092 _this.bar = _this.getChild(_this.options_.barName);
13094 // Set a horizontal or vertical class on the slider depending on the slider type
13095 _this.vertical(!!_this.options_.vertical);
13097 _this.on('mousedown', _this.handleMouseDown);
13098 _this.on('touchstart', _this.handleMouseDown);
13099 _this.on('focus', _this.handleFocus);
13100 _this.on('blur', _this.handleBlur);
13101 _this.on('click', _this.handleClick);
13103 _this.on(player, 'controlsvisible', _this.update);
13104 _this.on(player, _this.playerEvent, _this.update);
13109 * Create the `Button`s DOM element.
13111 * @param {string} type
13112 * Type of element to create.
13114 * @param {Object} [props={}]
13115 * List of properties in Object form.
13117 * @param {Object} [attributes={}]
13118 * list of attributes in Object form.
13120 * @return {Element}
13121 * The element that gets created.
13125 Slider.prototype.createEl = function createEl(type) {
13126 var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
13127 var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
13129 // Add the slider element class to all sub classes
13130 props.className = props.className + ' vjs-slider';
13131 props = (0, _obj.assign)({
13135 attributes = (0, _obj.assign)({
13137 'aria-valuenow': 0,
13138 'aria-valuemin': 0,
13139 'aria-valuemax': 100,
13143 return _Component.prototype.createEl.call(this, type, props, attributes);
13147 * Handle `mousedown` or `touchstart` events on the `Slider`.
13149 * @param {EventTarget~Event} event
13150 * `mousedown` or `touchstart` event that triggered this function
13152 * @listens mousedown
13153 * @listens touchstart
13154 * @fires Slider#slideractive
13158 Slider.prototype.handleMouseDown = function handleMouseDown(event) {
13159 var doc = this.bar.el_.ownerDocument;
13161 event.preventDefault();
13162 Dom.blockTextSelection();
13164 this.addClass('vjs-sliding');
13166 * Triggered when the slider is in an active state
13168 * @event Slider#slideractive
13169 * @type {EventTarget~Event}
13171 this.trigger('slideractive');
13173 this.on(doc, 'mousemove', this.handleMouseMove);
13174 this.on(doc, 'mouseup', this.handleMouseUp);
13175 this.on(doc, 'touchmove', this.handleMouseMove);
13176 this.on(doc, 'touchend', this.handleMouseUp);
13178 this.handleMouseMove(event);
13182 * Handle the `mousemove`, `touchmove`, and `mousedown` events on this `Slider`.
13183 * The `mousemove` and `touchmove` events will only only trigger this function during
13184 * `mousedown` and `touchstart`. This is due to {@link Slider#handleMouseDown} and
13185 * {@link Slider#handleMouseUp}.
13187 * @param {EventTarget~Event} event
13188 * `mousedown`, `mousemove`, `touchstart`, or `touchmove` event that triggered
13191 * @listens mousemove
13192 * @listens touchmove
13196 Slider.prototype.handleMouseMove = function handleMouseMove(event) {};
13199 * Handle `mouseup` or `touchend` events on the `Slider`.
13201 * @param {EventTarget~Event} event
13202 * `mouseup` or `touchend` event that triggered this function.
13204 * @listens touchend
13206 * @fires Slider#sliderinactive
13210 Slider.prototype.handleMouseUp = function handleMouseUp() {
13211 var doc = this.bar.el_.ownerDocument;
13213 Dom.unblockTextSelection();
13215 this.removeClass('vjs-sliding');
13217 * Triggered when the slider is no longer in an active state.
13219 * @event Slider#sliderinactive
13220 * @type {EventTarget~Event}
13222 this.trigger('sliderinactive');
13224 this.off(doc, 'mousemove', this.handleMouseMove);
13225 this.off(doc, 'mouseup', this.handleMouseUp);
13226 this.off(doc, 'touchmove', this.handleMouseMove);
13227 this.off(doc, 'touchend', this.handleMouseUp);
13233 * Update the progress bar of the `Slider`.
13237 Slider.prototype.update = function update() {
13238 // In VolumeBar init we have a setTimeout for update that pops and update to the end of the
13239 // execution stack. The player is destroyed before then update will cause an error
13244 // If scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
13245 // On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
13246 // var progress = (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration();
13247 var progress = this.getPercent();
13248 var bar = this.bar;
13250 // If there's no bar...
13255 // Protect against no duration and other division issues
13256 if (typeof progress !== 'number' || progress !== progress || progress < 0 || progress === Infinity) {
13260 // Convert to a percentage for setting
13261 var percentage = (progress * 100).toFixed(2) + '%';
13263 // Set the new bar width or height
13264 if (this.vertical()) {
13265 bar.el().style.height = percentage;
13267 bar.el().style.width = percentage;
13272 * Calculate distance for slider
13274 * @param {EventTarget~Event} event
13275 * The event that caused this function to run.
13278 * The current position of the Slider.
13279 * - position.x for vertical `Slider`s
13280 * - position.y for horizontal `Slider`s
13284 Slider.prototype.calculateDistance = function calculateDistance(event) {
13285 var position = Dom.getPointerPosition(this.el_, event);
13287 if (this.vertical()) {
13294 * Handle a `focus` event on this `Slider`.
13296 * @param {EventTarget~Event} event
13297 * The `focus` event that caused this function to run.
13303 Slider.prototype.handleFocus = function handleFocus() {
13304 this.on(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress);
13308 * Handle a `keydown` event on the `Slider`. Watches for left, right, up, and down
13309 * arrow keys. This function will only be called when the slider has focus. See
13310 * {@link Slider#handleFocus} and {@link Slider#handleBlur}.
13312 * @param {EventTarget~Event} event
13313 * the `keydown` event that caused this function to run.
13319 Slider.prototype.handleKeyPress = function handleKeyPress(event) {
13320 // Left and Down Arrows
13321 if (event.which === 37 || event.which === 40) {
13322 event.preventDefault();
13325 // Up and Right Arrows
13326 } else if (event.which === 38 || event.which === 39) {
13327 event.preventDefault();
13328 this.stepForward();
13333 * Handle a `blur` event on this `Slider`.
13335 * @param {EventTarget~Event} event
13336 * The `blur` event that caused this function to run.
13341 Slider.prototype.handleBlur = function handleBlur() {
13342 this.off(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress);
13346 * Listener for click events on slider, used to prevent clicks
13347 * from bubbling up to parent elements like button menus.
13349 * @param {Object} event
13350 * Event that caused this object to run
13354 Slider.prototype.handleClick = function handleClick(event) {
13355 event.stopImmediatePropagation();
13356 event.preventDefault();
13360 * Get/set if slider is horizontal for vertical
13362 * @param {boolean} [bool]
13363 * - true if slider is vertical,
13364 * - false is horizontal
13366 * @return {boolean|Slider}
13367 * - true if slider is vertical, and getting
13368 * - false is horizontal, and getting
13369 * - a reference to this object when setting
13373 Slider.prototype.vertical = function vertical(bool) {
13374 if (bool === undefined) {
13375 return this.vertical_ || false;
13378 this.vertical_ = !!bool;
13380 if (this.vertical_) {
13381 this.addClass('vjs-slider-vertical');
13383 this.addClass('vjs-slider-horizontal');
13390 }(_component2['default']);
13392 _component2['default'].registerComponent('Slider', Slider);
13393 exports['default'] = Slider;
13395 },{"5":5,"81":81,"88":88}],58:[function(_dereq_,module,exports){
13398 exports.__esModule = true;
13400 * @file flash-rtmp.js
13401 * @module flash-rtmp
13405 * Add RTMP properties to the {@link Flash} Tech.
13407 * @param {Flash} Flash
13408 * The flash tech class.
13410 * @mixin FlashRtmpDecorator
13412 function FlashRtmpDecorator(Flash) {
13413 Flash.streamingFormats = {
13419 * Join connection and stream with an ampersand.
13421 * @param {string} connection
13422 * The connection string.
13424 * @param {string} stream
13425 * The stream string.
13427 Flash.streamFromParts = function (connection, stream) {
13428 return connection + '&' + stream;
13432 * The flash parts object that contains connection and stream info.
13434 * @typedef {Object} Flash~PartsObject
13436 * @property {string} connection
13437 * The connection string of a source, defaults to an empty string.
13439 * @property {string} stream
13440 * The stream string of the source, defaults to an empty string.
13444 * Convert a source url into a stream and connection parts.
13446 * @param {string} src
13449 * @return {Flash~PartsObject}
13450 * The parts object that contains a connection and a stream
13452 Flash.streamToParts = function (src) {
13462 // Look for the normal URL separator we expect, '&'.
13463 // If found, we split the URL into two pieces around the
13465 var connEnd = src.search(/&(?!\w+=)/);
13466 var streamBegin = void 0;
13468 if (connEnd !== -1) {
13469 streamBegin = connEnd + 1;
13471 // If there's not a '&', we use the last '/' as the delimiter.
13472 connEnd = streamBegin = src.lastIndexOf('/') + 1;
13473 if (connEnd === 0) {
13474 // really, there's not a '/'?
13475 connEnd = streamBegin = src.length;
13479 parts.connection = src.substring(0, connEnd);
13480 parts.stream = src.substring(streamBegin, src.length);
13486 * Check if the source type is a streaming type.
13488 * @param {string} srcType
13489 * The mime type to check.
13491 * @return {boolean}
13492 * - True if the source type is a streaming type.
13493 * - False if the source type is not a streaming type.
13495 Flash.isStreamingType = function (srcType) {
13496 return srcType in Flash.streamingFormats;
13499 // RTMP has four variations, any string starting
13500 // with one of these protocols should be valid
13503 * Regular expression used to check if the source is an rtmp source.
13505 * @property {RegExp} Flash.RTMP_RE
13507 Flash.RTMP_RE = /^rtmp[set]?:\/\//i;
13510 * Check if the source itself is a streaming type.
13512 * @param {string} src
13513 * The url to the source.
13515 * @return {boolean}
13516 * - True if the source url indicates that the source is streaming.
13517 * - False if the shource url indicates that the source url is not streaming.
13519 Flash.isStreamingSrc = function (src) {
13520 return Flash.RTMP_RE.test(src);
13524 * A source handler for RTMP urls
13527 Flash.rtmpSourceHandler = {};
13530 * Check if Flash can play the given mime type.
13532 * @param {string} type
13533 * The mime type to check
13536 * 'maybe', or '' (empty string)
13538 Flash.rtmpSourceHandler.canPlayType = function (type) {
13539 if (Flash.isStreamingType(type)) {
13547 * Check if Flash can handle the source natively
13549 * @param {Object} source
13550 * The source object
13552 * @param {Object} [options]
13553 * The options passed to the tech
13556 * 'maybe', or '' (empty string)
13558 Flash.rtmpSourceHandler.canHandleSource = function (source, options) {
13559 var can = Flash.rtmpSourceHandler.canPlayType(source.type);
13565 if (Flash.isStreamingSrc(source.src)) {
13573 * Pass the source to the flash object.
13575 * @param {Object} source
13576 * The source object
13578 * @param {Flash} tech
13579 * The instance of the Flash tech
13581 * @param {Object} [options]
13582 * The options to pass to the source
13584 Flash.rtmpSourceHandler.handleSource = function (source, tech, options) {
13585 var srcParts = Flash.streamToParts(source.src);
13587 tech.setRtmpConnection(srcParts.connection);
13588 tech.setRtmpStream(srcParts.stream);
13591 // Register the native source handler
13592 Flash.registerSourceHandler(Flash.rtmpSourceHandler);
13597 exports['default'] = FlashRtmpDecorator;
13599 },{}],59:[function(_dereq_,module,exports){
13602 exports.__esModule = true;
13604 var _tech = _dereq_(62);
13606 var _tech2 = _interopRequireDefault(_tech);
13608 var _dom = _dereq_(81);
13610 var Dom = _interopRequireWildcard(_dom);
13612 var _url = _dereq_(92);
13614 var Url = _interopRequireWildcard(_url);
13616 var _timeRanges = _dereq_(90);
13618 var _flashRtmp = _dereq_(58);
13620 var _flashRtmp2 = _interopRequireDefault(_flashRtmp);
13622 var _component = _dereq_(5);
13624 var _component2 = _interopRequireDefault(_component);
13626 var _window = _dereq_(95);
13628 var _window2 = _interopRequireDefault(_window);
13630 var _obj = _dereq_(88);
13632 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
13634 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
13636 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
13638 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
13640 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
13642 * VideoJS-SWF - Custom Flash Player with HTML5-ish API
13643 * https://github.com/zencoder/video-js-swf
13644 * Not using setupTriggers. Using global onEvent func to distribute events
13647 var navigator = _window2['default'].navigator;
13650 * Flash Media Controller - Wrapper for Flash Media API
13652 * @mixes FlashRtmpDecorator
13653 * @mixes Tech~SouceHandlerAdditions
13657 var Flash = function (_Tech) {
13658 _inherits(Flash, _Tech);
13661 * Create an instance of this Tech.
13663 * @param {Object} [options]
13664 * The key/value store of player options.
13666 * @param {Component~ReadyCallback} ready
13667 * Callback function to call when the `Flash` Tech is ready.
13669 function Flash(options, ready) {
13670 _classCallCheck(this, Flash);
13672 // Set the source when ready
13673 var _this = _possibleConstructorReturn(this, _Tech.call(this, options, ready));
13675 if (options.source) {
13676 _this.ready(function () {
13677 this.setSource(options.source);
13681 // Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
13682 // This allows resetting the playhead when we catch the reload
13683 if (options.startTime) {
13684 _this.ready(function () {
13687 this.currentTime(options.startTime);
13691 // Add global window functions that the swf expects
13692 // A 4.x workflow we weren't able to solve for in 5.0
13693 // because of the need to hard code these functions
13694 // into the swf for security reasons
13695 _window2['default'].videojs = _window2['default'].videojs || {};
13696 _window2['default'].videojs.Flash = _window2['default'].videojs.Flash || {};
13697 _window2['default'].videojs.Flash.onReady = Flash.onReady;
13698 _window2['default'].videojs.Flash.onEvent = Flash.onEvent;
13699 _window2['default'].videojs.Flash.onError = Flash.onError;
13701 _this.on('seeked', function () {
13702 this.lastSeekTarget_ = undefined;
13709 * Create the `Flash` Tech's DOM element.
13711 * @return {Element}
13712 * The element that gets created.
13716 Flash.prototype.createEl = function createEl() {
13717 var options = this.options_;
13719 // If video.js is hosted locally you should also set the location
13720 // for the hosted swf, which should be relative to the page (not video.js)
13721 // Otherwise this adds a CDN url.
13722 // The CDN also auto-adds a swf URL for that specific version.
13723 if (!options.swf) {
13726 options.swf = '//vjs.zencdn.net/swf/' + ver + '/video-js.swf';
13729 // Generate ID for swf object
13730 var objId = options.techId;
13732 // Merge default flashvars with ones passed in to init
13733 var flashVars = (0, _obj.assign)({
13735 // SWF Callback Functions
13736 readyFunction: 'videojs.Flash.onReady',
13737 eventProxyFunction: 'videojs.Flash.onEvent',
13738 errorEventProxyFunction: 'videojs.Flash.onError',
13741 autoplay: options.autoplay,
13742 preload: options.preload,
13743 loop: options.loop,
13744 muted: options.muted
13746 }, options.flashVars);
13748 // Merge default parames with ones passed in
13749 var params = (0, _obj.assign)({
13750 // Opaque is needed to overlay controls, but can affect playback performance
13752 // Using bgcolor prevents a white flash when the object is loading
13754 }, options.params);
13756 // Merge default attributes with ones passed in
13757 var attributes = (0, _obj.assign)({
13758 // Both ID and Name needed or swf to identify itself
13761 'class': 'vjs-tech'
13762 }, options.attributes);
13764 this.el_ = Flash.embed(options.swf, flashVars, params, attributes);
13765 this.el_.tech = this;
13771 * Called by {@link Player#play} to play using the `Flash` `Tech`.
13775 Flash.prototype.play = function play() {
13776 if (this.ended()) {
13777 this.setCurrentTime(0);
13779 this.el_.vjs_play();
13783 * Called by {@link Player#pause} to pause using the `Flash` `Tech`.
13787 Flash.prototype.pause = function pause() {
13788 this.el_.vjs_pause();
13792 * A getter/setter for the `Flash` Tech's source object.
13793 * > Note: Please use {@link Flash#setSource}
13795 * @param {Tech~SourceObject} [src]
13796 * The source object you want to set on the `Flash` techs.
13798 * @return {Tech~SourceObject|undefined}
13799 * - The current source object when a source is not passed in.
13800 * - undefined when setting
13802 * @deprecated Since version 5.
13806 Flash.prototype.src = function src(_src) {
13807 if (_src === undefined) {
13808 return this.currentSrc();
13811 // Setting src through `src` not `setSrc` will be deprecated
13812 return this.setSrc(_src);
13816 * A getter/setter for the `Flash` Tech's source object.
13818 * @param {Tech~SourceObject} [src]
13819 * The source object you want to set on the `Flash` techs.
13821 * @return {Tech~SourceObject|undefined}
13822 * - The current source object when a source is not passed in.
13823 * - undefined when setting
13827 Flash.prototype.setSrc = function setSrc(src) {
13830 // Make sure source URL is absolute.
13831 src = Url.getAbsoluteURL(src);
13832 this.el_.vjs_src(src);
13834 // Currently the SWF doesn't autoplay if you load a source later.
13835 // e.g. Load player w/ no source, wait 2s, set src.
13836 if (this.autoplay()) {
13837 this.setTimeout(function () {
13838 return _this2.play();
13844 * Indicates whether the media is currently seeking to a new position or not.
13846 * @return {boolean}
13847 * - True if seeking to a new position
13848 * - False otherwise
13852 Flash.prototype.seeking = function seeking() {
13853 return this.lastSeekTarget_ !== undefined;
13857 * Returns the current time in seconds that the media is at in playback.
13859 * @param {number} time
13860 * Current playtime of the media in seconds.
13864 Flash.prototype.setCurrentTime = function setCurrentTime(time) {
13865 var seekable = this.seekable();
13867 if (seekable.length) {
13868 // clamp to the current seekable range
13869 time = time > seekable.start(0) ? time : seekable.start(0);
13870 time = time < seekable.end(seekable.length - 1) ? time : seekable.end(seekable.length - 1);
13872 this.lastSeekTarget_ = time;
13873 this.trigger('seeking');
13874 this.el_.vjs_setProperty('currentTime', time);
13875 _Tech.prototype.setCurrentTime.call(this);
13880 * Get the current playback time in seconds
13883 * The current time of playback in seconds.
13887 Flash.prototype.currentTime = function currentTime() {
13888 // when seeking make the reported time keep up with the requested time
13889 // by reading the time we're seeking to
13890 if (this.seeking()) {
13891 return this.lastSeekTarget_ || 0;
13893 return this.el_.vjs_getProperty('currentTime');
13897 * Get the current source
13899 * @method currentSrc
13900 * @return {Tech~SourceObject}
13901 * The current source
13905 Flash.prototype.currentSrc = function currentSrc() {
13906 if (this.currentSource_) {
13907 return this.currentSource_.src;
13909 return this.el_.vjs_getProperty('currentSrc');
13913 * Get the total duration of the current media.
13916 8 The total duration of the current media.
13920 Flash.prototype.duration = function duration() {
13921 if (this.readyState() === 0) {
13924 var duration = this.el_.vjs_getProperty('duration');
13926 return duration >= 0 ? duration : Infinity;
13930 * Load media into Tech.
13934 Flash.prototype.load = function load() {
13935 this.el_.vjs_load();
13939 * Get the poster image that was set on the tech.
13943 Flash.prototype.poster = function poster() {
13944 this.el_.vjs_getProperty('poster');
13948 * Poster images are not handled by the Flash tech so make this is a no-op.
13952 Flash.prototype.setPoster = function setPoster() {};
13955 * Determine the time ranges that can be seeked to in the media.
13957 * @return {TimeRange}
13958 * Returns the time ranges that can be seeked to.
13962 Flash.prototype.seekable = function seekable() {
13963 var duration = this.duration();
13965 if (duration === 0) {
13966 return (0, _timeRanges.createTimeRange)();
13968 return (0, _timeRanges.createTimeRange)(0, duration);
13972 * Get and create a `TimeRange` object for buffering.
13974 * @return {TimeRange}
13975 * The time range object that was created.
13979 Flash.prototype.buffered = function buffered() {
13980 var ranges = this.el_.vjs_getProperty('buffered');
13982 if (ranges.length === 0) {
13983 return (0, _timeRanges.createTimeRange)();
13985 return (0, _timeRanges.createTimeRange)(ranges[0][0], ranges[0][1]);
13989 * Get fullscreen support -
13991 * Flash does not allow fullscreen through javascript
13992 * so this always returns false.
13994 * @return {boolean}
13995 * The Flash tech does not support fullscreen, so it will always return false.
13999 Flash.prototype.supportsFullScreen = function supportsFullScreen() {
14000 // Flash does not allow fullscreen through javascript
14005 * Flash does not allow fullscreen through javascript
14006 * so this always returns false.
14008 * @return {boolean}
14009 * The Flash tech does not support fullscreen, so it will always return false.
14013 Flash.prototype.enterFullScreen = function enterFullScreen() {
14018 }(_tech2['default']);
14020 // Create setters and getters for attributes
14023 var _api = Flash.prototype;
14024 var _readWrite = 'rtmpConnection,rtmpStream,preload,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(',');
14025 var _readOnly = 'networkState,readyState,initialTime,startOffsetTime,paused,ended,videoWidth,videoHeight'.split(',');
14027 function _createSetter(attr) {
14028 var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
14030 _api['set' + attrUpper] = function (val) {
14031 return this.el_.vjs_setProperty(attr, val);
14035 function _createGetter(attr) {
14036 _api[attr] = function () {
14037 return this.el_.vjs_getProperty(attr);
14041 // Create getter and setters for all read/write attributes
14042 for (var i = 0; i < _readWrite.length; i++) {
14043 _createGetter(_readWrite[i]);
14044 _createSetter(_readWrite[i]);
14047 // Create getters for read-only attributes
14048 for (var _i = 0; _i < _readOnly.length; _i++) {
14049 _createGetter(_readOnly[_i]);
14052 /** ------------------------------ Getters ------------------------------ **/
14054 * Get the value of `rtmpConnection` from the swf.
14056 * @method Flash#rtmpConnection
14058 * The current value of `rtmpConnection` on the swf.
14062 * Get the value of `rtmpStream` from the swf.
14064 * @method Flash#rtmpStream
14066 * The current value of `rtmpStream` on the swf.
14070 * Get the value of `preload` from the swf. `preload` indicates
14071 * what should download before the media is interacted with. It can have the following
14073 * - none: nothing should be downloaded
14074 * - metadata: poster and the first few frames of the media may be downloaded to get
14075 * media dimensions and other metadata
14076 * - auto: allow the media and metadata for the media to be downloaded before
14079 * @method Flash#preload
14081 * The value of `preload` from the swf. Will be 'none', 'metadata',
14086 * Get the value of `defaultPlaybackRate` from the swf.
14088 * @method Flash#defaultPlaybackRate
14090 * The current value of `defaultPlaybackRate` on the swf.
14094 * Get the value of `playbackRate` from the swf. `playbackRate` indicates
14095 * the rate at which the media is currently playing back. Examples:
14096 * - if playbackRate is set to 2, media will play twice as fast.
14097 * - if playbackRate is set to 0.5, media will play half as fast.
14099 * @method Flash#playbackRate
14101 * The value of `playbackRate` from the swf. A number indicating
14102 * the current playback speed of the media, where 1 is normal speed.
14106 * Get the value of `autoplay` from the swf. `autoplay` indicates
14107 * that the media should start to play as soon as the page is ready.
14109 * @method Flash#autoplay
14110 * @return {boolean}
14111 * - The value of `autoplay` from the swf.
14112 * - True indicates that the media ashould start as soon as the page loads.
14113 * - False indicates that the media should not start as soon as the page loads.
14117 * Get the value of `loop` from the swf. `loop` indicates
14118 * that the media should return to the start of the media and continue playing once
14119 * it reaches the end.
14121 * @method Flash#loop
14122 * @return {boolean}
14123 * - The value of `loop` from the swf.
14124 * - True indicates that playback should seek back to start once
14125 * the end of a media is reached.
14126 * - False indicates that playback should not loop back to the start when the
14127 * end of the media is reached.
14131 * Get the value of `mediaGroup` from the swf.
14133 * @method Flash#mediaGroup
14135 * The current value of `mediaGroup` on the swf.
14139 * Get the value of `controller` from the swf.
14141 * @method Flash#controller
14143 * The current value of `controller` on the swf.
14147 * Get the value of `controls` from the swf. `controls` indicates
14148 * whether the native flash controls should be shown or hidden.
14150 * @method Flash#controls
14151 * @return {boolean}
14152 * - The value of `controls` from the swf.
14153 * - True indicates that native controls should be showing.
14154 * - False indicates that native controls should be hidden.
14158 * Get the value of the `volume` from the swf. `volume` indicates the current
14159 * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
14162 * @method Flash#volume
14164 * The volume percent as a decimal. Value will be between 0-1.
14168 * Get the value of the `muted` from the swf. `muted` indicates the current
14169 * audio level should be silent.
14171 * @method Flash#muted
14172 * @return {boolean}
14173 * - True if the audio should be set to silent
14174 * - False otherwise
14178 * Get the value of `defaultMuted` from the swf. `defaultMuted` indicates
14179 * whether the media should start muted or not. Only changes the default state of the
14180 * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
14183 * @method Flash#defaultMuted
14184 * @return {boolean}
14185 * - The value of `defaultMuted` from the swf.
14186 * - True indicates that the media should start muted.
14187 * - False indicates that the media should not start muted.
14191 * Get the value of `networkState` from the swf. `networkState` indicates
14192 * the current network state. It returns an enumeration from the following list:
14193 * - 0: NETWORK_EMPTY
14195 * - 2: NETWORK_LOADING
14196 * - 3: NETWORK_NO_SOURCE
14198 * @method Flash#networkState
14200 * The value of `networkState` from the swf. This will be a number
14201 * from the list in the description.
14205 * Get the value of `readyState` from the swf. `readyState` indicates
14206 * the current state of the media element. It returns an enumeration from the
14208 * - 0: HAVE_NOTHING
14209 * - 1: HAVE_METADATA
14210 * - 2: HAVE_CURRENT_DATA
14211 * - 3: HAVE_FUTURE_DATA
14212 * - 4: HAVE_ENOUGH_DATA
14214 * @method Flash#readyState
14216 * The value of `readyState` from the swf. This will be a number
14217 * from the list in the description.
14221 * Get the value of `readyState` from the swf. `readyState` indicates
14222 * the current state of the media element. It returns an enumeration from the
14224 * - 0: HAVE_NOTHING
14225 * - 1: HAVE_METADATA
14226 * - 2: HAVE_CURRENT_DATA
14227 * - 3: HAVE_FUTURE_DATA
14228 * - 4: HAVE_ENOUGH_DATA
14230 * @method Flash#readyState
14232 * The value of `readyState` from the swf. This will be a number
14233 * from the list in the description.
14237 * Get the value of `initialTime` from the swf.
14239 * @method Flash#initialTime
14241 * The `initialTime` proprety on the swf.
14245 * Get the value of `startOffsetTime` from the swf.
14247 * @method Flash#startOffsetTime
14249 * The `startOffsetTime` proprety on the swf.
14253 * Get the value of `paused` from the swf. `paused` indicates whether the swf
14254 * is current paused or not.
14256 * @method Flash#paused
14257 * @return {boolean}
14258 * The value of `paused` from the swf.
14262 * Get the value of `ended` from the swf. `ended` indicates whether
14263 * the media has reached the end or not.
14265 * @method Flash#ended
14266 * @return {boolean}
14267 * - True indicates that the media has ended.
14268 * - False indicates that the media has not ended.
14270 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-ended}
14274 * Get the value of `videoWidth` from the swf. `videoWidth` indicates
14275 * the current width of the media in css pixels.
14277 * @method Flash#videoWidth
14279 * The value of `videoWidth` from the swf. This will be a number
14284 * Get the value of `videoHeight` from the swf. `videoHeigth` indicates
14285 * the current height of the media in css pixels.
14287 * @method Flassh.prototype.videoHeight
14289 * The value of `videoHeight` from the swf. This will be a number
14292 /** ------------------------------ Setters ------------------------------ **/
14295 * Set the value of `rtmpConnection` on the swf.
14297 * @method Flash#setRtmpConnection
14298 * @param {string} rtmpConnection
14299 * New value to set the `rtmpConnection` property to.
14303 * Set the value of `rtmpStream` on the swf.
14305 * @method Flash#setRtmpStream
14306 * @param {string} rtmpStream
14307 * New value to set the `rtmpStream` property to.
14311 * Set the value of `preload` on the swf. `preload` indicates
14312 * what should download before the media is interacted with. It can have the following
14314 * - none: nothing should be downloaded
14315 * - metadata: poster and the first few frames of the media may be downloaded to get
14316 * media dimensions and other metadata
14317 * - auto: allow the media and metadata for the media to be downloaded before
14320 * @method Flash#setPreload
14321 * @param {string} preload
14322 * The value of `preload` to set on the swf. Should be 'none', 'metadata',
14327 * Set the value of `defaultPlaybackRate` on the swf.
14329 * @method Flash#setDefaultPlaybackRate
14330 * @param {number} defaultPlaybackRate
14331 * New value to set the `defaultPlaybackRate` property to.
14335 * Set the value of `playbackRate` on the swf. `playbackRate` indicates
14336 * the rate at which the media is currently playing back. Examples:
14337 * - if playbackRate is set to 2, media will play twice as fast.
14338 * - if playbackRate is set to 0.5, media will play half as fast.
14340 * @method Flash#setPlaybackRate
14341 * @param {number} playbackRate
14342 * New value of `playbackRate` on the swf. A number indicating
14343 * the current playback speed of the media, where 1 is normal speed.
14347 * Set the value of `autoplay` on the swf. `autoplay` indicates
14348 * that the media should start to play as soon as the page is ready.
14350 * @method Flash#setAutoplay
14351 * @param {boolean} autoplay
14352 * - The value of `autoplay` from the swf.
14353 * - True indicates that the media ashould start as soon as the page loads.
14354 * - False indicates that the media should not start as soon as the page loads.
14358 * Set the value of `loop` on the swf. `loop` indicates
14359 * that the media should return to the start of the media and continue playing once
14360 * it reaches the end.
14362 * @method Flash#setLoop
14363 * @param {boolean} loop
14364 * - True indicates that playback should seek back to start once
14365 * the end of a media is reached.
14366 * - False indicates that playback should not loop back to the start when the
14367 * end of the media is reached.
14371 * Set the value of `mediaGroup` on the swf.
14373 * @method Flash#setMediaGroup
14374 * @param {string} mediaGroup
14375 * New value of `mediaGroup` to set on the swf.
14379 * Set the value of `controller` on the swf.
14381 * @method Flash#setController
14382 * @param {string} controller
14383 * New value the current value of `controller` on the swf.
14387 * Get the value of `controls` from the swf. `controls` indicates
14388 * whether the native flash controls should be shown or hidden.
14390 * @method Flash#controls
14391 * @return {boolean}
14392 * - The value of `controls` from the swf.
14393 * - True indicates that native controls should be showing.
14394 * - False indicates that native controls should be hidden.
14398 * Set the value of the `volume` on the swf. `volume` indicates the current
14399 * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
14402 * @method Flash#setVolume
14403 * @param {number} percentAsDecimal
14404 * The volume percent as a decimal. Value will be between 0-1.
14408 * Set the value of the `muted` on the swf. `muted` indicates that the current
14409 * audio level should be silent.
14411 * @method Flash#setMuted
14412 * @param {boolean} muted
14413 * - True if the audio should be set to silent
14414 * - False otherwise
14418 * Set the value of `defaultMuted` on the swf. `defaultMuted` indicates
14419 * whether the media should start muted or not. Only changes the default state of the
14420 * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
14423 * @method Flash#setDefaultMuted
14424 * @param {boolean} defaultMuted
14425 * - True indicates that the media should start muted.
14426 * - False indicates that the media should not start muted.
14429 /* Flash Support Testing -------------------------------------------------------- */
14432 * Check if the Flash tech is currently supported.
14434 * @return {boolean}
14435 * - True if the flash tech is supported.
14436 * - False otherwise.
14438 Flash.isSupported = function () {
14439 return Flash.version()[0] >= 10;
14440 // return swfobject.hasFlashPlayerVersion('10');
14443 // Add Source Handler pattern functions to this tech
14444 _tech2['default'].withSourceHandlers(Flash);
14447 * Native source handler for flash, simply passes the source to the swf element.
14449 * @property {Tech~SourceObject} source
14450 * The source object
14452 * @property {Flash} tech
14453 * The instance of the Flash tech
14455 Flash.nativeSourceHandler = {};
14458 * Check if the Flash can play the given mime type.
14460 * @param {string} type
14461 * The mimetype to check
14464 * 'maybe', or '' (empty string)
14466 Flash.nativeSourceHandler.canPlayType = function (type) {
14467 if (type in Flash.formats) {
14475 * Check if the media element can handle a source natively.
14477 * @param {Tech~SourceObject} source
14478 * The source object
14480 * @param {Object} [options]
14481 * Options to be passed to the tech.
14484 * 'maybe', or '' (empty string).
14486 Flash.nativeSourceHandler.canHandleSource = function (source, options) {
14489 function guessMimeType(src) {
14490 var ext = Url.getFileExtension(src);
14493 return 'video/' + ext;
14498 if (!source.type) {
14499 type = guessMimeType(source.src);
14501 // Strip code information from the type because we don't get that specific
14502 type = source.type.replace(/;.*/, '').toLowerCase();
14505 return Flash.nativeSourceHandler.canPlayType(type);
14509 * Pass the source to the swf.
14511 * @param {Tech~SourceObject} source
14512 * The source object
14514 * @param {Flash} tech
14515 * The instance of the Flash tech
14517 * @param {Object} [options]
14518 * The options to pass to the source
14520 Flash.nativeSourceHandler.handleSource = function (source, tech, options) {
14521 tech.setSrc(source.src);
14525 * noop for native source handler dispose, as cleanup will happen automatically.
14527 Flash.nativeSourceHandler.dispose = function () {};
14529 // Register the native source handler
14530 Flash.registerSourceHandler(Flash.nativeSourceHandler);
14533 * Flash supported mime types.
14535 * @constant {Object}
14538 'video/flv': 'FLV',
14539 'video/x-flv': 'FLV',
14540 'video/mp4': 'MP4',
14545 * Called when the the swf is "ready", and makes sure that the swf is really
14546 * ready using {@link Flash#checkReady}
14548 Flash.onReady = function (currSwf) {
14549 var el = Dom.getEl(currSwf);
14550 var tech = el && el.tech;
14552 // if there is no el then the tech has been disposed
14553 // and the tech element was removed from the player div
14554 if (tech && tech.el()) {
14555 // check that the flash object is really ready
14556 Flash.checkReady(tech);
14561 * The SWF isn't always ready when it says it is. Sometimes the API functions still
14562 * need to be added to the object. If it's not ready, we set a timeout to check again
14565 * @param {Flash} tech
14566 * The instance of the flash tech to check.
14568 Flash.checkReady = function (tech) {
14569 // stop worrying if the tech has been disposed
14574 // check if API property exists
14575 if (tech.el().vjs_getProperty) {
14576 // tell tech it's ready
14577 tech.triggerReady();
14580 this.setTimeout(function () {
14581 Flash.checkReady(tech);
14587 * Trigger events from the swf on the Flash Tech.
14589 * @param {number} swfID
14590 * The id of the swf that had the event
14592 * @param {string} eventName
14593 * The name of the event to trigger
14595 Flash.onEvent = function (swfID, eventName) {
14596 var tech = Dom.getEl(swfID).tech;
14597 var args = Array.prototype.slice.call(arguments, 2);
14599 // dispatch Flash events asynchronously for two reasons:
14600 // - Flash swallows any exceptions generated by javascript it
14602 // - Flash is suspended until the javascript returns which may cause
14603 // playback performance issues
14604 tech.setTimeout(function () {
14605 tech.trigger(eventName, args);
14610 * Log errors from the swf on the Flash tech.
14612 * @param {number} swfID
14613 * The id of the swf that had an error.
14615 * @param {string} The error string
14616 * The error to set on the Flash Tech.
14618 * @return {MediaError|undefined}
14619 * - Returns a MediaError when err is 'srcnotfound'
14620 * - Returns undefined otherwise.
14622 Flash.onError = function (swfID, err) {
14623 var tech = Dom.getEl(swfID).tech;
14625 // trigger MEDIA_ERR_SRC_NOT_SUPPORTED
14626 if (err === 'srcnotfound') {
14627 return tech.error(4);
14630 // trigger a custom error
14631 tech.error('FLASH: ' + err);
14635 * Get the current version of Flash that is in use on the page.
14638 * an array of versions that are available.
14640 Flash.version = function () {
14641 var version = '0,0,0';
14645 version = new _window2['default'].ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
14650 if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {
14651 version = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
14657 return version.split(',');
14661 * Only use for non-iframe embeds.
14663 * @param {Object} swf
14664 * The videojs-swf object.
14666 * @param {Object} flashVars
14667 * Names and values to use as flash option variables.
14669 * @param {Object} params
14670 * Style parameters to set on the object.
14672 * @param {Object} attributes
14673 * Attributes to set on the element.
14675 * @return {Element}
14676 * The embedded Flash DOM element.
14678 Flash.embed = function (swf, flashVars, params, attributes) {
14679 var code = Flash.getEmbedCode(swf, flashVars, params, attributes);
14681 // Get element by embedding code and retrieving created element
14682 var obj = Dom.createEl('div', { innerHTML: code }).childNodes[0];
14688 * Only use for non-iframe embeds.
14690 * @param {Object} swf
14691 * The videojs-swf object.
14693 * @param {Object} flashVars
14694 * Names and values to use as flash option variables.
14696 * @param {Object} params
14697 * Style parameters to set on the object.
14699 * @param {Object} attributes
14700 * Attributes to set on the element.
14702 * @return {Element}
14703 * The embedded Flash DOM element.
14705 Flash.getEmbedCode = function (swf, flashVars, params, attributes) {
14706 var objTag = '<object type="application/x-shockwave-flash" ';
14707 var flashVarsString = '';
14708 var paramsString = '';
14709 var attrsString = '';
14711 // Convert flash vars to string
14713 Object.getOwnPropertyNames(flashVars).forEach(function (key) {
14714 flashVarsString += key + '=' + flashVars[key] + '&';
14718 // Add swf, flashVars, and other default params
14719 params = (0, _obj.assign)({
14721 flashvars: flashVarsString,
14722 // Required to talk to swf
14723 allowScriptAccess: 'always',
14724 // All should be default, but having security issues.
14725 allowNetworking: 'all'
14728 // Create param tags string
14729 Object.getOwnPropertyNames(params).forEach(function (key) {
14730 paramsString += '<param name="' + key + '" value="' + params[key] + '" />';
14733 attributes = (0, _obj.assign)({
14734 // Add swf to attributes (need both for IE and Others to work)
14737 // Default to 100% width/height
14743 // Create Attributes string
14744 Object.getOwnPropertyNames(attributes).forEach(function (key) {
14745 attrsString += key + '="' + attributes[key] + '" ';
14748 return '' + objTag + attrsString + '>' + paramsString + '</object>';
14751 // Run Flash through the RTMP decorator
14752 (0, _flashRtmp2['default'])(Flash);
14754 _component2['default'].registerComponent('Flash', Flash);
14755 _tech2['default'].registerTech('Flash', Flash);
14756 exports['default'] = Flash;
14758 },{"5":5,"58":58,"62":62,"81":81,"88":88,"90":90,"92":92,"95":95}],60:[function(_dereq_,module,exports){
14761 exports.__esModule = true;
14763 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
14765 var _templateObject = _taggedTemplateLiteralLoose(['Text Tracks are being loaded from another origin but the crossorigin attribute isn\'t used.\n This may prevent text tracks from loading.'], ['Text Tracks are being loaded from another origin but the crossorigin attribute isn\'t used.\n This may prevent text tracks from loading.']);
14767 var _tech = _dereq_(62);
14769 var _tech2 = _interopRequireDefault(_tech);
14771 var _component = _dereq_(5);
14773 var _component2 = _interopRequireDefault(_component);
14775 var _dom = _dereq_(81);
14777 var Dom = _interopRequireWildcard(_dom);
14779 var _url = _dereq_(92);
14781 var Url = _interopRequireWildcard(_url);
14783 var _fn = _dereq_(83);
14785 var Fn = _interopRequireWildcard(_fn);
14787 var _log = _dereq_(86);
14789 var _log2 = _interopRequireDefault(_log);
14791 var _tsml = _dereq_(98);
14793 var _tsml2 = _interopRequireDefault(_tsml);
14795 var _browser = _dereq_(78);
14797 var browser = _interopRequireWildcard(_browser);
14799 var _document = _dereq_(94);
14801 var _document2 = _interopRequireDefault(_document);
14803 var _window = _dereq_(95);
14805 var _window2 = _interopRequireDefault(_window);
14807 var _obj = _dereq_(88);
14809 var _mergeOptions = _dereq_(87);
14811 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
14813 var _toTitleCase = _dereq_(91);
14815 var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
14817 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
14819 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
14821 function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; }
14823 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
14825 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
14827 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
14833 * HTML5 Media Controller - Wrapper for HTML5 Media API
14835 * @mixes Tech~SouceHandlerAdditions
14838 var Html5 = function (_Tech) {
14839 _inherits(Html5, _Tech);
14842 * Create an instance of this Tech.
14844 * @param {Object} [options]
14845 * The key/value store of player options.
14847 * @param {Component~ReadyCallback} ready
14848 * Callback function to call when the `HTML5` Tech is ready.
14850 function Html5(options, ready) {
14851 _classCallCheck(this, Html5);
14853 var _this = _possibleConstructorReturn(this, _Tech.call(this, options, ready));
14855 var source = options.source;
14856 var crossoriginTracks = false;
14858 // Set the source if one is provided
14859 // 1) Check if the source is new (if not, we want to keep the original so playback isn't interrupted)
14860 // 2) Check to see if the network state of the tag was failed at init, and if so, reset the source
14861 // anyway so the error gets fired.
14862 if (source && (_this.el_.currentSrc !== source.src || options.tag && options.tag.initNetworkState_ === 3)) {
14863 _this.setSource(source);
14865 _this.handleLateInit_(_this.el_);
14868 if (_this.el_.hasChildNodes()) {
14870 var nodes = _this.el_.childNodes;
14871 var nodesLength = nodes.length;
14872 var removeNodes = [];
14874 while (nodesLength--) {
14875 var node = nodes[nodesLength];
14876 var nodeName = node.nodeName.toLowerCase();
14878 if (nodeName === 'track') {
14879 if (!_this.featuresNativeTextTracks) {
14880 // Empty video tag tracks so the built-in player doesn't use them also.
14881 // This may not be fast enough to stop HTML5 browsers from reading the tags
14882 // so we'll need to turn off any default tracks if we're manually doing
14883 // captions and subtitles. videoElement.textTracks
14884 removeNodes.push(node);
14886 // store HTMLTrackElement and TextTrack to remote list
14887 _this.remoteTextTrackEls().addTrackElement_(node);
14888 _this.remoteTextTracks().addTrack_(node.track);
14889 if (!crossoriginTracks && !_this.el_.hasAttribute('crossorigin') && Url.isCrossOrigin(node.src)) {
14890 crossoriginTracks = true;
14896 for (var i = 0; i < removeNodes.length; i++) {
14897 _this.el_.removeChild(removeNodes[i]);
14901 // TODO: add text tracks into this list
14902 var trackTypes = ['audio', 'video'];
14904 // ProxyNative Video/Audio Track
14905 trackTypes.forEach(function (type) {
14906 var elTracks = _this.el()[type + 'Tracks'];
14907 var techTracks = _this[type + 'Tracks']();
14908 var capitalType = (0, _toTitleCase2['default'])(type);
14910 if (!_this['featuresNative' + capitalType + 'Tracks'] || !elTracks || !elTracks.addEventListener) {
14914 _this['handle' + capitalType + 'TrackChange_'] = function (e) {
14915 techTracks.trigger({
14917 target: techTracks,
14918 currentTarget: techTracks,
14919 srcElement: techTracks
14923 _this['handle' + capitalType + 'TrackAdd_'] = function (e) {
14924 return techTracks.addTrack(e.track);
14926 _this['handle' + capitalType + 'TrackRemove_'] = function (e) {
14927 return techTracks.removeTrack(e.track);
14930 elTracks.addEventListener('change', _this['handle' + capitalType + 'TrackChange_']);
14931 elTracks.addEventListener('addtrack', _this['handle' + capitalType + 'TrackAdd_']);
14932 elTracks.addEventListener('removetrack', _this['handle' + capitalType + 'TrackRemove_']);
14933 _this['removeOld' + capitalType + 'Tracks_'] = function (e) {
14934 return _this.removeOldTracks_(techTracks, elTracks);
14937 // Remove (native) tracks that are not used anymore
14938 _this.on('loadstart', _this['removeOld' + capitalType + 'Tracks_']);
14941 if (_this.featuresNativeTextTracks) {
14942 if (crossoriginTracks) {
14943 _log2['default'].warn((0, _tsml2['default'])(_templateObject));
14946 _this.handleTextTrackChange_ = Fn.bind(_this, _this.handleTextTrackChange);
14947 _this.handleTextTrackAdd_ = Fn.bind(_this, _this.handleTextTrackAdd);
14948 _this.handleTextTrackRemove_ = Fn.bind(_this, _this.handleTextTrackRemove);
14949 _this.proxyNativeTextTracks_();
14952 // Determine if native controls should be used
14953 // Our goal should be to get the custom controls on mobile solid everywhere
14954 // so we can remove this all together. Right now this will block custom
14955 // controls on touch enabled laptops like the Chrome Pixel
14956 if ((browser.TOUCH_ENABLED || browser.IS_IPHONE || browser.IS_NATIVE_ANDROID) && options.nativeControlsForTouch === true) {
14957 _this.setControls(true);
14960 // on iOS, we want to proxy `webkitbeginfullscreen` and `webkitendfullscreen`
14961 // into a `fullscreenchange` event
14962 _this.proxyWebkitFullscreen_();
14964 _this.triggerReady();
14969 * Dispose of `HTML5` media element and remove all tracks.
14973 Html5.prototype.dispose = function dispose() {
14976 // Un-ProxyNativeTracks
14977 ['audio', 'video', 'text'].forEach(function (type) {
14978 var capitalType = (0, _toTitleCase2['default'])(type);
14979 var tl = _this2.el_[type + 'Tracks'];
14981 if (tl && tl.removeEventListener) {
14982 tl.removeEventListener('change', _this2['handle' + capitalType + 'TrackChange_']);
14983 tl.removeEventListener('addtrack', _this2['handle' + capitalType + 'TrackAdd_']);
14984 tl.removeEventListener('removetrack', _this2['handle' + capitalType + 'TrackRemove_']);
14987 // Stop removing old text tracks
14989 _this2.off('loadstart', _this2['removeOld' + capitalType + 'Tracks_']);
14993 Html5.disposeMediaElement(this.el_);
14994 // tech will handle clearing of the emulated track list
14995 _Tech.prototype.dispose.call(this);
14999 * Create the `Html5` Tech's DOM element.
15001 * @return {Element}
15002 * The element that gets created.
15006 Html5.prototype.createEl = function createEl() {
15007 var el = this.options_.tag;
15009 // Check if this browser supports moving the element into the box.
15010 // On the iPhone video will break if you move the element,
15011 // So we have to create a brand new element.
15012 // If we ingested the player div, we do not need to move the media element.
15013 if (!el || !(this.options_.playerElIngest || this.movingMediaElementInDOM)) {
15015 // If the original tag is still there, clone and remove it.
15017 var clone = el.cloneNode(true);
15019 if (el.parentNode) {
15020 el.parentNode.insertBefore(clone, el);
15022 Html5.disposeMediaElement(el);
15025 el = _document2['default'].createElement('video');
15027 // determine if native controls should be used
15028 var tagAttributes = this.options_.tag && Dom.getElAttributes(this.options_.tag);
15029 var attributes = (0, _mergeOptions2['default'])({}, tagAttributes);
15031 if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) {
15032 delete attributes.controls;
15035 Dom.setElAttributes(el, (0, _obj.assign)(attributes, {
15036 id: this.options_.techId,
15037 'class': 'vjs-tech'
15041 el.playerId = this.options_.playerId;
15044 // Update specific tag settings, in case they were overridden
15045 var settingsAttrs = ['autoplay', 'preload', 'loop', 'muted'];
15047 for (var i = settingsAttrs.length - 1; i >= 0; i--) {
15048 var attr = settingsAttrs[i];
15049 var overwriteAttrs = {};
15051 if (typeof this.options_[attr] !== 'undefined') {
15052 overwriteAttrs[attr] = this.options_[attr];
15054 Dom.setElAttributes(el, overwriteAttrs);
15061 * This will be triggered if the loadstart event has already fired, before videojs was
15062 * ready. Two known examples of when this can happen are:
15063 * 1. If we're loading the playback object after it has started loading
15064 * 2. The media is already playing the (often with autoplay on) then
15066 * This function will fire another loadstart so that videojs can catchup.
15068 * @fires Tech#loadstart
15070 * @return {undefined}
15075 Html5.prototype.handleLateInit_ = function handleLateInit_(el) {
15078 if (el.networkState === 0 || el.networkState === 3) {
15079 // The video element hasn't started loading the source yet
15080 // or didn't find a source
15084 if (el.readyState === 0) {
15085 var _ret = function () {
15086 // NetworkState is set synchronously BUT loadstart is fired at the
15087 // end of the current stack, usually before setInterval(fn, 0).
15088 // So at this point we know loadstart may have already fired or is
15089 // about to fire, and either way the player hasn't seen it yet.
15090 // We don't want to fire loadstart prematurely here and cause a
15091 // double loadstart so we'll wait and see if it happens between now
15092 // and the next loop, and fire it if not.
15093 // HOWEVER, we also want to make sure it fires before loadedmetadata
15094 // which could also happen between now and the next loop, so we'll
15095 // watch for that also.
15096 var loadstartFired = false;
15097 var setLoadstartFired = function setLoadstartFired() {
15098 loadstartFired = true;
15101 _this3.on('loadstart', setLoadstartFired);
15103 var triggerLoadstart = function triggerLoadstart() {
15104 // We did miss the original loadstart. Make sure the player
15105 // sees loadstart before loadedmetadata
15106 if (!loadstartFired) {
15107 this.trigger('loadstart');
15111 _this3.on('loadedmetadata', triggerLoadstart);
15113 _this3.ready(function () {
15114 this.off('loadstart', setLoadstartFired);
15115 this.off('loadedmetadata', triggerLoadstart);
15117 if (!loadstartFired) {
15118 // We did miss the original native loadstart. Fire it now.
15119 this.trigger('loadstart');
15128 if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
15131 // From here on we know that loadstart already fired and we missed it.
15132 // The other readyState events aren't as much of a problem if we double
15133 // them, so not going to go to as much trouble as loadstart to prevent
15134 // that unless we find reason to.
15135 var eventsToTrigger = ['loadstart'];
15137 // loadedmetadata: newly equal to HAVE_METADATA (1) or greater
15138 eventsToTrigger.push('loadedmetadata');
15140 // loadeddata: newly increased to HAVE_CURRENT_DATA (2) or greater
15141 if (el.readyState >= 2) {
15142 eventsToTrigger.push('loadeddata');
15145 // canplay: newly increased to HAVE_FUTURE_DATA (3) or greater
15146 if (el.readyState >= 3) {
15147 eventsToTrigger.push('canplay');
15150 // canplaythrough: newly equal to HAVE_ENOUGH_DATA (4)
15151 if (el.readyState >= 4) {
15152 eventsToTrigger.push('canplaythrough');
15155 // We still need to give the player time to add event listeners
15156 this.ready(function () {
15157 eventsToTrigger.forEach(function (type) {
15158 this.trigger(type);
15164 * Add event listeners to native text track events. This adds the native text tracks
15165 * to our emulated {@link TextTrackList}.
15169 Html5.prototype.proxyNativeTextTracks_ = function proxyNativeTextTracks_() {
15170 var tt = this.el().textTracks;
15173 // Add tracks - if player is initialised after DOM loaded, textTracks
15174 // will not trigger addtrack
15175 for (var i = 0; i < tt.length; i++) {
15176 this.textTracks().addTrack_(tt[i]);
15179 if (tt.addEventListener) {
15180 tt.addEventListener('change', this.handleTextTrackChange_);
15181 tt.addEventListener('addtrack', this.handleTextTrackAdd_);
15182 tt.addEventListener('removetrack', this.handleTextTrackRemove_);
15185 // Remove (native) texttracks that are not used anymore
15186 this.on('loadstart', this.removeOldTextTracks_);
15191 * Handle any {@link TextTrackList} `change` event.
15193 * @param {EventTarget~Event} e
15194 * The `change` event that caused this to run.
15196 * @listens TextTrackList#change
15200 Html5.prototype.handleTextTrackChange = function handleTextTrackChange(e) {
15201 var tt = this.textTracks();
15203 this.textTracks().trigger({
15212 * Handle any {@link TextTrackList} `addtrack` event.
15214 * @param {EventTarget~Event} e
15215 * The `addtrack` event that caused this to run.
15217 * @listens TextTrackList#addtrack
15221 Html5.prototype.handleTextTrackAdd = function handleTextTrackAdd(e) {
15222 this.textTracks().addTrack_(e.track);
15226 * Handle any {@link TextTrackList} `removetrack` event.
15228 * @param {EventTarget~Event} e
15229 * The `removetrack` event that caused this to run.
15231 * @listens TextTrackList#removetrack
15235 Html5.prototype.handleTextTrackRemove = function handleTextTrackRemove(e) {
15236 this.textTracks().removeTrack_(e.track);
15240 * This function removes any {@link AudioTrack}s, {@link VideoTrack}s, or
15241 * {@link TextTrack}s that are not in the media elements TrackList.
15243 * @param {TrackList} techTracks
15244 * HTML5 Tech's TrackList to search through
15246 * @param {TrackList} elTracks
15247 * HTML5 media elements TrackList to search through.
15253 Html5.prototype.removeOldTracks_ = function removeOldTracks_(techTracks, elTracks) {
15254 // This will loop over the techTracks and check if they are still used by the HTML5 media element
15255 // If not, they will be removed from the emulated list
15256 var removeTracks = [];
15262 for (var i = 0; i < techTracks.length; i++) {
15263 var techTrack = techTracks[i];
15266 for (var j = 0; j < elTracks.length; j++) {
15267 if (elTracks[j] === techTrack) {
15274 removeTracks.push(techTrack);
15278 for (var _i = 0; _i < removeTracks.length; _i++) {
15279 var track = removeTracks[_i];
15281 techTracks.removeTrack_(track);
15286 * Remove {@link TextTrack}s that dont exist in the native track list from our
15287 * emulated {@link TextTrackList}.
15289 * @listens Tech#loadstart
15293 Html5.prototype.removeOldTextTracks_ = function removeOldTextTracks_(e) {
15294 var techTracks = this.textTracks();
15295 var elTracks = this.el().textTracks;
15297 this.removeOldTracks_(techTracks, elTracks);
15301 * Called by {@link Player#play} to play using the `Html5` `Tech`.
15305 Html5.prototype.play = function play() {
15306 var playPromise = this.el_.play();
15308 // Catch/silence error when a pause interrupts a play request
15309 // on browsers which return a promise
15310 if (playPromise !== undefined && typeof playPromise.then === 'function') {
15311 playPromise.then(null, function (e) {});
15316 * Set current time for the `HTML5` tech.
15318 * @param {number} seconds
15319 * Set the current time of the media to this.
15323 Html5.prototype.setCurrentTime = function setCurrentTime(seconds) {
15325 this.el_.currentTime = seconds;
15327 (0, _log2['default'])(e, 'Video is not ready. (Video.js)');
15328 // this.warning(VideoJS.warnings.videoNotReady);
15333 * Get the current duration of the HTML5 media element.
15336 * The duration of the media or 0 if there is no duration.
15340 Html5.prototype.duration = function duration() {
15343 // Android Chrome will report duration as Infinity for VOD HLS until after
15344 // playback has started, which triggers the live display erroneously.
15345 // Return NaN if playback has not started and trigger a durationupdate once
15346 // the duration can be reliably known.
15347 if (this.el_.duration === Infinity && browser.IS_ANDROID && browser.IS_CHROME) {
15348 if (this.el_.currentTime === 0) {
15349 var _ret2 = function () {
15350 // Wait for the first `timeupdate` with currentTime > 0 - there may be
15352 var checkProgress = function checkProgress() {
15353 if (_this4.el_.currentTime > 0) {
15354 // Trigger durationchange for genuinely live video
15355 if (_this4.el_.duration === Infinity) {
15356 _this4.trigger('durationchange');
15358 _this4.off('timeupdate', checkProgress);
15362 _this4.on('timeupdate', checkProgress);
15368 if ((typeof _ret2 === 'undefined' ? 'undefined' : _typeof(_ret2)) === "object") return _ret2.v;
15371 return this.el_.duration || NaN;
15375 * Get the current width of the HTML5 media element.
15378 * The width of the HTML5 media element.
15382 Html5.prototype.width = function width() {
15383 return this.el_.offsetWidth;
15387 * Get the current height of the HTML5 media element.
15390 * The height of the HTML5 media element.
15394 Html5.prototype.height = function height() {
15395 return this.el_.offsetHeight;
15399 * Proxy iOS `webkitbeginfullscreen` and `webkitendfullscreen` into
15400 * `fullscreenchange` event.
15403 * @fires fullscreenchange
15404 * @listens webkitendfullscreen
15405 * @listens webkitbeginfullscreen
15406 * @listens webkitbeginfullscreen
15410 Html5.prototype.proxyWebkitFullscreen_ = function proxyWebkitFullscreen_() {
15413 if (!('webkitDisplayingFullscreen' in this.el_)) {
15417 var endFn = function endFn() {
15418 this.trigger('fullscreenchange', { isFullscreen: false });
15421 var beginFn = function beginFn() {
15422 this.one('webkitendfullscreen', endFn);
15424 this.trigger('fullscreenchange', { isFullscreen: true });
15427 this.on('webkitbeginfullscreen', beginFn);
15428 this.on('dispose', function () {
15429 _this5.off('webkitbeginfullscreen', beginFn);
15430 _this5.off('webkitendfullscreen', endFn);
15435 * Check if fullscreen is supported on the current playback device.
15437 * @return {boolean}
15438 * - True if fullscreen is supported.
15439 * - False if fullscreen is not supported.
15443 Html5.prototype.supportsFullScreen = function supportsFullScreen() {
15444 if (typeof this.el_.webkitEnterFullScreen === 'function') {
15445 var userAgent = _window2['default'].navigator && _window2['default'].navigator.userAgent || '';
15447 // Seems to be broken in Chromium/Chrome && Safari in Leopard
15448 if (/Android/.test(userAgent) || !/Chrome|Mac OS X 10.5/.test(userAgent)) {
15456 * Request that the `HTML5` Tech enter fullscreen.
15460 Html5.prototype.enterFullScreen = function enterFullScreen() {
15461 var video = this.el_;
15463 if (video.paused && video.networkState <= video.HAVE_METADATA) {
15464 // attempt to prime the video element for programmatic access
15465 // this isn't necessary on the desktop but shouldn't hurt
15468 // playing and pausing synchronously during the transition to fullscreen
15469 // can get iOS ~6.1 devices into a play/pause loop
15470 this.setTimeout(function () {
15472 video.webkitEnterFullScreen();
15475 video.webkitEnterFullScreen();
15480 * Request that the `HTML5` Tech exit fullscreen.
15484 Html5.prototype.exitFullScreen = function exitFullScreen() {
15485 this.el_.webkitExitFullScreen();
15489 * A getter/setter for the `Html5` Tech's source object.
15490 * > Note: Please use {@link Html5#setSource}
15492 * @param {Tech~SourceObject} [src]
15493 * The source object you want to set on the `HTML5` techs element.
15495 * @return {Tech~SourceObject|undefined}
15496 * - The current source object when a source is not passed in.
15497 * - undefined when setting
15499 * @deprecated Since version 5.
15503 Html5.prototype.src = function src(_src) {
15504 if (_src === undefined) {
15505 return this.el_.src;
15508 // Setting src through `src` instead of `setSrc` will be deprecated
15513 * Reset the tech by removing all sources and then calling
15514 * {@link Html5.resetMediaElement}.
15518 Html5.prototype.reset = function reset() {
15519 Html5.resetMediaElement(this.el_);
15523 * Get the current source on the `HTML5` Tech. Falls back to returning the source from
15524 * the HTML5 media element.
15526 * @return {Tech~SourceObject}
15527 * The current source object from the HTML5 tech. With a fallback to the
15532 Html5.prototype.currentSrc = function currentSrc() {
15533 if (this.currentSource_) {
15534 return this.currentSource_.src;
15536 return this.el_.currentSrc;
15540 * Set controls attribute for the HTML5 media Element.
15542 * @param {string} val
15543 * Value to set the controls attribute to
15547 Html5.prototype.setControls = function setControls(val) {
15548 this.el_.controls = !!val;
15552 * Create and returns a remote {@link TextTrack} object.
15554 * @param {string} kind
15555 * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata)
15557 * @param {string} [label]
15558 * Label to identify the text track
15560 * @param {string} [language]
15561 * Two letter language abbreviation
15563 * @return {TextTrack}
15564 * The TextTrack that gets created.
15568 Html5.prototype.addTextTrack = function addTextTrack(kind, label, language) {
15569 if (!this.featuresNativeTextTracks) {
15570 return _Tech.prototype.addTextTrack.call(this, kind, label, language);
15573 return this.el_.addTextTrack(kind, label, language);
15577 * Creates either native TextTrack or an emulated TextTrack depending
15578 * on the value of `featuresNativeTextTracks`
15580 * @param {Object} options
15581 * The object should contain the options to initialize the TextTrack with.
15583 * @param {string} [options.kind]
15584 * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata).
15586 * @param {string} [options.label].
15587 * Label to identify the text track
15589 * @param {string} [options.language]
15590 * Two letter language abbreviation.
15592 * @param {boolean} [options.default]
15593 * Default this track to on.
15595 * @param {string} [options.id]
15596 * The internal id to assign this track.
15598 * @param {string} [options.src]
15599 * A source url for the track.
15601 * @return {HTMLTrackElement}
15602 * The track element that gets created.
15606 Html5.prototype.createRemoteTextTrack = function createRemoteTextTrack(options) {
15607 if (!this.featuresNativeTextTracks) {
15608 return _Tech.prototype.createRemoteTextTrack.call(this, options);
15610 var htmlTrackElement = _document2['default'].createElement('track');
15612 if (options.kind) {
15613 htmlTrackElement.kind = options.kind;
15615 if (options.label) {
15616 htmlTrackElement.label = options.label;
15618 if (options.language || options.srclang) {
15619 htmlTrackElement.srclang = options.language || options.srclang;
15621 if (options['default']) {
15622 htmlTrackElement['default'] = options['default'];
15625 htmlTrackElement.id = options.id;
15628 htmlTrackElement.src = options.src;
15631 return htmlTrackElement;
15635 * Creates a remote text track object and returns an html track element.
15637 * @param {Object} options The object should contain values for
15638 * kind, language, label, and src (location of the WebVTT file)
15639 * @param {Boolean} [manualCleanup=true] if set to false, the TextTrack will be
15640 * automatically removed from the video element whenever the source changes
15641 * @return {HTMLTrackElement} An Html Track Element.
15642 * This can be an emulated {@link HTMLTrackElement} or a native one.
15643 * @deprecated The default value of the "manualCleanup" parameter will default
15644 * to "false" in upcoming versions of Video.js
15648 Html5.prototype.addRemoteTextTrack = function addRemoteTextTrack(options, manualCleanup) {
15649 var htmlTrackElement = _Tech.prototype.addRemoteTextTrack.call(this, options, manualCleanup);
15651 if (this.featuresNativeTextTracks) {
15652 this.el().appendChild(htmlTrackElement);
15655 return htmlTrackElement;
15659 * Remove remote `TextTrack` from `TextTrackList` object
15661 * @param {TextTrack} track
15662 * `TextTrack` object to remove
15666 Html5.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) {
15667 _Tech.prototype.removeRemoteTextTrack.call(this, track);
15669 if (this.featuresNativeTextTracks) {
15670 var tracks = this.$$('track');
15672 var i = tracks.length;
15675 if (track === tracks[i] || track === tracks[i].track) {
15676 this.el().removeChild(tracks[i]);
15683 }(_tech2['default']);
15685 /* HTML5 Support Testing ---------------------------------------------------- */
15687 if (Dom.isReal()) {
15690 * Element for testing browser HTML5 media capabilities
15696 Html5.TEST_VID = _document2['default'].createElement('video');
15697 var track = _document2['default'].createElement('track');
15699 track.kind = 'captions';
15700 track.srclang = 'en';
15701 track.label = 'English';
15702 Html5.TEST_VID.appendChild(track);
15706 * Check if HTML5 media is supported by this browser/device.
15708 * @return {boolean}
15709 * - True if HTML5 media is supported.
15710 * - False if HTML5 media is not supported.
15712 Html5.isSupported = function () {
15713 // IE9 with no Media Player is a LIAR! (#984)
15715 Html5.TEST_VID.volume = 0.5;
15720 return !!(Html5.TEST_VID && Html5.TEST_VID.canPlayType);
15724 * Check if the volume can be changed in this browser/device.
15725 * Volume cannot be changed in a lot of mobile devices.
15726 * Specifically, it can't be changed from 1 on iOS.
15728 * @return {boolean}
15729 * - True if volume can be controlled
15730 * - False otherwise
15732 Html5.canControlVolume = function () {
15733 // IE will error if Windows Media Player not installed #3315
15735 var volume = Html5.TEST_VID.volume;
15737 Html5.TEST_VID.volume = volume / 2 + 0.1;
15738 return volume !== Html5.TEST_VID.volume;
15745 * Check if the playback rate can be changed in this browser/device.
15747 * @return {boolean}
15748 * - True if playback rate can be controlled
15749 * - False otherwise
15751 Html5.canControlPlaybackRate = function () {
15752 // Playback rate API is implemented in Android Chrome, but doesn't do anything
15753 // https://github.com/videojs/video.js/issues/3180
15754 if (browser.IS_ANDROID && browser.IS_CHROME) {
15757 // IE will error if Windows Media Player not installed #3315
15759 var playbackRate = Html5.TEST_VID.playbackRate;
15761 Html5.TEST_VID.playbackRate = playbackRate / 2 + 0.1;
15762 return playbackRate !== Html5.TEST_VID.playbackRate;
15769 * Check to see if native `TextTrack`s are supported by this browser/device.
15771 * @return {boolean}
15772 * - True if native `TextTrack`s are supported.
15773 * - False otherwise
15775 Html5.supportsNativeTextTracks = function () {
15776 return browser.IS_ANY_SAFARI;
15780 * Check to see if native `VideoTrack`s are supported by this browser/device
15782 * @return {boolean}
15783 * - True if native `VideoTrack`s are supported.
15784 * - False otherwise
15786 Html5.supportsNativeVideoTracks = function () {
15787 return !!(Html5.TEST_VID && Html5.TEST_VID.videoTracks);
15791 * Check to see if native `AudioTrack`s are supported by this browser/device
15793 * @return {boolean}
15794 * - True if native `AudioTrack`s are supported.
15795 * - False otherwise
15797 Html5.supportsNativeAudioTracks = function () {
15798 return !!(Html5.TEST_VID && Html5.TEST_VID.audioTracks);
15802 * An array of events available on the Html5 tech.
15807 Html5.Events = ['loadstart', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'seeking', 'seeked', 'ended', 'durationchange', 'timeupdate', 'progress', 'play', 'pause', 'ratechange', 'volumechange'];
15810 * Boolean indicating whether the `Tech` supports volume control.
15813 * @default {@link Html5.canControlVolume}
15815 Html5.prototype.featuresVolumeControl = Html5.canControlVolume();
15818 * Boolean indicating whether the `Tech` supports changing the speed at which the media
15820 * - Set player to play 2x (twice) as fast
15821 * - Set player to play 0.5x (half) as fast
15824 * @default {@link Html5.canControlPlaybackRate}
15826 Html5.prototype.featuresPlaybackRate = Html5.canControlPlaybackRate();
15829 * Boolean indicating whether the `HTML5` tech currently supports the media element
15830 * moving in the DOM. iOS breaks if you move the media element, so this is set this to
15831 * false there. Everywhere else this should be true.
15836 Html5.prototype.movingMediaElementInDOM = !browser.IS_IOS;
15838 // TODO: Previous comment: No longer appears to be used. Can probably be removed.
15841 * Boolean indicating whether the `HTML5` tech currently supports automatic media resize
15842 * when going into fullscreen.
15847 Html5.prototype.featuresFullscreenResize = true;
15850 * Boolean indicating whether the `HTML5` tech currently supports the progress event.
15851 * If this is false, manual `progress` events will be triggred instead.
15856 Html5.prototype.featuresProgressEvents = true;
15859 * Boolean indicating whether the `HTML5` tech currently supports the timeupdate event.
15860 * If this is false, manual `timeupdate` events will be triggred instead.
15864 Html5.prototype.featuresTimeupdateEvents = true;
15867 * Boolean indicating whether the `HTML5` tech currently supports native `TextTrack`s.
15870 * @default {@link Html5.supportsNativeTextTracks}
15872 Html5.prototype.featuresNativeTextTracks = Html5.supportsNativeTextTracks();
15875 * Boolean indicating whether the `HTML5` tech currently supports native `VideoTrack`s.
15878 * @default {@link Html5.supportsNativeVideoTracks}
15880 Html5.prototype.featuresNativeVideoTracks = Html5.supportsNativeVideoTracks();
15883 * Boolean indicating whether the `HTML5` tech currently supports native `AudioTrack`s.
15886 * @default {@link Html5.supportsNativeAudioTracks}
15888 Html5.prototype.featuresNativeAudioTracks = Html5.supportsNativeAudioTracks();
15890 // HTML5 Feature detection and Device Fixes --------------------------------- //
15891 var canPlayType = Html5.TEST_VID && Html5.TEST_VID.constructor.prototype.canPlayType;
15892 var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
15893 var mp4RE = /^video\/mp4/i;
15895 Html5.patchCanPlayType = function () {
15897 // Android 4.0 and above can play HLS to some extent but it reports being unable to do so
15898 if (browser.ANDROID_VERSION >= 4.0 && !browser.IS_FIREFOX) {
15899 Html5.TEST_VID.constructor.prototype.canPlayType = function (type) {
15900 if (type && mpegurlRE.test(type)) {
15903 return canPlayType.call(this, type);
15906 // Override Android 2.2 and less canPlayType method which is broken
15907 } else if (browser.IS_OLD_ANDROID) {
15908 Html5.TEST_VID.constructor.prototype.canPlayType = function (type) {
15909 if (type && mp4RE.test(type)) {
15912 return canPlayType.call(this, type);
15917 Html5.unpatchCanPlayType = function () {
15918 var r = Html5.TEST_VID.constructor.prototype.canPlayType;
15920 Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType;
15924 // by default, patch the media element
15925 Html5.patchCanPlayType();
15927 Html5.disposeMediaElement = function (el) {
15932 if (el.parentNode) {
15933 el.parentNode.removeChild(el);
15936 // remove any child track or source nodes to prevent their loading
15937 while (el.hasChildNodes()) {
15938 el.removeChild(el.firstChild);
15941 // remove any src reference. not setting `src=''` because that causes a warning
15943 el.removeAttribute('src');
15945 // force the media element to update its loading state by calling load()
15946 // however IE on Windows 7N has a bug that throws an error so need a try/catch (#793)
15947 if (typeof el.load === 'function') {
15948 // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
15959 Html5.resetMediaElement = function (el) {
15964 var sources = el.querySelectorAll('source');
15965 var i = sources.length;
15968 el.removeChild(sources[i]);
15971 // remove any src reference.
15972 // not setting `src=''` because that throws an error
15973 el.removeAttribute('src');
15975 if (typeof el.load === 'function') {
15976 // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
15987 /* Native HTML5 element property wrapping ----------------------------------- */
15988 // Wrap native properties with a getter
15991 * Get the value of `paused` from the media element. `paused` indicates whether the media element
15992 * is currently paused or not.
15994 * @method Html5#paused
15995 * @return {boolean}
15996 * The value of `paused` from the media element.
15998 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused}
16003 * Get the value of `currentTime` from the media element. `currentTime` indicates
16004 * the current second that the media is at in playback.
16006 * @method Html5#currentTime
16008 * The value of `currentTime` from the media element.
16010 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-currenttime}
16015 * Get the value of `buffered` from the media element. `buffered` is a `TimeRange`
16016 * object that represents the parts of the media that are already downloaded and
16017 * available for playback.
16019 * @method Html5#buffered
16020 * @return {TimeRange}
16021 * The value of `buffered` from the media element.
16023 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-buffered}
16028 * Get the value of `volume` from the media element. `volume` indicates
16029 * the current playback volume of audio for a media. `volume` will be a value from 0
16030 * (silent) to 1 (loudest and default).
16032 * @method Html5#volume
16034 * The value of `volume` from the media element. Value will be between 0-1.
16036 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume}
16041 * Get the value of `muted` from the media element. `muted` indicates
16042 * that the volume for the media should be set to silent. This does not actually change
16043 * the `volume` attribute.
16045 * @method Html5#muted
16046 * @return {boolean}
16047 * - True if the value of `volume` should be ignored and the audio set to silent.
16048 * - False if the value of `volume` should be used.
16050 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
16055 * Get the value of `poster` from the media element. `poster` indicates
16056 * that the url of an image file that can/will be shown when no media data is available.
16058 * @method Html5#poster
16060 * The value of `poster` from the media element. Value will be a url to an
16063 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-video-poster}
16068 * Get the value of `preload` from the media element. `preload` indicates
16069 * what should download before the media is interacted with. It can have the following
16071 * - none: nothing should be downloaded
16072 * - metadata: poster and the first few frames of the media may be downloaded to get
16073 * media dimensions and other metadata
16074 * - auto: allow the media and metadata for the media to be downloaded before
16077 * @method Html5#preload
16079 * The value of `preload` from the media element. Will be 'none', 'metadata',
16082 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload}
16087 * Get the value of `autoplay` from the media element. `autoplay` indicates
16088 * that the media should start to play as soon as the page is ready.
16090 * @method Html5#autoplay
16091 * @return {boolean}
16092 * - The value of `autoplay` from the media element.
16093 * - True indicates that the media should start as soon as the page loads.
16094 * - False indicates that the media should not start as soon as the page loads.
16096 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
16101 * Get the value of `controls` from the media element. `controls` indicates
16102 * whether the native media controls should be shown or hidden.
16104 * @method Html5#controls
16105 * @return {boolean}
16106 * - The value of `controls` from the media element.
16107 * - True indicates that native controls should be showing.
16108 * - False indicates that native controls should be hidden.
16110 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-controls}
16115 * Get the value of `loop` from the media element. `loop` indicates
16116 * that the media should return to the start of the media and continue playing once
16117 * it reaches the end.
16119 * @method Html5#loop
16120 * @return {boolean}
16121 * - The value of `loop` from the media element.
16122 * - True indicates that playback should seek back to start once
16123 * the end of a media is reached.
16124 * - False indicates that playback should not loop back to the start when the
16125 * end of the media is reached.
16127 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
16132 * Get the value of the `error` from the media element. `error` indicates any
16133 * MediaError that may have occurred during playback. If error returns null there is no
16136 * @method Html5#error
16137 * @return {MediaError|null}
16138 * The value of `error` from the media element. Will be `MediaError` if there
16139 * is a current error and null otherwise.
16141 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-error}
16146 * Get the value of `seeking` from the media element. `seeking` indicates whether the
16147 * media is currently seeking to a new position or not.
16149 * @method Html5#seeking
16150 * @return {boolean}
16151 * - The value of `seeking` from the media element.
16152 * - True indicates that the media is currently seeking to a new position.
16153 * - Flase indicates that the media is not seeking to a new position at this time.
16155 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seeking}
16160 * Get the value of `seekable` from the media element. `seekable` returns a
16161 * `TimeRange` object indicating ranges of time that can currently be `seeked` to.
16163 * @method Html5#seekable
16164 * @return {TimeRange}
16165 * The value of `seekable` from the media element. A `TimeRange` object
16166 * indicating the current ranges of time that can be seeked to.
16168 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seekable}
16173 * Get the value of `ended` from the media element. `ended` indicates whether
16174 * the media has reached the end or not.
16176 * @method Html5#ended
16177 * @return {boolean}
16178 * - The value of `ended` from the media element.
16179 * - True indicates that the media has ended.
16180 * - False indicates that the media has not ended.
16182 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-ended}
16187 * Get the value of `defaultMuted` from the media element. `defaultMuted` indicates
16188 * whether the media should start muted or not. Only changes the default state of the
16189 * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
16192 * @method Html5#defaultMuted
16193 * @return {boolean}
16194 * - The value of `defaultMuted` from the media element.
16195 * - True indicates that the media should start muted.
16196 * - False indicates that the media should not start muted
16198 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted}
16203 * Get the value of `playbackRate` from the media element. `playbackRate` indicates
16204 * the rate at which the media is currently playing back. Examples:
16205 * - if playbackRate is set to 2, media will play twice as fast.
16206 * - if playbackRate is set to 0.5, media will play half as fast.
16208 * @method Html5#playbackRate
16210 * The value of `playbackRate` from the media element. A number indicating
16211 * the current playback speed of the media, where 1 is normal speed.
16213 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate}
16218 * Get the value of `played` from the media element. `played` returns a `TimeRange`
16219 * object representing points in the media timeline that have been played.
16221 * @method Html5#played
16222 * @return {TimeRange}
16223 * The value of `played` from the media element. A `TimeRange` object indicating
16224 * the ranges of time that have been played.
16226 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-played}
16231 * Get the value of `networkState` from the media element. `networkState` indicates
16232 * the current network state. It returns an enumeration from the following list:
16233 * - 0: NETWORK_EMPTY
16235 * - 2: NETWORK_LOADING
16236 * - 3: NETWORK_NO_SOURCE
16238 * @method Html5#networkState
16240 * The value of `networkState` from the media element. This will be a number
16241 * from the list in the description.
16243 * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-networkstate}
16248 * Get the value of `readyState` from the media element. `readyState` indicates
16249 * the current state of the media element. It returns an enumeration from the
16251 * - 0: HAVE_NOTHING
16252 * - 1: HAVE_METADATA
16253 * - 2: HAVE_CURRENT_DATA
16254 * - 3: HAVE_FUTURE_DATA
16255 * - 4: HAVE_ENOUGH_DATA
16257 * @method Html5#readyState
16259 * The value of `readyState` from the media element. This will be a number
16260 * from the list in the description.
16262 * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#ready-states}
16267 * Get the value of `videoWidth` from the video element. `videoWidth` indicates
16268 * the current width of the video in css pixels.
16270 * @method Html5#videoWidth
16272 * The value of `videoWidth` from the video element. This will be a number
16275 * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth}
16280 * Get the value of `videoHeight` from the video element. `videoHeigth` indicates
16281 * the current height of the video in css pixels.
16283 * @method Html5#videoHeight
16285 * The value of `videoHeight` from the video element. This will be a number
16288 * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth}
16290 'videoHeight'].forEach(function (prop) {
16291 Html5.prototype[prop] = function () {
16292 return this.el_[prop];
16296 // Wrap native properties with a setter in this format:
16297 // set + toTitleCase(name)
16300 * Set the value of `volume` on the media element. `volume` indicates the current
16301 * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
16304 * @method Html5#setVolume
16305 * @param {number} percentAsDecimal
16306 * The volume percent as a decimal. Valid range is from 0-1.
16308 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume}
16313 * Set the value of `muted` on the media element. `muted` indicates the current
16314 * audio level should be silent.
16316 * @method Html5#setMuted
16317 * @param {boolean} muted
16318 * - True if the audio should be set to silent
16319 * - False otherwise
16321 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
16326 * Set the value of `src` on the media element. `src` indicates the current
16327 * {@link Tech~SourceObject} for the media.
16329 * @method Html5#setSrc
16330 * @param {Tech~SourceObject} src
16331 * The source object to set as the current source.
16333 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-src}
16338 * Set the value of `poster` on the media element. `poster` is the url to
16339 * an image file that can/will be shown when no media data is available.
16341 * @method Html5#setPoster
16342 * @param {string} poster
16343 * The url to an image that should be used as the `poster` for the media
16346 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-poster}
16351 * Set the value of `preload` on the media element. `preload` indicates
16352 * what should download before the media is interacted with. It can have the following
16354 * - none: nothing should be downloaded
16355 * - metadata: poster and the first few frames of the media may be downloaded to get
16356 * media dimensions and other metadata
16357 * - auto: allow the media and metadata for the media to be downloaded before
16360 * @method Html5#setPreload
16361 * @param {string} preload
16362 * The value of `preload` to set on the media element. Must be 'none', 'metadata',
16365 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload}
16370 * Set the value of `autoplay` on the media element. `autoplay` indicates
16371 * that the media should start to play as soon as the page is ready.
16373 * @method Html5#setAutoplay
16374 * @param {boolean} autoplay
16375 * - True indicates that the media should start as soon as the page loads.
16376 * - False indicates that the media should not start as soon as the page loads.
16378 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
16383 * Set the value of `loop` on the media element. `loop` indicates
16384 * that the media should return to the start of the media and continue playing once
16385 * it reaches the end.
16387 * @method Html5#setLoop
16388 * @param {boolean} loop
16389 * - True indicates that playback should seek back to start once
16390 * the end of a media is reached.
16391 * - False indicates that playback should not loop back to the start when the
16392 * end of the media is reached.
16394 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
16399 * Set the value of `playbackRate` on the media element. `playbackRate` indicates
16400 * the rate at which the media should play back. Examples:
16401 * - if playbackRate is set to 2, media will play twice as fast.
16402 * - if playbackRate is set to 0.5, media will play half as fast.
16404 * @method Html5#setPlaybackRate
16406 * The value of `playbackRate` from the media element. A number indicating
16407 * the current playback speed of the media, where 1 is normal speed.
16409 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate}
16411 'playbackRate'].forEach(function (prop) {
16412 Html5.prototype['set' + (0, _toTitleCase2['default'])(prop)] = function (v) {
16413 this.el_[prop] = v;
16417 // wrap native functions with a function
16420 * A wrapper around the media elements `pause` function. This will call the `HTML5`
16421 * media elements `pause` function.
16423 * @method Html5#pause
16424 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-pause}
16429 * A wrapper around the media elements `load` function. This will call the `HTML5`s
16430 * media element `load` function.
16432 * @method Html5#load
16433 * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-load}
16435 'load'].forEach(function (prop) {
16436 Html5.prototype[prop] = function () {
16437 return this.el_[prop]();
16441 _tech2['default'].withSourceHandlers(Html5);
16444 * Native source handler for Html5, simply passes the source to the media element.
16446 * @proprety {Tech~SourceObject} source
16447 * The source object
16449 * @proprety {Html5} tech
16450 * The instance of the HTML5 tech.
16452 Html5.nativeSourceHandler = {};
16455 * Check if the media element can play the given mime type.
16457 * @param {string} type
16458 * The mimetype to check
16461 * 'probably', 'maybe', or '' (empty string)
16463 Html5.nativeSourceHandler.canPlayType = function (type) {
16464 // IE9 on Windows 7 without MediaPlayer throws an error here
16465 // https://github.com/videojs/video.js/issues/519
16467 return Html5.TEST_VID.canPlayType(type);
16474 * Check if the media element can handle a source natively.
16476 * @param {Tech~SourceObject} source
16477 * The source object
16479 * @param {Object} [options]
16480 * Options to be passed to the tech.
16483 * 'probably', 'maybe', or '' (empty string).
16485 Html5.nativeSourceHandler.canHandleSource = function (source, options) {
16487 // If a type was provided we should rely on that
16489 return Html5.nativeSourceHandler.canPlayType(source.type);
16491 // If no type, fall back to checking 'video/[EXTENSION]'
16492 } else if (source.src) {
16493 var ext = Url.getFileExtension(source.src);
16495 return Html5.nativeSourceHandler.canPlayType('video/' + ext);
16502 * Pass the source to the native media element.
16504 * @param {Tech~SourceObject} source
16505 * The source object
16507 * @param {Html5} tech
16508 * The instance of the Html5 tech
16510 * @param {Object} [options]
16511 * The options to pass to the source
16513 Html5.nativeSourceHandler.handleSource = function (source, tech, options) {
16514 tech.setSrc(source.src);
16518 * A noop for the native dispose function, as cleanup is not needed.
16520 Html5.nativeSourceHandler.dispose = function () {};
16522 // Register the native source handler
16523 Html5.registerSourceHandler(Html5.nativeSourceHandler);
16525 _component2['default'].registerComponent('Html5', Html5);
16526 _tech2['default'].registerTech('Html5', Html5);
16527 exports['default'] = Html5;
16529 },{"5":5,"62":62,"78":78,"81":81,"83":83,"86":86,"87":87,"88":88,"91":91,"92":92,"94":94,"95":95,"98":98}],61:[function(_dereq_,module,exports){
16532 exports.__esModule = true;
16534 var _component = _dereq_(5);
16536 var _component2 = _interopRequireDefault(_component);
16538 var _tech = _dereq_(62);
16540 var _tech2 = _interopRequireDefault(_tech);
16542 var _toTitleCase = _dereq_(91);
16544 var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
16546 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16548 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16550 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
16552 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
16558 * The `MediaLoader` is the `Component` that decides which playback technology to load
16559 * when a player is initialized.
16561 * @extends Component
16563 var MediaLoader = function (_Component) {
16564 _inherits(MediaLoader, _Component);
16567 * Create an instance of this class.
16569 * @param {Player} player
16570 * The `Player` that this class should attach to.
16572 * @param {Object} [options]
16573 * The key/value store of player options.
16575 * @param {Component~ReadyCallback} [ready]
16576 * The function that is run when this component is ready.
16578 function MediaLoader(player, options, ready) {
16579 _classCallCheck(this, MediaLoader);
16581 // If there are no sources when the player is initialized,
16582 // load the first supported playback technology.
16584 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options, ready));
16586 if (!options.playerOptions.sources || options.playerOptions.sources.length === 0) {
16587 for (var i = 0, j = options.playerOptions.techOrder; i < j.length; i++) {
16588 var techName = (0, _toTitleCase2['default'])(j[i]);
16589 var tech = _tech2['default'].getTech(techName);
16591 // Support old behavior of techs being registered as components.
16592 // Remove once that deprecated behavior is removed.
16594 tech = _component2['default'].getComponent(techName);
16597 // Check if the browser supports this technology
16598 if (tech && tech.isSupported()) {
16599 player.loadTech_(techName);
16604 // Loop through playback technologies (HTML5, Flash) and check for support.
16605 // Then load the best source.
16606 // A few assumptions here:
16607 // All playback technologies respect preload false.
16608 player.src(options.playerOptions.sources);
16613 return MediaLoader;
16614 }(_component2['default']);
16616 _component2['default'].registerComponent('MediaLoader', MediaLoader);
16617 exports['default'] = MediaLoader;
16619 },{"5":5,"62":62,"91":91}],62:[function(_dereq_,module,exports){
16622 exports.__esModule = true;
16624 var _component = _dereq_(5);
16626 var _component2 = _interopRequireDefault(_component);
16628 var _htmlTrackElement = _dereq_(66);
16630 var _htmlTrackElement2 = _interopRequireDefault(_htmlTrackElement);
16632 var _htmlTrackElementList = _dereq_(65);
16634 var _htmlTrackElementList2 = _interopRequireDefault(_htmlTrackElementList);
16636 var _mergeOptions = _dereq_(87);
16638 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
16640 var _textTrack = _dereq_(72);
16642 var _textTrack2 = _interopRequireDefault(_textTrack);
16644 var _textTrackList = _dereq_(70);
16646 var _textTrackList2 = _interopRequireDefault(_textTrackList);
16648 var _videoTrackList = _dereq_(76);
16650 var _videoTrackList2 = _interopRequireDefault(_videoTrackList);
16652 var _audioTrackList = _dereq_(63);
16654 var _audioTrackList2 = _interopRequireDefault(_audioTrackList);
16656 var _fn = _dereq_(83);
16658 var Fn = _interopRequireWildcard(_fn);
16660 var _log = _dereq_(86);
16662 var _log2 = _interopRequireDefault(_log);
16664 var _timeRanges = _dereq_(90);
16666 var _buffer = _dereq_(79);
16668 var _mediaError = _dereq_(46);
16670 var _mediaError2 = _interopRequireDefault(_mediaError);
16672 var _window = _dereq_(95);
16674 var _window2 = _interopRequireDefault(_window);
16676 var _document = _dereq_(94);
16678 var _document2 = _interopRequireDefault(_document);
16680 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
16682 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
16684 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16686 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
16688 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
16693 * An Object containing a structure like: `{src: 'url', type: 'mimetype'}` or string
16694 * that just contains the src url alone.
16695 * * `var SourceObject = {src: 'http://ex.com/video.mp4', type: 'video/mp4'};`
16696 * `var SourceString = 'http://example.com/some-video.mp4';`
16698 * @typedef {Object|string} Tech~SourceObject
16700 * @property {string} src
16701 * The url to the source
16703 * @property {string} type
16704 * The mime type of the source
16708 * A function used by {@link Tech} to create a new {@link TextTrack}.
16710 * @param {Tech} self
16711 * An instance of the Tech class.
16713 * @param {string} kind
16714 * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata)
16716 * @param {string} [label]
16717 * Label to identify the text track
16719 * @param {string} [language]
16720 * Two letter language abbreviation
16722 * @param {Object} [options={}]
16723 * An object with additional text track options
16725 * @return {TextTrack}
16726 * The text track that was created.
16728 function createTrackHelper(self, kind, label, language) {
16729 var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
16731 var tracks = self.textTracks();
16733 options.kind = kind;
16736 options.label = label;
16739 options.language = language;
16741 options.tech = self;
16743 var track = new _textTrack2['default'](options);
16745 tracks.addTrack_(track);
16751 * This is the base class for media playback technology controllers, such as
16752 * {@link Flash} and {@link HTML5}
16754 * @extends Component
16757 var Tech = function (_Component) {
16758 _inherits(Tech, _Component);
16761 * Create an instance of this Tech.
16763 * @param {Object} [options]
16764 * The key/value store of player options.
16766 * @param {Component~ReadyCallback} ready
16767 * Callback function to call when the `HTML5` Tech is ready.
16770 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16771 var ready = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {};
16773 _classCallCheck(this, Tech);
16775 // we don't want the tech to report user activity automatically.
16776 // This is done manually in addControlsListeners
16777 options.reportTouchActivity = false;
16779 // keep track of whether the current source has played at all to
16780 // implement a very limited played()
16781 var _this = _possibleConstructorReturn(this, _Component.call(this, null, options, ready));
16783 _this.hasStarted_ = false;
16784 _this.on('playing', function () {
16785 this.hasStarted_ = true;
16787 _this.on('loadstart', function () {
16788 this.hasStarted_ = false;
16791 _this.textTracks_ = options.textTracks;
16792 _this.videoTracks_ = options.videoTracks;
16793 _this.audioTracks_ = options.audioTracks;
16795 // Manually track progress in cases where the browser/flash player doesn't report it.
16796 if (!_this.featuresProgressEvents) {
16797 _this.manualProgressOn();
16800 // Manually track timeupdates in cases where the browser/flash player doesn't report it.
16801 if (!_this.featuresTimeupdateEvents) {
16802 _this.manualTimeUpdatesOn();
16805 ['Text', 'Audio', 'Video'].forEach(function (track) {
16806 if (options['native' + track + 'Tracks'] === false) {
16807 _this['featuresNative' + track + 'Tracks'] = false;
16811 if (options.nativeCaptions === false) {
16812 _this.featuresNativeTextTracks = false;
16815 if (!_this.featuresNativeTextTracks) {
16816 _this.emulateTextTracks();
16819 _this.autoRemoteTextTracks_ = new _textTrackList2['default']();
16821 _this.initTextTrackListeners();
16822 _this.initTrackListeners();
16824 // Turn on component tap events only if not using native controls
16825 if (!options.nativeControlsForTouch) {
16826 _this.emitTapEvents();
16831 /* Fallbacks for unsupported event types
16832 ================================================================================ */
16835 * Polyfill the `progress` event for browsers that don't support it natively.
16837 * @see {@link Tech#trackProgress}
16841 Tech.prototype.manualProgressOn = function manualProgressOn() {
16842 this.on('durationchange', this.onDurationChange);
16844 this.manualProgress = true;
16846 // Trigger progress watching when a source begins loading
16847 this.one('ready', this.trackProgress);
16851 * Turn off the polyfill for `progress` events that was created in
16852 * {@link Tech#manualProgressOn}
16856 Tech.prototype.manualProgressOff = function manualProgressOff() {
16857 this.manualProgress = false;
16858 this.stopTrackingProgress();
16860 this.off('durationchange', this.onDurationChange);
16864 * This is used to trigger a `progress` event when the buffered percent changes. It
16865 * sets an interval function that will be called every 500 milliseconds to check if the
16866 * buffer end percent has changed.
16868 * > This function is called by {@link Tech#manualProgressOn}
16870 * @param {EventTarget~Event} event
16871 * The `ready` event that caused this to run.
16873 * @listens Tech#ready
16874 * @fires Tech#progress
16878 Tech.prototype.trackProgress = function trackProgress(event) {
16879 this.stopTrackingProgress();
16880 this.progressInterval = this.setInterval(Fn.bind(this, function () {
16881 // Don't trigger unless buffered amount is greater than last time
16883 var numBufferedPercent = this.bufferedPercent();
16885 if (this.bufferedPercent_ !== numBufferedPercent) {
16887 * See {@link Player#progress}
16889 * @event Tech#progress
16890 * @type {EventTarget~Event}
16892 this.trigger('progress');
16895 this.bufferedPercent_ = numBufferedPercent;
16897 if (numBufferedPercent === 1) {
16898 this.stopTrackingProgress();
16904 * Update our internal duration on a `durationchange` event by calling
16905 * {@link Tech#duration}.
16907 * @param {EventTarget~Event} event
16908 * The `durationchange` event that caused this to run.
16910 * @listens Tech#durationchange
16914 Tech.prototype.onDurationChange = function onDurationChange(event) {
16915 this.duration_ = this.duration();
16919 * Get and create a `TimeRange` object for buffering.
16921 * @return {TimeRange}
16922 * The time range object that was created.
16926 Tech.prototype.buffered = function buffered() {
16927 return (0, _timeRanges.createTimeRange)(0, 0);
16931 * Get the percentage of the current video that is currently buffered.
16934 * A number from 0 to 1 that represents the decimal percentage of the
16935 * video that is buffered.
16940 Tech.prototype.bufferedPercent = function bufferedPercent() {
16941 return (0, _buffer.bufferedPercent)(this.buffered(), this.duration_);
16945 * Turn off the polyfill for `progress` events that was created in
16946 * {@link Tech#manualProgressOn}
16947 * Stop manually tracking progress events by clearing the interval that was set in
16948 * {@link Tech#trackProgress}.
16952 Tech.prototype.stopTrackingProgress = function stopTrackingProgress() {
16953 this.clearInterval(this.progressInterval);
16957 * Polyfill the `timeupdate` event for browsers that don't support it.
16959 * @see {@link Tech#trackCurrentTime}
16963 Tech.prototype.manualTimeUpdatesOn = function manualTimeUpdatesOn() {
16964 this.manualTimeUpdates = true;
16966 this.on('play', this.trackCurrentTime);
16967 this.on('pause', this.stopTrackingCurrentTime);
16971 * Turn off the polyfill for `timeupdate` events that was created in
16972 * {@link Tech#manualTimeUpdatesOn}
16976 Tech.prototype.manualTimeUpdatesOff = function manualTimeUpdatesOff() {
16977 this.manualTimeUpdates = false;
16978 this.stopTrackingCurrentTime();
16979 this.off('play', this.trackCurrentTime);
16980 this.off('pause', this.stopTrackingCurrentTime);
16984 * Sets up an interval function to track current time and trigger `timeupdate` every
16985 * 250 milliseconds.
16987 * @listens Tech#play
16988 * @triggers Tech#timeupdate
16992 Tech.prototype.trackCurrentTime = function trackCurrentTime() {
16993 if (this.currentTimeInterval) {
16994 this.stopTrackingCurrentTime();
16996 this.currentTimeInterval = this.setInterval(function () {
16998 * Triggered at an interval of 250ms to indicated that time is passing in the video.
17000 * @event Tech#timeupdate
17001 * @type {EventTarget~Event}
17003 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
17005 // 42 = 24 fps // 250 is what Webkit uses // FF uses 15
17010 * Stop the interval function created in {@link Tech#trackCurrentTime} so that the
17011 * `timeupdate` event is no longer triggered.
17013 * @listens {Tech#pause}
17017 Tech.prototype.stopTrackingCurrentTime = function stopTrackingCurrentTime() {
17018 this.clearInterval(this.currentTimeInterval);
17020 // #1002 - if the video ends right before the next timeupdate would happen,
17021 // the progress bar won't make it all the way to the end
17022 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
17026 * Turn off all event polyfills, clear the `Tech`s {@link AudioTrackList},
17027 * {@link VideoTrackList}, and {@link TextTrackList}, and dispose of this Tech.
17029 * @fires Component#dispose
17033 Tech.prototype.dispose = function dispose() {
17035 // clear out all tracks because we can't reuse them between techs
17036 this.clearTracks(['audio', 'video', 'text']);
17038 // Turn off any manual progress or timeupdate tracking
17039 if (this.manualProgress) {
17040 this.manualProgressOff();
17043 if (this.manualTimeUpdates) {
17044 this.manualTimeUpdatesOff();
17047 _Component.prototype.dispose.call(this);
17051 * Clear out a single `TrackList` or an array of `TrackLists` given their names.
17053 * > Note: Techs without source handlers should call this between sources for `video`
17054 * & `audio` tracks. You don't want to use them between tracks!
17056 * @param {string[]|string} types
17057 * TrackList names to clear, valid names are `video`, `audio`, and
17062 Tech.prototype.clearTracks = function clearTracks(types) {
17065 types = [].concat(types);
17066 // clear out all tracks because we can't reuse them between techs
17067 types.forEach(function (type) {
17068 var list = _this2[type + 'Tracks']() || [];
17069 var i = list.length;
17072 var track = list[i];
17074 if (type === 'text') {
17075 _this2.removeRemoteTextTrack(track);
17077 list.removeTrack_(track);
17083 * Remove any TextTracks added via addRemoteTextTrack that are
17084 * flagged for automatic garbage collection
17088 Tech.prototype.cleanupAutoTextTracks = function cleanupAutoTextTracks() {
17089 var list = this.autoRemoteTextTracks_ || [];
17090 var i = list.length;
17093 var track = list[i];
17095 this.removeRemoteTextTrack(track);
17100 * Reset the tech, which will removes all sources and reset the internal readyState.
17106 Tech.prototype.reset = function reset() {};
17109 * Get or set an error on the Tech.
17111 * @param {MediaError} [err]
17112 * Error to set on the Tech
17114 * @return {MediaError|null}
17115 * The current error object on the tech, or null if there isn't one.
17119 Tech.prototype.error = function error(err) {
17120 if (err !== undefined) {
17121 this.error_ = new _mediaError2['default'](err);
17122 this.trigger('error');
17124 return this.error_;
17128 * Returns the `TimeRange`s that have been played through for the current source.
17130 * > NOTE: This implementation is incomplete. It does not track the played `TimeRange`.
17131 * It only checks whether the source has played at all or not.
17133 * @return {TimeRange}
17134 * - A single time range if this video has played
17135 * - An empty set of ranges if not.
17139 Tech.prototype.played = function played() {
17140 if (this.hasStarted_) {
17141 return (0, _timeRanges.createTimeRange)(0, 0);
17143 return (0, _timeRanges.createTimeRange)();
17147 * Causes a manual time update to occur if {@link Tech#manualTimeUpdatesOn} was
17148 * previously called.
17150 * @fires Tech#timeupdate
17154 Tech.prototype.setCurrentTime = function setCurrentTime() {
17155 // improve the accuracy of manual timeupdates
17156 if (this.manualTimeUpdates) {
17158 * A manual `timeupdate` event.
17160 * @event Tech#timeupdate
17161 * @type {EventTarget~Event}
17163 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true });
17168 * Turn on listeners for {@link TextTrackList} events. This adds
17169 * {@link EventTarget~EventListeners} for `texttrackchange`, `addtrack` and
17172 * @fires Tech#texttrackchange
17176 Tech.prototype.initTextTrackListeners = function initTextTrackListeners() {
17177 var textTrackListChanges = Fn.bind(this, function () {
17179 * Triggered when tracks are added or removed on the Tech {@link TextTrackList}
17181 * @event Tech#texttrackchange
17182 * @type {EventTarget~Event}
17184 this.trigger('texttrackchange');
17187 var tracks = this.textTracks();
17193 tracks.addEventListener('removetrack', textTrackListChanges);
17194 tracks.addEventListener('addtrack', textTrackListChanges);
17196 this.on('dispose', Fn.bind(this, function () {
17197 tracks.removeEventListener('removetrack', textTrackListChanges);
17198 tracks.removeEventListener('addtrack', textTrackListChanges);
17203 * Turn on listeners for {@link VideoTrackList} and {@link {AudioTrackList} events.
17204 * This adds {@link EventTarget~EventListeners} for `addtrack`, and `removetrack`.
17206 * @fires Tech#audiotrackchange
17207 * @fires Tech#videotrackchange
17211 Tech.prototype.initTrackListeners = function initTrackListeners() {
17214 var trackTypes = ['video', 'audio'];
17216 trackTypes.forEach(function (type) {
17218 * Triggered when tracks are added or removed on the Tech {@link AudioTrackList}
17220 * @event Tech#audiotrackchange
17221 * @type {EventTarget~Event}
17225 * Triggered when tracks are added or removed on the Tech {@link VideoTrackList}
17227 * @event Tech#videotrackchange
17228 * @type {EventTarget~Event}
17230 var trackListChanges = function trackListChanges() {
17231 _this3.trigger(type + 'trackchange');
17234 var tracks = _this3[type + 'Tracks']();
17236 tracks.addEventListener('removetrack', trackListChanges);
17237 tracks.addEventListener('addtrack', trackListChanges);
17239 _this3.on('dispose', function () {
17240 tracks.removeEventListener('removetrack', trackListChanges);
17241 tracks.removeEventListener('addtrack', trackListChanges);
17247 * Emulate TextTracks using vtt.js if necessary
17249 * @fires Tech#vttjsloaded
17250 * @fires Tech#vttjserror
17251 * @fires Tech#texttrackchange
17255 Tech.prototype.addWebVttScript_ = function addWebVttScript_() {
17258 if (!_window2['default'].WebVTT && this.el().parentNode !== null && this.el().parentNode !== undefined) {
17260 var script = _document2['default'].createElement('script');
17262 script.src = _this4.options_['vtt.js'] || 'https://cdn.rawgit.com/gkatsev/vtt.js/vjs-v0.12.1/dist/vtt.min.js';
17263 script.onload = function () {
17265 * Fired when vtt.js is loaded.
17267 * @event Tech#vttjsloaded
17268 * @type {EventTarget~Event}
17270 _this4.trigger('vttjsloaded');
17272 script.onerror = function () {
17274 * Fired when vtt.js was not loaded due to an error
17276 * @event Tech#vttjsloaded
17277 * @type {EventTarget~Event}
17279 _this4.trigger('vttjserror');
17281 _this4.on('dispose', function () {
17282 script.onload = null;
17283 script.onerror = null;
17285 // but have not loaded yet and we set it to true before the inject so that
17286 // we don't overwrite the injected window.WebVTT if it loads right away
17287 _window2['default'].WebVTT = true;
17288 _this4.el().parentNode.appendChild(script);
17294 * Emulate texttracks
17296 * @method emulateTextTracks
17300 Tech.prototype.emulateTextTracks = function emulateTextTracks() {
17303 var tracks = this.textTracks();
17309 this.remoteTextTracks().on('addtrack', function (e) {
17310 _this5.textTracks().addTrack_(e.track);
17313 this.remoteTextTracks().on('removetrack', function (e) {
17314 _this5.textTracks().removeTrack_(e.track);
17317 // Initially, Tech.el_ is a child of a dummy-div wait until the Component system
17318 // signals that the Tech is ready at which point Tech.el_ is part of the DOM
17319 // before inserting the WebVTT script
17320 this.on('ready', this.addWebVttScript_);
17322 var updateDisplay = function updateDisplay() {
17323 return _this5.trigger('texttrackchange');
17325 var textTracksChanges = function textTracksChanges() {
17328 for (var i = 0; i < tracks.length; i++) {
17329 var track = tracks[i];
17331 track.removeEventListener('cuechange', updateDisplay);
17332 if (track.mode === 'showing') {
17333 track.addEventListener('cuechange', updateDisplay);
17338 textTracksChanges();
17339 tracks.addEventListener('change', textTracksChanges);
17341 this.on('dispose', function () {
17342 tracks.removeEventListener('change', textTracksChanges);
17347 * Get the `Tech`s {@link VideoTrackList}.
17349 * @return {VideoTrackList}
17350 * The video track list that the Tech is currently using.
17354 Tech.prototype.videoTracks = function videoTracks() {
17355 this.videoTracks_ = this.videoTracks_ || new _videoTrackList2['default']();
17356 return this.videoTracks_;
17360 * Get the `Tech`s {@link AudioTrackList}.
17362 * @return {AudioTrackList}
17363 * The audio track list that the Tech is currently using.
17367 Tech.prototype.audioTracks = function audioTracks() {
17368 this.audioTracks_ = this.audioTracks_ || new _audioTrackList2['default']();
17369 return this.audioTracks_;
17373 * Get the `Tech`s {@link TextTrackList}.
17375 * @return {TextTrackList}
17376 * The text track list that the Tech is currently using.
17380 Tech.prototype.textTracks = function textTracks() {
17381 this.textTracks_ = this.textTracks_ || new _textTrackList2['default']();
17382 return this.textTracks_;
17386 * Get the `Tech`s remote {@link TextTrackList}, which is created from elements
17387 * that were added to the DOM.
17389 * @return {TextTrackList}
17390 * The remote text track list that the Tech is currently using.
17394 Tech.prototype.remoteTextTracks = function remoteTextTracks() {
17395 this.remoteTextTracks_ = this.remoteTextTracks_ || new _textTrackList2['default']();
17396 return this.remoteTextTracks_;
17400 * Get The `Tech`s {HTMLTrackElementList}, which are the elements in the DOM that are
17401 * being used as TextTracks.
17403 * @return {HTMLTrackElementList}
17404 * The current HTML track elements that exist for the tech.
17408 Tech.prototype.remoteTextTrackEls = function remoteTextTrackEls() {
17409 this.remoteTextTrackEls_ = this.remoteTextTrackEls_ || new _htmlTrackElementList2['default']();
17410 return this.remoteTextTrackEls_;
17414 * Create and returns a remote {@link TextTrack} object.
17416 * @param {string} kind
17417 * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata)
17419 * @param {string} [label]
17420 * Label to identify the text track
17422 * @param {string} [language]
17423 * Two letter language abbreviation
17425 * @return {TextTrack}
17426 * The TextTrack that gets created.
17430 Tech.prototype.addTextTrack = function addTextTrack(kind, label, language) {
17432 throw new Error('TextTrack kind is required but was not provided');
17435 return createTrackHelper(this, kind, label, language);
17439 * Create an emulated TextTrack for use by addRemoteTextTrack
17441 * This is intended to be overridden by classes that inherit from
17442 * Tech in order to create native or custom TextTracks.
17444 * @param {Object} options
17445 * The object should contain the options to initialize the TextTrack with.
17447 * @param {string} [options.kind]
17448 * `TextTrack` kind (subtitles, captions, descriptions, chapters, or metadata).
17450 * @param {string} [options.label].
17451 * Label to identify the text track
17453 * @param {string} [options.language]
17454 * Two letter language abbreviation.
17456 * @return {HTMLTrackElement}
17457 * The track element that gets created.
17461 Tech.prototype.createRemoteTextTrack = function createRemoteTextTrack(options) {
17462 var track = (0, _mergeOptions2['default'])(options, {
17466 return new _htmlTrackElement2['default'](track);
17470 * Creates a remote text track object and returns an html track element.
17472 * > Note: This can be an emulated {@link HTMLTrackElement} or a native one.
17474 * @param {Object} options
17475 * See {@link Tech#createRemoteTextTrack} for more detailed properties.
17477 * @param {boolean} [manualCleanup=true]
17478 * - When false: the TextTrack will be automatically removed from the video
17479 * element whenever the source changes
17480 * - When True: The TextTrack will have to be cleaned up manually
17482 * @return {HTMLTrackElement}
17483 * An Html Track Element.
17485 * @deprecated The default functionality for this function will be equivalent
17486 * to "manualCleanup=false" in the future. The manualCleanup parameter will
17491 Tech.prototype.addRemoteTextTrack = function addRemoteTextTrack() {
17492 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
17493 var manualCleanup = arguments[1];
17495 var htmlTrackElement = this.createRemoteTextTrack(options);
17497 if (manualCleanup !== true && manualCleanup !== false) {
17498 // deprecation warning
17499 _log2['default'].warn('Calling addRemoteTextTrack without explicitly setting the "manualCleanup" parameter to `true` is deprecated and default to `false` in future version of video.js');
17500 manualCleanup = true;
17503 // store HTMLTrackElement and TextTrack to remote list
17504 this.remoteTextTrackEls().addTrackElement_(htmlTrackElement);
17505 this.remoteTextTracks().addTrack_(htmlTrackElement.track);
17507 if (manualCleanup !== true) {
17508 // create the TextTrackList if it doesn't exist
17509 this.autoRemoteTextTracks_.addTrack_(htmlTrackElement.track);
17512 return htmlTrackElement;
17516 * Remove a remote text track from the remote `TextTrackList`.
17518 * @param {TextTrack} track
17519 * `TextTrack` to remove from the `TextTrackList`
17523 Tech.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) {
17524 var trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track);
17526 // remove HTMLTrackElement and TextTrack from remote list
17527 this.remoteTextTrackEls().removeTrackElement_(trackElement);
17528 this.remoteTextTracks().removeTrack_(track);
17529 this.autoRemoteTextTracks_.removeTrack_(track);
17533 * A method to set a poster from a `Tech`.
17539 Tech.prototype.setPoster = function setPoster() {};
17542 * Check if the tech can support the given mime-type.
17544 * The base tech does not support any type, but source handlers might
17547 * @param {string} type
17548 * The mimetype to check for support
17551 * 'probably', 'maybe', or empty string
17553 * @see [Spec]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType}
17559 Tech.prototype.canPlayType = function canPlayType() {
17564 * Return whether the argument is a Tech or not.
17565 * Can be passed either a Class like `Html5` or a instance like `player.tech_`
17567 * @param {Object} component
17568 * The item to check
17570 * @return {boolean}
17571 * Whether it is a tech or not
17572 * - True if it is a tech
17573 * - False if it is not
17577 Tech.isTech = function isTech(component) {
17578 return component.prototype instanceof Tech || component instanceof Tech || component === Tech;
17582 * Registers a `Tech` into a shared list for videojs.
17584 * @param {string} name
17585 * Name of the `Tech` to register.
17587 * @param {Object} tech
17588 * The `Tech` class to register.
17592 Tech.registerTech = function registerTech(name, tech) {
17593 if (!Tech.techs_) {
17597 if (!Tech.isTech(tech)) {
17598 throw new Error('Tech ' + name + ' must be a Tech');
17601 Tech.techs_[name] = tech;
17606 * Get a `Tech` from the shared list by name.
17608 * @param {string} name
17609 * Name of the component to get
17611 * @return {Tech|undefined}
17612 * The `Tech` or undefined if there was no tech with the name requested.
17616 Tech.getTech = function getTech(name) {
17617 if (Tech.techs_ && Tech.techs_[name]) {
17618 return Tech.techs_[name];
17621 if (_window2['default'] && _window2['default'].videojs && _window2['default'].videojs[name]) {
17622 _log2['default'].warn('The ' + name + ' tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)');
17623 return _window2['default'].videojs[name];
17628 }(_component2['default']);
17631 * List of associated text tracks.
17633 * @type {TextTrackList}
17638 Tech.prototype.textTracks_; // eslint-disable-line
17641 * List of associated audio tracks.
17643 * @type {AudioTrackList}
17646 Tech.prototype.audioTracks_; // eslint-disable-line
17649 * List of associated video tracks.
17651 * @type {VideoTrackList}
17654 Tech.prototype.videoTracks_; // eslint-disable-line
17657 * Boolean indicating whether the `Tech` supports volume control.
17662 Tech.prototype.featuresVolumeControl = true;
17665 * Boolean indicating whether the `Tech` support fullscreen resize control.
17666 * Resizing plugins using request fullscreen reloads the plugin
17671 Tech.prototype.featuresFullscreenResize = false;
17674 * Boolean indicating whether the `Tech` supports changing the speed at which the video
17676 * - Set player to play 2x (twice) as fast
17677 * - Set player to play 0.5x (half) as fast
17682 Tech.prototype.featuresPlaybackRate = false;
17685 * Boolean indicating whether the `Tech` supports the `progress` event. This is currently
17686 * not triggered by video-js-swf. This will be used to determine if
17687 * {@link Tech#manualProgressOn} should be called.
17692 Tech.prototype.featuresProgressEvents = false;
17695 * Boolean indicating whether the `Tech` supports the `timeupdate` event. This is currently
17696 * not triggered by video-js-swf. This will be used to determine if
17697 * {@link Tech#manualTimeUpdates} should be called.
17702 Tech.prototype.featuresTimeupdateEvents = false;
17705 * Boolean indicating whether the `Tech` supports the native `TextTrack`s.
17706 * This will help us integrate with native `TextTrack`s if the browser supports them.
17711 Tech.prototype.featuresNativeTextTracks = false;
17714 * A functional mixin for techs that want to use the Source Handler pattern.
17715 * Source handlers are scripts for handling specific formats.
17716 * The source handler pattern is used for adaptive formats (HLS, DASH) that
17717 * manually load video data and feed it into a Source Buffer (Media Source Extensions)
17718 * Example: `Tech.withSourceHandlers.call(MyTech);`
17720 * @param {Tech} _Tech
17721 * The tech to add source handler functions to.
17723 * @mixes Tech~SourceHandlerAdditions
17725 Tech.withSourceHandlers = function (_Tech) {
17728 * Register a source handler
17730 * @param {Function} handler
17731 * The source handler class
17733 * @param {number} [index]
17734 * Register it at the following index
17736 _Tech.registerSourceHandler = function (handler, index) {
17737 var handlers = _Tech.sourceHandlers;
17740 handlers = _Tech.sourceHandlers = [];
17743 if (index === undefined) {
17744 // add to the end of the list
17745 index = handlers.length;
17748 handlers.splice(index, 0, handler);
17752 * Check if the tech can support the given type. Also checks the
17753 * Techs sourceHandlers.
17755 * @param {string} type
17756 * The mimetype to check.
17759 * 'probably', 'maybe', or '' (empty string)
17761 _Tech.canPlayType = function (type) {
17762 var handlers = _Tech.sourceHandlers || [];
17765 for (var i = 0; i < handlers.length; i++) {
17766 can = handlers[i].canPlayType(type);
17777 * Returns the first source handler that supports the source.
17779 * TODO: Answer question: should 'probably' be prioritized over 'maybe'
17781 * @param {Tech~SourceObject} source
17782 * The source object
17784 * @param {Object} options
17785 * The options passed to the tech
17787 * @return {SourceHandler|null}
17788 * The first source handler that supports the source or null if
17789 * no SourceHandler supports the source
17791 _Tech.selectSourceHandler = function (source, options) {
17792 var handlers = _Tech.sourceHandlers || [];
17795 for (var i = 0; i < handlers.length; i++) {
17796 can = handlers[i].canHandleSource(source, options);
17799 return handlers[i];
17807 * Check if the tech can support the given source.
17809 * @param {Tech~SourceObject} srcObj
17810 * The source object
17812 * @param {Object} options
17813 * The options passed to the tech
17816 * 'probably', 'maybe', or '' (empty string)
17818 _Tech.canPlaySource = function (srcObj, options) {
17819 var sh = _Tech.selectSourceHandler(srcObj, options);
17822 return sh.canHandleSource(srcObj, options);
17829 * When using a source handler, prefer its implementation of
17830 * any function normally provided by the tech.
17832 var deferrable = ['seekable', 'duration'];
17835 * A wrapper around {@link Tech#seekable} that will call a `SourceHandler`s seekable
17836 * function if it exists, with a fallback to the Techs seekable function.
17838 * @method _Tech.seekable
17842 * A wrapper around {@link Tech#duration} that will call a `SourceHandler`s duration
17843 * function if it exists, otherwise it will fallback to the techs duration function.
17845 * @method _Tech.duration
17848 deferrable.forEach(function (fnName) {
17849 var originalFn = this[fnName];
17851 if (typeof originalFn !== 'function') {
17855 this[fnName] = function () {
17856 if (this.sourceHandler_ && this.sourceHandler_[fnName]) {
17857 return this.sourceHandler_[fnName].apply(this.sourceHandler_, arguments);
17859 return originalFn.apply(this, arguments);
17861 }, _Tech.prototype);
17864 * Create a function for setting the source using a source object
17865 * and source handlers.
17866 * Should never be called unless a source handler was found.
17868 * @param {Tech~SourceObject} source
17869 * A source object with src and type keys
17872 * Returns itself; this method is chainable
17874 _Tech.prototype.setSource = function (source) {
17875 var sh = _Tech.selectSourceHandler(source, this.options_);
17878 // Fall back to a native source handler when unsupported sources are
17879 // deliberately set
17880 if (_Tech.nativeSourceHandler) {
17881 sh = _Tech.nativeSourceHandler;
17883 _log2['default'].error('No source handler found for the current source.');
17887 // Dispose any existing source handler
17888 this.disposeSourceHandler();
17889 this.off('dispose', this.disposeSourceHandler);
17891 if (sh !== _Tech.nativeSourceHandler) {
17892 this.currentSource_ = source;
17894 // Catch if someone replaced the src without calling setSource.
17895 // If they do, set currentSource_ to null and dispose our source handler.
17896 this.off(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_);
17897 this.off(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
17898 this.one(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_);
17901 this.sourceHandler_ = sh.handleSource(source, this, this.options_);
17902 this.on('dispose', this.disposeSourceHandler);
17908 * Called once for the first loadstart of a video.
17910 * @listens Tech#loadstart
17912 _Tech.prototype.firstLoadStartListener_ = function () {
17913 this.one(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
17916 // On successive loadstarts when setSource has not been called again
17918 * Called after the first loadstart for a video occurs.
17920 * @listens Tech#loadstart
17922 _Tech.prototype.successiveLoadStartListener_ = function () {
17923 this.disposeSourceHandler();
17924 this.one(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
17928 * Clean up any existing SourceHandlers and listeners when the Tech is disposed.
17930 * @listens Tech#dispose
17932 _Tech.prototype.disposeSourceHandler = function () {
17933 // if we have a source and get another one
17934 // then we are loading something new
17935 // than clear all of our current tracks
17936 if (this.currentSource_) {
17937 this.clearTracks(['audio', 'video']);
17938 this.currentSource_ = null;
17941 // always clean up auto-text tracks
17942 this.cleanupAutoTextTracks();
17944 if (this.sourceHandler_) {
17945 this.off(this.el_, 'loadstart', _Tech.prototype.firstLoadStartListener_);
17946 this.off(this.el_, 'loadstart', _Tech.prototype.successiveLoadStartListener_);
17948 if (this.sourceHandler_.dispose) {
17949 this.sourceHandler_.dispose();
17952 this.sourceHandler_ = null;
17957 _component2['default'].registerComponent('Tech', Tech);
17958 // Old name for Tech
17960 _component2['default'].registerComponent('MediaTechController', Tech);
17961 Tech.registerTech('Tech', Tech);
17962 exports['default'] = Tech;
17964 },{"46":46,"5":5,"63":63,"65":65,"66":66,"70":70,"72":72,"76":76,"79":79,"83":83,"86":86,"87":87,"90":90,"94":94,"95":95}],63:[function(_dereq_,module,exports){
17967 exports.__esModule = true;
17969 var _trackList = _dereq_(74);
17971 var _trackList2 = _interopRequireDefault(_trackList);
17973 var _browser = _dereq_(78);
17975 var browser = _interopRequireWildcard(_browser);
17977 var _document = _dereq_(94);
17979 var _document2 = _interopRequireDefault(_document);
17981 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
17983 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
17985 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
17987 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
17989 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
17990 * @file audio-track-list.js
17995 * Anywhere we call this function we diverge from the spec
17996 * as we only support one enabled audiotrack at a time
17998 * @param {AudioTrackList} list
18001 * @param {AudioTrack} track
18002 * The track to skip
18006 var disableOthers = function disableOthers(list, track) {
18007 for (var i = 0; i < list.length; i++) {
18008 if (track.id === list[i].id) {
18011 // another audio track is enabled, disable it
18012 list[i].enabled = false;
18017 * The current list of {@link AudioTrack} for a media file.
18019 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist}
18020 * @extends TrackList
18023 var AudioTrackList = function (_TrackList) {
18024 _inherits(AudioTrackList, _TrackList);
18027 * Create an instance of this class.
18029 * @param {AudioTrack[]} [tracks=[]]
18030 * A list of `AudioTrack` to instantiate the list with.
18032 function AudioTrackList() {
18035 var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
18037 _classCallCheck(this, AudioTrackList);
18041 // make sure only 1 track is enabled
18042 // sorted from last index to first index
18043 for (var i = tracks.length - 1; i >= 0; i--) {
18044 if (tracks[i].enabled) {
18045 disableOthers(tracks, tracks[i]);
18050 // IE8 forces us to implement inheritance ourselves
18051 // as it does not support Object.defineProperty properly
18052 if (browser.IS_IE8) {
18053 list = _document2['default'].createElement('custom');
18054 for (var prop in _trackList2['default'].prototype) {
18055 if (prop !== 'constructor') {
18056 list[prop] = _trackList2['default'].prototype[prop];
18059 for (var _prop in AudioTrackList.prototype) {
18060 if (_prop !== 'constructor') {
18061 list[_prop] = AudioTrackList.prototype[_prop];
18066 list = (_this = _possibleConstructorReturn(this, _TrackList.call(this, tracks, list)), _this);
18067 list.changing_ = false;
18069 return _ret = list, _possibleConstructorReturn(_this, _ret);
18073 * Add an {@link AudioTrack} to the `AudioTrackList`.
18075 * @param {AudioTrack} track
18076 * The AudioTrack to add to the list
18078 * @fires Track#addtrack
18083 AudioTrackList.prototype.addTrack_ = function addTrack_(track) {
18086 if (track.enabled) {
18087 disableOthers(this, track);
18090 _TrackList.prototype.addTrack_.call(this, track);
18091 // native tracks don't have this
18092 if (!track.addEventListener) {
18097 * @listens AudioTrack#enabledchange
18098 * @fires TrackList#change
18100 track.addEventListener('enabledchange', function () {
18101 // when we are disabling other tracks (since we don't support
18102 // more than one track at a time) we will set changing_
18103 // to true so that we don't trigger additional change events
18104 if (_this2.changing_) {
18107 _this2.changing_ = true;
18108 disableOthers(_this2, track);
18109 _this2.changing_ = false;
18110 _this2.trigger('change');
18115 * Add an {@link AudioTrack} to the `AudioTrackList`.
18117 * @param {AudioTrack} track
18118 * The AudioTrack to add to the list
18120 * @fires Track#addtrack
18124 AudioTrackList.prototype.addTrack = function addTrack(track) {
18125 this.addTrack_(track);
18129 * Remove an {@link AudioTrack} from the `AudioTrackList`.
18131 * @param {AudioTrack} track
18132 * The AudioTrack to remove from the list
18134 * @fires Track#removetrack
18138 AudioTrackList.prototype.removeTrack = function removeTrack(track) {
18139 _TrackList.prototype.removeTrack_.call(this, track);
18142 return AudioTrackList;
18143 }(_trackList2['default']);
18145 exports['default'] = AudioTrackList;
18147 },{"74":74,"78":78,"94":94}],64:[function(_dereq_,module,exports){
18150 exports.__esModule = true;
18152 var _trackEnums = _dereq_(73);
18154 var _track = _dereq_(75);
18156 var _track2 = _interopRequireDefault(_track);
18158 var _mergeOptions = _dereq_(87);
18160 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
18162 var _browser = _dereq_(78);
18164 var browser = _interopRequireWildcard(_browser);
18166 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
18168 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18170 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
18172 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
18174 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
18177 * A representation of a single `AudioTrack`. If it is part of an {@link AudioTrackList}
18178 * only one `AudioTrack` in the list will be enabled at a time.
18180 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotrack}
18183 var AudioTrack = function (_Track) {
18184 _inherits(AudioTrack, _Track);
18187 * Create an instance of this class.
18189 * @param {Object} [options={}]
18190 * Object of option names and values
18192 * @param {AudioTrack~Kind} [options.kind='']
18193 * A valid audio track kind
18195 * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
18196 * A unique id for this AudioTrack.
18198 * @param {string} [options.label='']
18199 * The menu label for this track.
18201 * @param {string} [options.language='']
18202 * A valid two character language code.
18204 * @param {boolean} [options.enabled]
18205 * If this track is the one that is currently playing. If this track is part of
18206 * an {@link AudioTrackList}, only one {@link AudioTrack} will be enabled.
18208 function AudioTrack() {
18211 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
18213 _classCallCheck(this, AudioTrack);
18215 var settings = (0, _mergeOptions2['default'])(options, {
18216 kind: _trackEnums.AudioTrackKind[options.kind] || ''
18218 // on IE8 this will be a document element
18219 // for every other browser this will be a normal object
18220 var track = (_this = _possibleConstructorReturn(this, _Track.call(this, settings)), _this);
18221 var enabled = false;
18223 if (browser.IS_IE8) {
18224 for (var prop in AudioTrack.prototype) {
18225 if (prop !== 'constructor') {
18226 track[prop] = AudioTrack.prototype[prop];
18231 * @member {boolean} enabled
18232 * If this `AudioTrack` is enabled or not. When setting this will
18233 * fire {@link AudioTrack#enabledchange} if the state of enabled is changed.
18235 * @fires VideoTrack#selectedchange
18237 Object.defineProperty(track, 'enabled', {
18238 get: function get() {
18241 set: function set(newEnabled) {
18242 // an invalid or unchanged value
18243 if (typeof newEnabled !== 'boolean' || newEnabled === enabled) {
18246 enabled = newEnabled;
18249 * An event that fires when enabled changes on this track. This allows
18250 * the AudioTrackList that holds this track to act accordingly.
18252 * > Note: This is not part of the spec! Native tracks will do
18253 * this internally without an event.
18255 * @event AudioTrack#enabledchange
18256 * @type {EventTarget~Event}
18258 this.trigger('enabledchange');
18262 // if the user sets this track to selected then
18263 // set selected to that true value otherwise
18264 // we keep it false
18265 if (settings.enabled) {
18266 track.enabled = settings.enabled;
18268 track.loaded_ = true;
18270 return _ret = track, _possibleConstructorReturn(_this, _ret);
18274 }(_track2['default']);
18276 exports['default'] = AudioTrack;
18278 },{"73":73,"75":75,"78":78,"87":87}],65:[function(_dereq_,module,exports){
18281 exports.__esModule = true;
18283 var _browser = _dereq_(78);
18285 var browser = _interopRequireWildcard(_browser);
18287 var _document = _dereq_(94);
18289 var _document2 = _interopRequireDefault(_document);
18291 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18293 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
18295 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
18296 * @file html-track-element-list.js
18300 * The current list of {@link HtmlTrackElement}s.
18302 var HtmlTrackElementList = function () {
18305 * Create an instance of this class.
18307 * @param {HtmlTrackElement[]} [tracks=[]]
18308 * A list of `HtmlTrackElement` to instantiate the list with.
18310 function HtmlTrackElementList() {
18311 var trackElements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
18313 _classCallCheck(this, HtmlTrackElementList);
18315 var list = this; // eslint-disable-line
18317 if (browser.IS_IE8) {
18318 list = _document2['default'].createElement('custom');
18320 for (var prop in HtmlTrackElementList.prototype) {
18321 if (prop !== 'constructor') {
18322 list[prop] = HtmlTrackElementList.prototype[prop];
18327 list.trackElements_ = [];
18330 * @member {number} length
18331 * The current number of `Track`s in the this Trackist.
18333 Object.defineProperty(list, 'length', {
18334 get: function get() {
18335 return this.trackElements_.length;
18339 for (var i = 0, length = trackElements.length; i < length; i++) {
18340 list.addTrackElement_(trackElements[i]);
18343 if (browser.IS_IE8) {
18349 * Add an {@link HtmlTrackElement} to the `HtmlTrackElementList`
18351 * @param {HtmlTrackElement} trackElement
18352 * The track element to add to the list.
18358 HtmlTrackElementList.prototype.addTrackElement_ = function addTrackElement_(trackElement) {
18359 var index = this.trackElements_.length;
18361 if (!('' + index in this)) {
18362 Object.defineProperty(this, index, {
18363 get: function get() {
18364 return this.trackElements_[index];
18369 // Do not add duplicate elements
18370 if (this.trackElements_.indexOf(trackElement) === -1) {
18371 this.trackElements_.push(trackElement);
18376 * Get an {@link HtmlTrackElement} from the `HtmlTrackElementList` given an
18377 * {@link TextTrack}.
18379 * @param {TextTrack} track
18380 * The track associated with a track element.
18382 * @return {HtmlTrackElement|undefined}
18383 * The track element that was found or undefined.
18389 HtmlTrackElementList.prototype.getTrackElementByTrack_ = function getTrackElementByTrack_(track) {
18390 var trackElement_ = void 0;
18392 for (var i = 0, length = this.trackElements_.length; i < length; i++) {
18393 if (track === this.trackElements_[i].track) {
18394 trackElement_ = this.trackElements_[i];
18400 return trackElement_;
18404 * Remove a {@link HtmlTrackElement} from the `HtmlTrackElementList`
18406 * @param {HtmlTrackElement} trackElement
18407 * The track element to remove from the list.
18413 HtmlTrackElementList.prototype.removeTrackElement_ = function removeTrackElement_(trackElement) {
18414 for (var i = 0, length = this.trackElements_.length; i < length; i++) {
18415 if (trackElement === this.trackElements_[i]) {
18416 this.trackElements_.splice(i, 1);
18423 return HtmlTrackElementList;
18426 exports['default'] = HtmlTrackElementList;
18428 },{"78":78,"94":94}],66:[function(_dereq_,module,exports){
18431 exports.__esModule = true;
18433 var _browser = _dereq_(78);
18435 var browser = _interopRequireWildcard(_browser);
18437 var _document = _dereq_(94);
18439 var _document2 = _interopRequireDefault(_document);
18441 var _eventTarget = _dereq_(42);
18443 var _eventTarget2 = _interopRequireDefault(_eventTarget);
18445 var _textTrack = _dereq_(72);
18447 var _textTrack2 = _interopRequireDefault(_textTrack);
18449 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18451 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
18453 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
18455 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
18457 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
18458 * @file html-track-element.js
18462 * @typedef {HTMLTrackElement~ReadyState}
18471 * A single track represented in the DOM.
18473 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement}
18474 * @extends EventTarget
18477 var HTMLTrackElement = function (_EventTarget) {
18478 _inherits(HTMLTrackElement, _EventTarget);
18481 * Create an instance of this class.
18483 * @param {Object} options={}
18484 * Object of option names and values
18486 * @param {Tech} options.tech
18487 * A reference to the tech that owns this HTMLTrackElement.
18489 * @param {TextTrack~Kind} [options.kind='subtitles']
18490 * A valid text track kind.
18492 * @param {TextTrack~Mode} [options.mode='disabled']
18493 * A valid text track mode.
18495 * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
18496 * A unique id for this TextTrack.
18498 * @param {string} [options.label='']
18499 * The menu label for this track.
18501 * @param {string} [options.language='']
18502 * A valid two character language code.
18504 * @param {string} [options.srclang='']
18505 * A valid two character language code. An alternative, but deprioritized
18506 * version of `options.language`
18508 * @param {string} [options.src]
18509 * A url to TextTrack cues.
18511 * @param {boolean} [options.default]
18512 * If this track should default to on or off.
18514 function HTMLTrackElement() {
18515 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
18517 _classCallCheck(this, HTMLTrackElement);
18519 var _this = _possibleConstructorReturn(this, _EventTarget.call(this));
18521 var readyState = void 0;
18522 var trackElement = _this; // eslint-disable-line
18524 if (browser.IS_IE8) {
18525 trackElement = _document2['default'].createElement('custom');
18527 for (var prop in HTMLTrackElement.prototype) {
18528 if (prop !== 'constructor') {
18529 trackElement[prop] = HTMLTrackElement.prototype[prop];
18534 var track = new _textTrack2['default'](options);
18536 trackElement.kind = track.kind;
18537 trackElement.src = track.src;
18538 trackElement.srclang = track.language;
18539 trackElement.label = track.label;
18540 trackElement['default'] = track['default'];
18543 * @member {HTMLTrackElement~ReadyState} readyState
18544 * The current ready state of the track element.
18546 Object.defineProperty(trackElement, 'readyState', {
18547 get: function get() {
18553 * @member {TextTrack} track
18554 * The underlying TextTrack object.
18556 Object.defineProperty(trackElement, 'track', {
18557 get: function get() {
18565 * @listens TextTrack#loadeddata
18566 * @fires HTMLTrackElement#load
18568 track.addEventListener('loadeddata', function () {
18569 readyState = LOADED;
18571 trackElement.trigger({
18573 target: trackElement
18577 if (browser.IS_IE8) {
18580 return _ret = trackElement, _possibleConstructorReturn(_this, _ret);
18585 return HTMLTrackElement;
18586 }(_eventTarget2['default']);
18588 HTMLTrackElement.prototype.allowedEvents_ = {
18592 HTMLTrackElement.NONE = NONE;
18593 HTMLTrackElement.LOADING = LOADING;
18594 HTMLTrackElement.LOADED = LOADED;
18595 HTMLTrackElement.ERROR = ERROR;
18597 exports['default'] = HTMLTrackElement;
18599 },{"42":42,"72":72,"78":78,"94":94}],67:[function(_dereq_,module,exports){
18602 exports.__esModule = true;
18604 var _browser = _dereq_(78);
18606 var browser = _interopRequireWildcard(_browser);
18608 var _document = _dereq_(94);
18610 var _document2 = _interopRequireDefault(_document);
18612 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18614 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
18616 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /**
18617 * @file text-track-cue-list.js
18622 * @typedef {Object} TextTrackCue
18624 * @property {string} id
18625 * The unique id for this text track cue
18627 * @property {number} startTime
18628 * The start time for this text track cue
18630 * @property {number} endTime
18631 * The end time for this text track cue
18633 * @property {boolean} pauseOnExit
18634 * Pause when the end time is reached if true.
18636 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcue}
18640 * A List of TextTrackCues.
18642 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist}
18644 var TextTrackCueList = function () {
18647 * Create an instance of this class..
18649 * @param {Array} cues
18650 * A list of cues to be initialized with
18652 function TextTrackCueList(cues) {
18653 _classCallCheck(this, TextTrackCueList);
18655 var list = this; // eslint-disable-line
18657 if (browser.IS_IE8) {
18658 list = _document2['default'].createElement('custom');
18660 for (var prop in TextTrackCueList.prototype) {
18661 if (prop !== 'constructor') {
18662 list[prop] = TextTrackCueList.prototype[prop];
18667 TextTrackCueList.prototype.setCues_.call(list, cues);
18670 * @member {number} length
18671 * The current number of `TextTrackCue`s in the TextTrackCueList.
18673 Object.defineProperty(list, 'length', {
18674 get: function get() {
18675 return this.length_;
18679 if (browser.IS_IE8) {
18685 * A setter for cues in this list. Creates getters
18686 * an an index for the cues.
18688 * @param {Array} cues
18689 * An array of cues to set
18695 TextTrackCueList.prototype.setCues_ = function setCues_(cues) {
18696 var oldLength = this.length || 0;
18698 var l = cues.length;
18701 this.length_ = cues.length;
18703 var defineProp = function defineProp(index) {
18704 if (!('' + index in this)) {
18705 Object.defineProperty(this, '' + index, {
18706 get: function get() {
18707 return this.cues_[index];
18713 if (oldLength < l) {
18716 for (; i < l; i++) {
18717 defineProp.call(this, i);
18723 * Get a `TextTrackCue` that is currently in the `TextTrackCueList` by id.
18725 * @param {string} id
18726 * The id of the cue that should be searched for.
18728 * @return {TextTrackCue|null}
18729 * A single cue or null if none was found.
18733 TextTrackCueList.prototype.getCueById = function getCueById(id) {
18736 for (var i = 0, l = this.length; i < l; i++) {
18739 if (cue.id === id) {
18748 return TextTrackCueList;
18751 exports['default'] = TextTrackCueList;
18753 },{"78":78,"94":94}],68:[function(_dereq_,module,exports){
18756 exports.__esModule = true;
18758 var _component = _dereq_(5);
18760 var _component2 = _interopRequireDefault(_component);
18762 var _fn = _dereq_(83);
18764 var Fn = _interopRequireWildcard(_fn);
18766 var _window = _dereq_(95);
18768 var _window2 = _interopRequireDefault(_window);
18770 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
18772 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
18774 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
18776 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
18778 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
18779 * @file text-track-display.js
18783 var darkGray = '#222';
18784 var lightGray = '#ccc';
18786 monospace: 'monospace',
18787 sansSerif: 'sans-serif',
18789 monospaceSansSerif: '"Andale Mono", "Lucida Console", monospace',
18790 monospaceSerif: '"Courier New", monospace',
18791 proportionalSansSerif: 'sans-serif',
18792 proportionalSerif: 'serif',
18793 casual: '"Comic Sans MS", Impact, fantasy',
18794 script: '"Monotype Corsiva", cursive',
18795 smallcaps: '"Andale Mono", "Lucida Console", monospace, sans-serif'
18799 * Construct an rgba color from a given hex color code.
18801 * @param {number} color
18802 * Hex number for color, like #f0e.
18804 * @param {number} opacity
18805 * Value for opacity, 0.0 - 1.0.
18808 * The rgba color that was created, like 'rgba(255, 0, 0, 0.3)'.
18812 function constructColor(color, opacity) {
18814 // color looks like "#f0e"
18815 parseInt(color[1] + color[1], 16) + ',' + parseInt(color[2] + color[2], 16) + ',' + parseInt(color[3] + color[3], 16) + ',' + opacity + ')';
18819 * Try to update the style of a DOM element. Some style changes will throw an error,
18820 * particularly in IE8. Those should be noops.
18822 * @param {Element} el
18823 * The DOM element to be styled.
18825 * @param {string} style
18826 * The CSS property on the element that should be styled.
18828 * @param {string} rule
18829 * The style rule that should be applied to the property.
18831 function tryUpdateStyle(el, style, rule) {
18833 el.style[style] = rule;
18836 // Satisfies linter.
18842 * The component for displaying text track cues.
18844 * @extends Component
18847 var TextTrackDisplay = function (_Component) {
18848 _inherits(TextTrackDisplay, _Component);
18851 * Creates an instance of this class.
18853 * @param {Player} player
18854 * The `Player` that this class should be attached to.
18856 * @param {Object} [options]
18857 * The key/value store of player options.
18859 * @param {Component~ReadyCallback} [ready]
18860 * The function to call when `TextTrackDisplay` is ready.
18862 function TextTrackDisplay(player, options, ready) {
18863 _classCallCheck(this, TextTrackDisplay);
18865 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options, ready));
18867 player.on('loadstart', Fn.bind(_this, _this.toggleDisplay));
18868 player.on('texttrackchange', Fn.bind(_this, _this.updateDisplay));
18870 // This used to be called during player init, but was causing an error
18871 // if a track should show by default and the display hadn't loaded yet.
18872 // Should probably be moved to an external track loader when we support
18873 // tracks that don't need a display.
18874 player.ready(Fn.bind(_this, function () {
18875 if (player.tech_ && player.tech_.featuresNativeTextTracks) {
18880 player.on('fullscreenchange', Fn.bind(this, this.updateDisplay));
18882 var tracks = this.options_.playerOptions.tracks || [];
18884 for (var i = 0; i < tracks.length; i++) {
18885 this.player_.addRemoteTextTrack(tracks[i], true);
18888 var modes = { captions: 1, subtitles: 1 };
18889 var trackList = this.player_.textTracks();
18890 var firstDesc = void 0;
18891 var firstCaptions = void 0;
18894 for (var _i = 0; _i < trackList.length; _i++) {
18895 var track = trackList[_i];
18897 if (track['default']) {
18898 if (track.kind === 'descriptions' && !firstDesc) {
18900 } else if (track.kind in modes && !firstCaptions) {
18901 firstCaptions = track;
18906 // We want to show the first default track but captions and subtitles
18907 // take precedence over descriptions.
18908 // So, display the first default captions or subtitles track
18909 // and otherwise the first default descriptions track.
18910 if (firstCaptions) {
18911 firstCaptions.mode = 'showing';
18912 } else if (firstDesc) {
18913 firstDesc.mode = 'showing';
18921 * Turn display of {@link TextTrack}'s from the current state into the other state.
18922 * There are only two states:
18926 * @listens Player#loadstart
18930 TextTrackDisplay.prototype.toggleDisplay = function toggleDisplay() {
18931 if (this.player_.tech_ && this.player_.tech_.featuresNativeTextTracks) {
18939 * Create the {@link Component}'s DOM element.
18941 * @return {Element}
18942 * The element that was created.
18946 TextTrackDisplay.prototype.createEl = function createEl() {
18947 return _Component.prototype.createEl.call(this, 'div', {
18948 className: 'vjs-text-track-display'
18950 'aria-live': 'off',
18951 'aria-atomic': 'true'
18956 * Clear all displayed {@link TextTrack}s.
18960 TextTrackDisplay.prototype.clearDisplay = function clearDisplay() {
18961 if (typeof _window2['default'].WebVTT === 'function') {
18962 _window2['default'].WebVTT.processCues(_window2['default'], [], this.el_);
18967 * Update the displayed TextTrack when a either a {@link Player#texttrackchange} or
18968 * a {@link Player#fullscreenchange} is fired.
18970 * @listens Player#texttrackchange
18971 * @listens Player#fullscreenchange
18975 TextTrackDisplay.prototype.updateDisplay = function updateDisplay() {
18976 var tracks = this.player_.textTracks();
18978 this.clearDisplay();
18984 // Track display prioritization model: if multiple tracks are 'showing',
18985 // display the first 'subtitles' or 'captions' track which is 'showing',
18986 // otherwise display the first 'descriptions' track which is 'showing'
18988 var descriptionsTrack = null;
18989 var captionsSubtitlesTrack = null;
18991 var i = tracks.length;
18994 var track = tracks[i];
18996 if (track.mode === 'showing') {
18997 if (track.kind === 'descriptions') {
18998 descriptionsTrack = track;
19000 captionsSubtitlesTrack = track;
19005 if (captionsSubtitlesTrack) {
19006 if (this.getAttribute('aria-live') !== 'off') {
19007 this.setAttribute('aria-live', 'off');
19009 this.updateForTrack(captionsSubtitlesTrack);
19010 } else if (descriptionsTrack) {
19011 if (this.getAttribute('aria-live') !== 'assertive') {
19012 this.setAttribute('aria-live', 'assertive');
19014 this.updateForTrack(descriptionsTrack);
19019 * Add an {@link Texttrack} to to the {@link Tech}s {@link TextTrackList}.
19021 * @param {TextTrack} track
19022 * Text track object to be added to the list.
19026 TextTrackDisplay.prototype.updateForTrack = function updateForTrack(track) {
19027 if (typeof _window2['default'].WebVTT !== 'function' || !track.activeCues) {
19031 var overrides = this.player_.textTrackSettings.getValues();
19034 for (var _i2 = 0; _i2 < track.activeCues.length; _i2++) {
19035 cues.push(track.activeCues[_i2]);
19038 _window2['default'].WebVTT.processCues(_window2['default'], cues, this.el_);
19040 var i = cues.length;
19049 var cueDiv = cue.displayState;
19051 if (overrides.color) {
19052 cueDiv.firstChild.style.color = overrides.color;
19054 if (overrides.textOpacity) {
19055 tryUpdateStyle(cueDiv.firstChild, 'color', constructColor(overrides.color || '#fff', overrides.textOpacity));
19057 if (overrides.backgroundColor) {
19058 cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor;
19060 if (overrides.backgroundOpacity) {
19061 tryUpdateStyle(cueDiv.firstChild, 'backgroundColor', constructColor(overrides.backgroundColor || '#000', overrides.backgroundOpacity));
19063 if (overrides.windowColor) {
19064 if (overrides.windowOpacity) {
19065 tryUpdateStyle(cueDiv, 'backgroundColor', constructColor(overrides.windowColor, overrides.windowOpacity));
19067 cueDiv.style.backgroundColor = overrides.windowColor;
19070 if (overrides.edgeStyle) {
19071 if (overrides.edgeStyle === 'dropshadow') {
19072 cueDiv.firstChild.style.textShadow = '2px 2px 3px ' + darkGray + ', 2px 2px 4px ' + darkGray + ', 2px 2px 5px ' + darkGray;
19073 } else if (overrides.edgeStyle === 'raised') {
19074 cueDiv.firstChild.style.textShadow = '1px 1px ' + darkGray + ', 2px 2px ' + darkGray + ', 3px 3px ' + darkGray;
19075 } else if (overrides.edgeStyle === 'depressed') {
19076 cueDiv.firstChild.style.textShadow = '1px 1px ' + lightGray + ', 0 1px ' + lightGray + ', -1px -1px ' + darkGray + ', 0 -1px ' + darkGray;
19077 } else if (overrides.edgeStyle === 'uniform') {
19078 cueDiv.firstChild.style.textShadow = '0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray;
19081 if (overrides.fontPercent && overrides.fontPercent !== 1) {
19082 var fontSize = _window2['default'].parseFloat(cueDiv.style.fontSize);
19084 cueDiv.style.fontSize = fontSize * overrides.fontPercent + 'px';
19085 cueDiv.style.height = 'auto';
19086 cueDiv.style.top = 'auto';
19087 cueDiv.style.bottom = '2px';
19089 if (overrides.fontFamily && overrides.fontFamily !== 'default') {
19090 if (overrides.fontFamily === 'small-caps') {
19091 cueDiv.firstChild.style.fontVariant = 'small-caps';
19093 cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily];
19099 return TextTrackDisplay;
19100 }(_component2['default']);
19102 _component2['default'].registerComponent('TextTrackDisplay', TextTrackDisplay);
19103 exports['default'] = TextTrackDisplay;
19105 },{"5":5,"83":83,"95":95}],69:[function(_dereq_,module,exports){
19108 exports.__esModule = true;
19110 * @file text-track-list-converter.js Utilities for capturing text track state and
19111 * re-creating tracks based on a capture.
19113 * @module text-track-list-converter
19117 * Examine a single {@link TextTrack} and return a JSON-compatible javascript object that
19118 * represents the {@link TextTrack}'s state.
19120 * @param {TextTrack} track
19121 * The text track to query.
19124 * A serializable javascript representation of the TextTrack.
19127 var trackToJson_ = function trackToJson_(track) {
19128 var ret = ['kind', 'label', 'language', 'id', 'inBandMetadataTrackDispatchType', 'mode', 'src'].reduce(function (acc, prop, i) {
19131 acc[prop] = track[prop];
19136 cues: track.cues && Array.prototype.map.call(track.cues, function (cue) {
19138 startTime: cue.startTime,
19139 endTime: cue.endTime,
19150 * Examine a {@link Tech} and return a JSON-compatible javascript array that represents the
19151 * state of all {@link TextTrack}s currently configured. The return array is compatible with
19152 * {@link text-track-list-converter:jsonToTextTracks}.
19154 * @param {Tech} tech
19155 * The tech object to query
19158 * A serializable javascript representation of the {@link Tech}s
19159 * {@link TextTrackList}.
19161 var textTracksToJson = function textTracksToJson(tech) {
19163 var trackEls = tech.$$('track');
19165 var trackObjs = Array.prototype.map.call(trackEls, function (t) {
19168 var tracks = Array.prototype.map.call(trackEls, function (trackEl) {
19169 var json = trackToJson_(trackEl.track);
19172 json.src = trackEl.src;
19177 return tracks.concat(Array.prototype.filter.call(tech.textTracks(), function (track) {
19178 return trackObjs.indexOf(track) === -1;
19179 }).map(trackToJson_));
19183 * Create a set of remote {@link TextTrack}s on a {@link Tech} based on an array of javascript
19184 * object {@link TextTrack} representations.
19186 * @param {Array} json
19187 * An array of `TextTrack` representation objects, like those that would be
19188 * produced by `textTracksToJson`.
19190 * @param {Tech} tech
19191 * The `Tech` to create the `TextTrack`s on.
19193 var jsonToTextTracks = function jsonToTextTracks(json, tech) {
19194 json.forEach(function (track) {
19195 var addedTrack = tech.addRemoteTextTrack(track).track;
19197 if (!track.src && track.cues) {
19198 track.cues.forEach(function (cue) {
19199 return addedTrack.addCue(cue);
19204 return tech.textTracks();
19207 exports['default'] = { textTracksToJson: textTracksToJson, jsonToTextTracks: jsonToTextTracks, trackToJson_: trackToJson_ };
19209 },{}],70:[function(_dereq_,module,exports){
19212 exports.__esModule = true;
19214 var _trackList = _dereq_(74);
19216 var _trackList2 = _interopRequireDefault(_trackList);
19218 var _fn = _dereq_(83);
19220 var Fn = _interopRequireWildcard(_fn);
19222 var _browser = _dereq_(78);
19224 var browser = _interopRequireWildcard(_browser);
19226 var _document = _dereq_(94);
19228 var _document2 = _interopRequireDefault(_document);
19230 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
19232 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19234 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
19236 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
19238 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
19239 * @file text-track-list.js
19244 * The current list of {@link TextTrack} for a media file.
19246 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist}
19247 * @extends TrackList
19249 var TextTrackList = function (_TrackList) {
19250 _inherits(TextTrackList, _TrackList);
19253 * Create an instance of this class.
19255 * @param {TextTrack[]} [tracks=[]]
19256 * A list of `TextTrack` to instantiate the list with.
19258 function TextTrackList() {
19261 var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
19263 _classCallCheck(this, TextTrackList);
19267 // IE8 forces us to implement inheritance ourselves
19268 // as it does not support Object.defineProperty properly
19269 if (browser.IS_IE8) {
19270 list = _document2['default'].createElement('custom');
19271 for (var prop in _trackList2['default'].prototype) {
19272 if (prop !== 'constructor') {
19273 list[prop] = _trackList2['default'].prototype[prop];
19276 for (var _prop in TextTrackList.prototype) {
19277 if (_prop !== 'constructor') {
19278 list[_prop] = TextTrackList.prototype[_prop];
19283 list = (_this = _possibleConstructorReturn(this, _TrackList.call(this, tracks, list)), _this);
19284 return _ret = list, _possibleConstructorReturn(_this, _ret);
19288 * Add a {@link TextTrack} to the `TextTrackList`
19290 * @param {TextTrack} track
19291 * The text track to add to the list.
19293 * @fires TrackList#addtrack
19298 TextTrackList.prototype.addTrack_ = function addTrack_(track) {
19299 _TrackList.prototype.addTrack_.call(this, track);
19302 * @listens TextTrack#modechange
19303 * @fires TrackList#change
19305 track.addEventListener('modechange', Fn.bind(this, function () {
19306 this.trigger('change');
19310 return TextTrackList;
19311 }(_trackList2['default']);
19313 exports['default'] = TextTrackList;
19315 },{"74":74,"78":78,"83":83,"94":94}],71:[function(_dereq_,module,exports){
19318 exports.__esModule = true;
19320 var _window = _dereq_(95);
19322 var _window2 = _interopRequireDefault(_window);
19324 var _component = _dereq_(5);
19326 var _component2 = _interopRequireDefault(_component);
19328 var _dom = _dereq_(81);
19330 var _fn = _dereq_(83);
19332 var Fn = _interopRequireWildcard(_fn);
19334 var _obj = _dereq_(88);
19336 var Obj = _interopRequireWildcard(_obj);
19338 var _log = _dereq_(86);
19340 var _log2 = _interopRequireDefault(_log);
19342 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
19344 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19346 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
19348 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
19350 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
19351 * @file text-track-settings.js
19355 var LOCAL_STORAGE_KEY = 'vjs-text-track-settings';
19357 var COLOR_BLACK = ['#000', 'Black'];
19358 var COLOR_BLUE = ['#00F', 'Blue'];
19359 var COLOR_CYAN = ['#0FF', 'Cyan'];
19360 var COLOR_GREEN = ['#0F0', 'Green'];
19361 var COLOR_MAGENTA = ['#F0F', 'Magenta'];
19362 var COLOR_RED = ['#F00', 'Red'];
19363 var COLOR_WHITE = ['#FFF', 'White'];
19364 var COLOR_YELLOW = ['#FF0', 'Yellow'];
19366 var OPACITY_OPAQUE = ['1', 'Opaque'];
19367 var OPACITY_SEMI = ['0.5', 'Semi-Transparent'];
19368 var OPACITY_TRANS = ['0', 'Transparent'];
19370 // Configuration for the various <select> elements in the DOM of this component.
19372 // Possible keys include:
19375 // The default option index. Only needs to be provided if not zero.
19377 // A function which is used to parse the value from the selected option in
19378 // a customized way.
19380 // The selector used to find the associated <select> element.
19381 var selectConfigs = {
19383 selector: '.vjs-bg-color > select',
19384 id: 'captions-background-color-%s',
19386 options: [COLOR_BLACK, COLOR_WHITE, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN]
19389 backgroundOpacity: {
19390 selector: '.vjs-bg-opacity > select',
19391 id: 'captions-background-opacity-%s',
19392 label: 'Transparency',
19393 options: [OPACITY_OPAQUE, OPACITY_SEMI, OPACITY_TRANS]
19397 selector: '.vjs-fg-color > select',
19398 id: 'captions-foreground-color-%s',
19400 options: [COLOR_WHITE, COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_MAGENTA, COLOR_CYAN]
19404 selector: '.vjs-edge-style > select',
19406 label: 'Text Edge Style',
19407 options: [['none', 'None'], ['raised', 'Raised'], ['depressed', 'Depressed'], ['uniform', 'Uniform'], ['dropshadow', 'Dropshadow']]
19411 selector: '.vjs-font-family > select',
19412 id: 'captions-font-family-%s',
19413 label: 'Font Family',
19414 options: [['proportionalSansSerif', 'Proportional Sans-Serif'], ['monospaceSansSerif', 'Monospace Sans-Serif'], ['proportionalSerif', 'Proportional Serif'], ['monospaceSerif', 'Monospace Serif'], ['casual', 'Casual'], ['script', 'Script'], ['small-caps', 'Small Caps']]
19418 selector: '.vjs-font-percent > select',
19419 id: 'captions-font-size-%s',
19420 label: 'Font Size',
19421 options: [['0.50', '50%'], ['0.75', '75%'], ['1.00', '100%'], ['1.25', '125%'], ['1.50', '150%'], ['1.75', '175%'], ['2.00', '200%'], ['3.00', '300%'], ['4.00', '400%']],
19423 parser: function parser(v) {
19424 return v === '1.00' ? null : Number(v);
19429 selector: '.vjs-text-opacity > select',
19430 id: 'captions-foreground-opacity-%s',
19431 label: 'Transparency',
19432 options: [OPACITY_OPAQUE, OPACITY_SEMI]
19435 // Options for this object are defined below.
19437 selector: '.vjs-window-color > select',
19438 id: 'captions-window-color-%s',
19442 // Options for this object are defined below.
19444 selector: '.vjs-window-opacity > select',
19445 id: 'captions-window-opacity-%s',
19446 label: 'Transparency',
19447 options: [OPACITY_TRANS, OPACITY_SEMI, OPACITY_OPAQUE]
19451 selectConfigs.windowColor.options = selectConfigs.backgroundColor.options;
19454 * Get the actual value of an option.
19456 * @param {string} value
19459 * @param {Function} [parser]
19460 * Optional function to adjust the value.
19463 * - Will be `undefined` if no value exists
19464 * - Will be `undefined` if the given value is "none".
19465 * - Will be the actual value otherwise.
19469 function parseOptionValue(value, parser) {
19471 value = parser(value);
19474 if (value && value !== 'none') {
19480 * Gets the value of the selected <option> element within a <select> element.
19482 * @param {Element} el
19483 * the element to look in
19485 * @param {Function} [parser]
19486 * Optional function to adjust the value.
19489 * - Will be `undefined` if no value exists
19490 * - Will be `undefined` if the given value is "none".
19491 * - Will be the actual value otherwise.
19495 function getSelectedOptionValue(el, parser) {
19496 var value = el.options[el.options.selectedIndex].value;
19498 return parseOptionValue(value, parser);
19502 * Sets the selected <option> element within a <select> element based on a
19505 * @param {Element} el
19506 * The element to look in.
19508 * @param {string} value
19509 * the property to look on.
19511 * @param {Function} [parser]
19512 * Optional function to adjust the value before comparing.
19516 function setSelectedOption(el, value, parser) {
19521 for (var i = 0; i < el.options.length; i++) {
19522 if (parseOptionValue(el.options[i].value, parser) === value) {
19523 el.selectedIndex = i;
19530 * Manipulate Text Tracks settings.
19532 * @extends Component
19535 var TextTrackSettings = function (_Component) {
19536 _inherits(TextTrackSettings, _Component);
19539 * Creates an instance of this class.
19541 * @param {Player} player
19542 * The `Player` that this class should be attached to.
19544 * @param {Object} [options]
19545 * The key/value store of player options.
19547 function TextTrackSettings(player, options) {
19548 _classCallCheck(this, TextTrackSettings);
19550 var _this = _possibleConstructorReturn(this, _Component.call(this, player, options));
19552 _this.setDefaults();
19555 _this.updateDisplay = Fn.bind(_this, _this.updateDisplay);
19557 // Grab `persistTextTrackSettings` from the player options if not passed in child options
19558 if (options.persistTextTrackSettings === undefined) {
19559 _this.options_.persistTextTrackSettings = _this.options_.playerOptions.persistTextTrackSettings;
19562 _this.on(_this.$('.vjs-done-button'), 'click', function () {
19563 _this.saveSettings();
19567 _this.on(_this.$('.vjs-default-button'), 'click', function () {
19568 _this.setDefaults();
19569 _this.updateDisplay();
19572 Obj.each(selectConfigs, function (config) {
19573 _this.on(_this.$(config.selector), 'change', _this.updateDisplay);
19576 if (_this.options_.persistTextTrackSettings) {
19577 _this.restoreSettings();
19583 * Create a <select> element with configured options.
19585 * @param {string} key
19586 * Configuration key to use during creation.
19588 * @return {Element}
19589 * The DOM element that gets created.
19594 TextTrackSettings.prototype.createElSelect_ = function createElSelect_(key) {
19597 var config = selectConfigs[key];
19598 var id = config.id.replace('%s', this.id_);
19600 return [(0, _dom.createEl)('label', {
19601 className: 'vjs-label',
19602 textContent: config.label
19605 }), (0, _dom.createEl)('select', { id: id }, undefined, config.options.map(function (o) {
19606 return (0, _dom.createEl)('option', {
19607 textContent: _this2.localize(o[1]),
19614 * Create foreground color element for the component
19616 * @return {Element}
19617 * The element that was created.
19623 TextTrackSettings.prototype.createElFgColor_ = function createElFgColor_() {
19624 var legend = (0, _dom.createEl)('legend', {
19625 textContent: this.localize('Text')
19628 var select = this.createElSelect_('color');
19630 var opacity = (0, _dom.createEl)('span', {
19631 className: 'vjs-text-opacity vjs-opacity'
19632 }, undefined, this.createElSelect_('textOpacity'));
19634 return (0, _dom.createEl)('fieldset', {
19635 className: 'vjs-fg-color vjs-tracksetting'
19636 }, undefined, [legend].concat(select, opacity));
19640 * Create background color element for the component
19642 * @return {Element}
19643 * The element that was created
19649 TextTrackSettings.prototype.createElBgColor_ = function createElBgColor_() {
19650 var legend = (0, _dom.createEl)('legend', {
19651 textContent: this.localize('Background')
19654 var select = this.createElSelect_('backgroundColor');
19656 var opacity = (0, _dom.createEl)('span', {
19657 className: 'vjs-bg-opacity vjs-opacity'
19658 }, undefined, this.createElSelect_('backgroundOpacity'));
19660 return (0, _dom.createEl)('fieldset', {
19661 className: 'vjs-bg-color vjs-tracksetting'
19662 }, undefined, [legend].concat(select, opacity));
19666 * Create window color element for the component
19668 * @return {Element}
19669 * The element that was created
19675 TextTrackSettings.prototype.createElWinColor_ = function createElWinColor_() {
19676 var legend = (0, _dom.createEl)('legend', {
19677 textContent: this.localize('Window')
19680 var select = this.createElSelect_('windowColor');
19682 var opacity = (0, _dom.createEl)('span', {
19683 className: 'vjs-window-opacity vjs-opacity'
19684 }, undefined, this.createElSelect_('windowOpacity'));
19686 return (0, _dom.createEl)('fieldset', {
19687 className: 'vjs-window-color vjs-tracksetting'
19688 }, undefined, [legend].concat(select, opacity));
19692 * Create color elements for the component
19694 * @return {Element}
19695 * The element that was created
19701 TextTrackSettings.prototype.createElColors_ = function createElColors_() {
19702 return (0, _dom.createEl)('div', {
19703 className: 'vjs-tracksettings-colors'
19704 }, undefined, [this.createElFgColor_(), this.createElBgColor_(), this.createElWinColor_()]);
19708 * Create font elements for the component
19710 * @return {Element}
19711 * The element that was created.
19717 TextTrackSettings.prototype.createElFont_ = function createElFont_() {
19718 var fontPercent = (0, _dom.createEl)('div', {
19719 className: 'vjs-font-percent vjs-tracksetting'
19720 }, undefined, this.createElSelect_('fontPercent'));
19722 var edgeStyle = (0, _dom.createEl)('div', {
19723 className: 'vjs-edge-style vjs-tracksetting'
19724 }, undefined, this.createElSelect_('edgeStyle'));
19726 var fontFamily = (0, _dom.createEl)('div', {
19727 className: 'vjs-font-family vjs-tracksetting'
19728 }, undefined, this.createElSelect_('fontFamily'));
19730 return (0, _dom.createEl)('div', {
19731 className: 'vjs-tracksettings-font'
19732 }, undefined, [fontPercent, edgeStyle, fontFamily]);
19736 * Create controls for the component
19738 * @return {Element}
19739 * The element that was created.
19745 TextTrackSettings.prototype.createElControls_ = function createElControls_() {
19746 var defaultsButton = (0, _dom.createEl)('button', {
19747 className: 'vjs-default-button',
19748 textContent: this.localize('Defaults')
19751 var doneButton = (0, _dom.createEl)('button', {
19752 className: 'vjs-done-button',
19753 textContent: 'Done'
19756 return (0, _dom.createEl)('div', {
19757 className: 'vjs-tracksettings-controls'
19758 }, undefined, [defaultsButton, doneButton]);
19762 * Create the component's DOM element
19764 * @return {Element}
19765 * The element that was created.
19769 TextTrackSettings.prototype.createEl = function createEl() {
19770 var settings = (0, _dom.createEl)('div', {
19771 className: 'vjs-tracksettings'
19772 }, undefined, [this.createElColors_(), this.createElFont_(), this.createElControls_()]);
19774 var heading = (0, _dom.createEl)('div', {
19775 className: 'vjs-control-text',
19776 id: 'TTsettingsDialogLabel-' + this.id_,
19777 textContent: 'Caption Settings Dialog'
19783 var description = (0, _dom.createEl)('div', {
19784 className: 'vjs-control-text',
19785 id: 'TTsettingsDialogDescription-' + this.id_,
19786 textContent: 'Beginning of dialog window. Escape will cancel and close the window.'
19789 var doc = (0, _dom.createEl)('div', undefined, {
19791 }, [heading, description, settings]);
19793 return (0, _dom.createEl)('div', {
19794 className: 'vjs-caption-settings vjs-modal-overlay',
19798 'aria-labelledby': heading.id,
19799 'aria-describedby': description.id
19804 * Gets an object of text track settings (or null).
19807 * An object with config values parsed from the DOM or localStorage.
19811 TextTrackSettings.prototype.getValues = function getValues() {
19814 return Obj.reduce(selectConfigs, function (accum, config, key) {
19815 var value = getSelectedOptionValue(_this3.$(config.selector), config.parser);
19817 if (value !== undefined) {
19818 accum[key] = value;
19826 * Sets text track settings from an object of values.
19828 * @param {Object} values
19829 * An object with config values parsed from the DOM or localStorage.
19833 TextTrackSettings.prototype.setValues = function setValues(values) {
19836 Obj.each(selectConfigs, function (config, key) {
19837 setSelectedOption(_this4.$(config.selector), values[key], config.parser);
19842 * Sets all <select> elements to their default values.
19846 TextTrackSettings.prototype.setDefaults = function setDefaults() {
19849 Obj.each(selectConfigs, function (config) {
19850 var index = config.hasOwnProperty('default') ? config['default'] : 0;
19852 _this5.$(config.selector).selectedIndex = index;
19857 * Restore texttrack settings from localStorage
19861 TextTrackSettings.prototype.restoreSettings = function restoreSettings() {
19862 var values = void 0;
19865 values = JSON.parse(_window2['default'].localStorage.getItem(LOCAL_STORAGE_KEY));
19867 _log2['default'].warn(err);
19871 this.setValues(values);
19876 * Save text track settings to localStorage
19880 TextTrackSettings.prototype.saveSettings = function saveSettings() {
19881 if (!this.options_.persistTextTrackSettings) {
19885 var values = this.getValues();
19888 if (Object.keys(values).length) {
19889 _window2['default'].localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(values));
19891 _window2['default'].localStorage.removeItem(LOCAL_STORAGE_KEY);
19894 _log2['default'].warn(err);
19899 * Update display of text track settings
19903 TextTrackSettings.prototype.updateDisplay = function updateDisplay() {
19904 var ttDisplay = this.player_.getChild('textTrackDisplay');
19907 ttDisplay.updateDisplay();
19911 return TextTrackSettings;
19912 }(_component2['default']);
19914 _component2['default'].registerComponent('TextTrackSettings', TextTrackSettings);
19916 exports['default'] = TextTrackSettings;
19918 },{"5":5,"81":81,"83":83,"86":86,"88":88,"95":95}],72:[function(_dereq_,module,exports){
19921 exports.__esModule = true;
19923 var _textTrackCueList = _dereq_(67);
19925 var _textTrackCueList2 = _interopRequireDefault(_textTrackCueList);
19927 var _fn = _dereq_(83);
19929 var Fn = _interopRequireWildcard(_fn);
19931 var _trackEnums = _dereq_(73);
19933 var _log = _dereq_(86);
19935 var _log2 = _interopRequireDefault(_log);
19937 var _window = _dereq_(95);
19939 var _window2 = _interopRequireDefault(_window);
19941 var _track = _dereq_(75);
19943 var _track2 = _interopRequireDefault(_track);
19945 var _url = _dereq_(92);
19947 var _xhr = _dereq_(99);
19949 var _xhr2 = _interopRequireDefault(_xhr);
19951 var _mergeOptions = _dereq_(87);
19953 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
19955 var _browser = _dereq_(78);
19957 var browser = _interopRequireWildcard(_browser);
19959 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
19961 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
19963 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
19965 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
19967 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
19968 * @file text-track.js
19973 * Takes a webvtt file contents and parses it into cues
19975 * @param {string} srcContent
19976 * webVTT file contents
19978 * @param {TextTrack} track
19979 * TextTrack to add cues to. Cues come from the srcContent.
19983 var parseCues = function parseCues(srcContent, track) {
19984 var parser = new _window2['default'].WebVTT.Parser(_window2['default'], _window2['default'].vttjs, _window2['default'].WebVTT.StringDecoder());
19987 parser.oncue = function (cue) {
19991 parser.onparsingerror = function (error) {
19992 errors.push(error);
19995 parser.onflush = function () {
19997 type: 'loadeddata',
20002 parser.parse(srcContent);
20003 if (errors.length > 0) {
20004 if (_window2['default'].console && _window2['default'].console.groupCollapsed) {
20005 _window2['default'].console.groupCollapsed('Text Track parsing errors for ' + track.src);
20007 errors.forEach(function (error) {
20008 return _log2['default'].error(error);
20010 if (_window2['default'].console && _window2['default'].console.groupEnd) {
20011 _window2['default'].console.groupEnd();
20019 * Load a `TextTrack` from a specified url.
20021 * @param {string} src
20022 * Url to load track from.
20024 * @param {TextTrack} track
20025 * Track to add cues to. Comes from the content at the end of `url`.
20029 var loadTrack = function loadTrack(src, track) {
20033 var crossOrigin = (0, _url.isCrossOrigin)(src);
20036 opts.cors = crossOrigin;
20039 (0, _xhr2['default'])(opts, Fn.bind(this, function (err, response, responseBody) {
20041 return _log2['default'].error(err, response);
20044 track.loaded_ = true;
20046 // Make sure that vttjs has loaded, otherwise, wait till it finished loading
20047 // NOTE: this is only used for the alt/video.novtt.js build
20048 if (typeof _window2['default'].WebVTT !== 'function') {
20051 var loadHandler = function loadHandler() {
20052 return parseCues(responseBody, track);
20055 track.tech_.on('vttjsloaded', loadHandler);
20056 track.tech_.on('vttjserror', function () {
20057 _log2['default'].error('vttjs failed to load, stopping trying to process ' + track.src);
20058 track.tech_.off('vttjsloaded', loadHandler);
20063 parseCues(responseBody, track);
20069 * A representation of a single `TextTrack`.
20071 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack}
20075 var TextTrack = function (_Track) {
20076 _inherits(TextTrack, _Track);
20079 * Create an instance of this class.
20081 * @param {Object} options={}
20082 * Object of option names and values
20084 * @param {Tech} options.tech
20085 * A reference to the tech that owns this TextTrack.
20087 * @param {TextTrack~Kind} [options.kind='subtitles']
20088 * A valid text track kind.
20090 * @param {TextTrack~Mode} [options.mode='disabled']
20091 * A valid text track mode.
20093 * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
20094 * A unique id for this TextTrack.
20096 * @param {string} [options.label='']
20097 * The menu label for this track.
20099 * @param {string} [options.language='']
20100 * A valid two character language code.
20102 * @param {string} [options.srclang='']
20103 * A valid two character language code. An alternative, but deprioritized
20104 * version of `options.language`
20106 * @param {string} [options.src]
20107 * A url to TextTrack cues.
20109 * @param {boolean} [options.default]
20110 * If this track should default to on or off.
20112 function TextTrack() {
20115 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
20117 _classCallCheck(this, TextTrack);
20119 if (!options.tech) {
20120 throw new Error('A tech was not provided.');
20123 var settings = (0, _mergeOptions2['default'])(options, {
20124 kind: _trackEnums.TextTrackKind[options.kind] || 'subtitles',
20125 language: options.language || options.srclang || ''
20127 var mode = _trackEnums.TextTrackMode[settings.mode] || 'disabled';
20128 var default_ = settings['default'];
20130 if (settings.kind === 'metadata' || settings.kind === 'chapters') {
20133 // on IE8 this will be a document element
20134 // for every other browser this will be a normal object
20135 var tt = (_this = _possibleConstructorReturn(this, _Track.call(this, settings)), _this);
20137 tt.tech_ = settings.tech;
20139 if (browser.IS_IE8) {
20140 for (var prop in TextTrack.prototype) {
20141 if (prop !== 'constructor') {
20142 tt[prop] = TextTrack.prototype[prop];
20148 tt.activeCues_ = [];
20150 var cues = new _textTrackCueList2['default'](tt.cues_);
20151 var activeCues = new _textTrackCueList2['default'](tt.activeCues_);
20152 var changed = false;
20153 var timeupdateHandler = Fn.bind(tt, function () {
20155 // Accessing this.activeCues for the side-effects of updating itself
20156 // due to it's nature as a getter function. Do not remove or cues will
20158 /* eslint-disable no-unused-expressions */
20160 /* eslint-enable no-unused-expressions */
20162 this.trigger('cuechange');
20167 if (mode !== 'disabled') {
20168 tt.tech_.on('timeupdate', timeupdateHandler);
20172 * @member {boolean} default
20173 * If this track was set to be on or off by default. Cannot be changed after
20178 Object.defineProperty(tt, 'default', {
20179 get: function get() {
20182 set: function set() {}
20186 * @member {string} mode
20187 * Set the mode of this TextTrack to a valid {@link TextTrack~Mode}. Will
20188 * not be set if setting to an invalid mode.
20190 * @fires TextTrack#modechange
20192 Object.defineProperty(tt, 'mode', {
20193 get: function get() {
20196 set: function set(newMode) {
20197 if (!_trackEnums.TextTrackMode[newMode]) {
20201 if (mode === 'showing') {
20202 this.tech_.on('timeupdate', timeupdateHandler);
20205 * An event that fires when mode changes on this track. This allows
20206 * the TextTrackList that holds this track to act accordingly.
20208 * > Note: This is not part of the spec!
20210 * @event TextTrack#modechange
20211 * @type {EventTarget~Event}
20213 this.trigger('modechange');
20218 * @member {TextTrackCueList} cues
20219 * The text track cue list for this TextTrack.
20221 Object.defineProperty(tt, 'cues', {
20222 get: function get() {
20223 if (!this.loaded_) {
20229 set: function set() {}
20233 * @member {TextTrackCueList} activeCues
20234 * The list text track cues that are currently active for this TextTrack.
20236 Object.defineProperty(tt, 'activeCues', {
20237 get: function get() {
20238 if (!this.loaded_) {
20243 if (this.cues.length === 0) {
20247 var ct = this.tech_.currentTime();
20250 for (var i = 0, l = this.cues.length; i < l; i++) {
20251 var cue = this.cues[i];
20253 if (cue.startTime <= ct && cue.endTime >= ct) {
20255 } else if (cue.startTime === cue.endTime && cue.startTime <= ct && cue.startTime + 0.5 >= ct) {
20262 if (active.length !== this.activeCues_.length) {
20265 for (var _i = 0; _i < active.length; _i++) {
20266 if (this.activeCues_.indexOf(active[_i]) === -1) {
20272 this.activeCues_ = active;
20273 activeCues.setCues_(this.activeCues_);
20277 set: function set() {}
20280 if (settings.src) {
20281 tt.src = settings.src;
20282 loadTrack(settings.src, tt);
20287 return _ret2 = tt, _possibleConstructorReturn(_this, _ret2);
20291 * Add a cue to the internal list of cues.
20293 * @param {TextTrack~Cue} cue
20294 * The cue to add to our internal list
20298 TextTrack.prototype.addCue = function addCue(cue) {
20299 var tracks = this.tech_.textTracks();
20302 for (var i = 0; i < tracks.length; i++) {
20303 if (tracks[i] !== this) {
20304 tracks[i].removeCue(cue);
20309 this.cues_.push(cue);
20310 this.cues.setCues_(this.cues_);
20314 * Remove a cue from our internal list
20316 * @param {TextTrack~Cue} removeCue
20317 * The cue to remove from our internal list
20321 TextTrack.prototype.removeCue = function removeCue(_removeCue) {
20322 var removed = false;
20324 for (var i = 0, l = this.cues_.length; i < l; i++) {
20325 var cue = this.cues_[i];
20327 if (cue === _removeCue) {
20328 this.cues_.splice(i, 1);
20334 this.cues.setCues_(this.cues_);
20339 }(_track2['default']);
20342 * cuechange - One or more cues in the track have become active or stopped being active.
20346 TextTrack.prototype.allowedEvents_ = {
20347 cuechange: 'cuechange'
20350 exports['default'] = TextTrack;
20352 },{"67":67,"73":73,"75":75,"78":78,"83":83,"86":86,"87":87,"92":92,"95":95,"99":99}],73:[function(_dereq_,module,exports){
20355 exports.__esModule = true;
20357 * @file track-kinds.js
20361 * All possible `VideoTrackKind`s
20363 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-videotrack-kind
20364 * @typedef VideoTrack~Kind
20367 var VideoTrackKind = exports.VideoTrackKind = {
20368 alternative: 'alternative',
20369 captions: 'captions',
20372 subtitles: 'subtitles',
20373 commentary: 'commentary'
20377 * All possible `AudioTrackKind`s
20379 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-audiotrack-kind
20380 * @typedef AudioTrack~Kind
20383 var AudioTrackKind = exports.AudioTrackKind = {
20384 'alternative': 'alternative',
20385 'descriptions': 'descriptions',
20387 'main-desc': 'main-desc',
20388 'translation': 'translation',
20389 'commentary': 'commentary'
20393 * All possible `TextTrackKind`s
20395 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-texttrack-kind
20396 * @typedef TextTrack~Kind
20399 var TextTrackKind = exports.TextTrackKind = {
20400 subtitles: 'subtitles',
20401 captions: 'captions',
20402 descriptions: 'descriptions',
20403 chapters: 'chapters',
20404 metadata: 'metadata'
20408 * All possible `TextTrackMode`s
20410 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode
20411 * @typedef TextTrack~Mode
20414 var TextTrackMode = exports.TextTrackMode = {
20415 disabled: 'disabled',
20420 },{}],74:[function(_dereq_,module,exports){
20423 exports.__esModule = true;
20425 var _eventTarget = _dereq_(42);
20427 var _eventTarget2 = _interopRequireDefault(_eventTarget);
20429 var _browser = _dereq_(78);
20431 var browser = _interopRequireWildcard(_browser);
20433 var _document = _dereq_(94);
20435 var _document2 = _interopRequireDefault(_document);
20437 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
20439 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20441 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
20443 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
20445 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
20446 * @file track-list.js
20451 * Common functionaliy between {@link TextTrackList}, {@link AudioTrackList}, and
20452 * {@link VideoTrackList}
20454 * @extends EventTarget
20456 var TrackList = function (_EventTarget) {
20457 _inherits(TrackList, _EventTarget);
20460 * Create an instance of this class
20462 * @param {Track[]} tracks
20463 * A list of tracks to initialize the list with.
20465 * @param {Object} [list]
20466 * The child object with inheritance done manually for ie8.
20470 function TrackList() {
20471 var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
20475 var list = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
20477 _classCallCheck(this, TrackList);
20479 var _this = _possibleConstructorReturn(this, _EventTarget.call(this));
20482 list = _this; // eslint-disable-line
20483 if (browser.IS_IE8) {
20484 list = _document2['default'].createElement('custom');
20485 for (var prop in TrackList.prototype) {
20486 if (prop !== 'constructor') {
20487 list[prop] = TrackList.prototype[prop];
20496 * @member {number} length
20497 * The current number of `Track`s in the this Trackist.
20499 Object.defineProperty(list, 'length', {
20500 get: function get() {
20501 return this.tracks_.length;
20505 for (var i = 0; i < tracks.length; i++) {
20506 list.addTrack_(tracks[i]);
20509 // must return the object, as for ie8 it will not be this
20510 // but a reference to a document object
20511 return _ret = list, _possibleConstructorReturn(_this, _ret);
20515 * Add a {@link Track} to the `TrackList`
20517 * @param {Track} track
20518 * The audio, video, or text track to add to the list.
20520 * @fires TrackList#addtrack
20525 TrackList.prototype.addTrack_ = function addTrack_(track) {
20526 var index = this.tracks_.length;
20528 if (!('' + index in this)) {
20529 Object.defineProperty(this, index, {
20530 get: function get() {
20531 return this.tracks_[index];
20536 // Do not add duplicate tracks
20537 if (this.tracks_.indexOf(track) === -1) {
20538 this.tracks_.push(track);
20540 * Triggered when a track is added to a track list.
20542 * @event TrackList#addtrack
20543 * @type {EventTarget~Event}
20544 * @property {Track} track
20545 * A reference to track that was added.
20555 * Remove a {@link Track} from the `TrackList`
20557 * @param {Track} track
20558 * The audio, video, or text track to remove from the list.
20560 * @fires TrackList#removetrack
20565 TrackList.prototype.removeTrack_ = function removeTrack_(rtrack) {
20566 var track = void 0;
20568 for (var i = 0, l = this.length; i < l; i++) {
20569 if (this[i] === rtrack) {
20575 this.tracks_.splice(i, 1);
20586 * Triggered when a track is removed from track list.
20588 * @event TrackList#removetrack
20589 * @type {EventTarget~Event}
20590 * @property {Track} track
20591 * A reference to track that was removed.
20595 type: 'removetrack'
20600 * Get a Track from the TrackList by a tracks id
20602 * @param {String} id - the id of the track to get
20603 * @method getTrackById
20609 TrackList.prototype.getTrackById = function getTrackById(id) {
20612 for (var i = 0, l = this.length; i < l; i++) {
20613 var track = this[i];
20615 if (track.id === id) {
20625 }(_eventTarget2['default']);
20628 * Triggered when a different track is selected/enabled.
20630 * @event TrackList#change
20631 * @type {EventTarget~Event}
20635 * Events that can be called with on + eventName. See {@link EventHandler}.
20637 * @property {Object} TrackList#allowedEvents_
20642 TrackList.prototype.allowedEvents_ = {
20644 addtrack: 'addtrack',
20645 removetrack: 'removetrack'
20648 // emulate attribute EventHandler support to allow for feature detection
20649 for (var event in TrackList.prototype.allowedEvents_) {
20650 TrackList.prototype['on' + event] = null;
20653 exports['default'] = TrackList;
20655 },{"42":42,"78":78,"94":94}],75:[function(_dereq_,module,exports){
20658 exports.__esModule = true;
20660 var _browser = _dereq_(78);
20662 var browser = _interopRequireWildcard(_browser);
20664 var _document = _dereq_(94);
20666 var _document2 = _interopRequireDefault(_document);
20668 var _guid = _dereq_(85);
20670 var Guid = _interopRequireWildcard(_guid);
20672 var _eventTarget = _dereq_(42);
20674 var _eventTarget2 = _interopRequireDefault(_eventTarget);
20676 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20678 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
20680 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
20682 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
20684 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
20690 * A Track class that contains all of the common functionality for {@link AudioTrack},
20691 * {@link VideoTrack}, and {@link TextTrack}.
20693 * > Note: This class should not be used directly
20695 * @see {@link https://html.spec.whatwg.org/multipage/embedded-content.html}
20696 * @extends EventTarget
20699 var Track = function (_EventTarget) {
20700 _inherits(Track, _EventTarget);
20703 * Create an instance of this class.
20705 * @param {Object} [options={}]
20706 * Object of option names and values
20708 * @param {string} [options.kind='']
20709 * A valid kind for the track type you are creating.
20711 * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
20712 * A unique id for this AudioTrack.
20714 * @param {string} [options.label='']
20715 * The menu label for this track.
20717 * @param {string} [options.language='']
20718 * A valid two character language code.
20725 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
20727 _classCallCheck(this, Track);
20729 var _this = _possibleConstructorReturn(this, _EventTarget.call(this));
20731 var track = _this; // eslint-disable-line
20733 if (browser.IS_IE8) {
20734 track = _document2['default'].createElement('custom');
20735 for (var prop in Track.prototype) {
20736 if (prop !== 'constructor') {
20737 track[prop] = Track.prototype[prop];
20743 id: options.id || 'vjs_track_' + Guid.newGUID(),
20744 kind: options.kind || '',
20745 label: options.label || '',
20746 language: options.language || ''
20750 * @member {string} id
20751 * The id of this track. Cannot be changed after creation.
20757 * @member {string} kind
20758 * The kind of track that this is. Cannot be changed after creation.
20764 * @member {string} label
20765 * The label of this track. Cannot be changed after creation.
20771 * @member {string} language
20772 * The two letter language code for this track. Cannot be changed after
20778 var _loop = function _loop(key) {
20779 Object.defineProperty(track, key, {
20780 get: function get() {
20781 return trackProps[key];
20783 set: function set() {}
20787 for (var key in trackProps) {
20791 return _ret = track, _possibleConstructorReturn(_this, _ret);
20795 }(_eventTarget2['default']);
20797 exports['default'] = Track;
20799 },{"42":42,"78":78,"85":85,"94":94}],76:[function(_dereq_,module,exports){
20802 exports.__esModule = true;
20804 var _trackList = _dereq_(74);
20806 var _trackList2 = _interopRequireDefault(_trackList);
20808 var _browser = _dereq_(78);
20810 var browser = _interopRequireWildcard(_browser);
20812 var _document = _dereq_(94);
20814 var _document2 = _interopRequireDefault(_document);
20816 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
20818 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
20820 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
20822 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
20824 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
20825 * @file video-track-list.js
20830 * Un-select all other {@link VideoTrack}s that are selected.
20832 * @param {VideoTrackList} list
20835 * @param {VideoTrack} track
20836 * The track to skip
20840 var disableOthers = function disableOthers(list, track) {
20841 for (var i = 0; i < list.length; i++) {
20842 if (track.id === list[i].id) {
20845 // another video track is enabled, disable it
20846 list[i].selected = false;
20851 * The current list of {@link VideoTrack} for a video.
20853 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist}
20854 * @extends TrackList
20857 var VideoTrackList = function (_TrackList) {
20858 _inherits(VideoTrackList, _TrackList);
20861 * Create an instance of this class.
20863 * @param {VideoTrack[]} [tracks=[]]
20864 * A list of `VideoTrack` to instantiate the list with.
20866 function VideoTrackList() {
20869 var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
20871 _classCallCheck(this, VideoTrackList);
20875 // make sure only 1 track is enabled
20876 // sorted from last index to first index
20877 for (var i = tracks.length - 1; i >= 0; i--) {
20878 if (tracks[i].selected) {
20879 disableOthers(tracks, tracks[i]);
20884 // IE8 forces us to implement inheritance ourselves
20885 // as it does not support Object.defineProperty properly
20886 if (browser.IS_IE8) {
20887 list = _document2['default'].createElement('custom');
20888 for (var prop in _trackList2['default'].prototype) {
20889 if (prop !== 'constructor') {
20890 list[prop] = _trackList2['default'].prototype[prop];
20893 for (var _prop in VideoTrackList.prototype) {
20894 if (_prop !== 'constructor') {
20895 list[_prop] = VideoTrackList.prototype[_prop];
20900 list = (_this = _possibleConstructorReturn(this, _TrackList.call(this, tracks, list)), _this);
20901 list.changing_ = false;
20904 * @member {number} VideoTrackList#selectedIndex
20905 * The current index of the selected {@link VideoTrack`}.
20907 Object.defineProperty(list, 'selectedIndex', {
20908 get: function get() {
20909 for (var _i = 0; _i < this.length; _i++) {
20910 if (this[_i].selected) {
20916 set: function set() {}
20919 return _ret = list, _possibleConstructorReturn(_this, _ret);
20923 * Add a {@link VideoTrack} to the `VideoTrackList`.
20925 * @param {VideoTrack} track
20926 * The VideoTrack to add to the list
20928 * @fires TrackList#addtrack
20933 VideoTrackList.prototype.addTrack_ = function addTrack_(track) {
20936 if (track.selected) {
20937 disableOthers(this, track);
20940 _TrackList.prototype.addTrack_.call(this, track);
20941 // native tracks don't have this
20942 if (!track.addEventListener) {
20947 * @listens VideoTrack#selectedchange
20948 * @fires TrackList#change
20950 track.addEventListener('selectedchange', function () {
20951 if (_this2.changing_) {
20954 _this2.changing_ = true;
20955 disableOthers(_this2, track);
20956 _this2.changing_ = false;
20957 _this2.trigger('change');
20962 * Add a {@link VideoTrack} to the `VideoTrackList`.
20964 * @param {VideoTrack} track
20965 * The VideoTrack to add to the list
20967 * @fires TrackList#addtrack
20971 VideoTrackList.prototype.addTrack = function addTrack(track) {
20972 this.addTrack_(track);
20976 * Remove a {@link VideoTrack} to the `VideoTrackList`.
20978 * @param {VideoTrack} track
20979 * The VideoTrack to remove from the list.
20981 * @fires TrackList#removetrack
20985 VideoTrackList.prototype.removeTrack = function removeTrack(track) {
20986 _TrackList.prototype.removeTrack_.call(this, track);
20989 return VideoTrackList;
20990 }(_trackList2['default']);
20992 exports['default'] = VideoTrackList;
20994 },{"74":74,"78":78,"94":94}],77:[function(_dereq_,module,exports){
20997 exports.__esModule = true;
20999 var _trackEnums = _dereq_(73);
21001 var _track = _dereq_(75);
21003 var _track2 = _interopRequireDefault(_track);
21005 var _mergeOptions = _dereq_(87);
21007 var _mergeOptions2 = _interopRequireDefault(_mergeOptions);
21009 var _browser = _dereq_(78);
21011 var browser = _interopRequireWildcard(_browser);
21013 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
21015 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21017 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
21019 function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
21021 function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
21024 * A representation of a single `VideoTrack`.
21026 * @see [Spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#videotrack}
21029 var VideoTrack = function (_Track) {
21030 _inherits(VideoTrack, _Track);
21033 * Create an instance of this class.
21035 * @param {Object} [options={}]
21036 * Object of option names and values
21038 * @param {string} [options.kind='']
21039 * A valid {@link VideoTrack~Kind}
21041 * @param {string} [options.id='vjs_track_' + Guid.newGUID()]
21042 * A unique id for this AudioTrack.
21044 * @param {string} [options.label='']
21045 * The menu label for this track.
21047 * @param {string} [options.language='']
21048 * A valid two character language code.
21050 * @param {boolean} [options.selected]
21051 * If this track is the one that is currently playing.
21053 function VideoTrack() {
21056 var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
21058 _classCallCheck(this, VideoTrack);
21060 var settings = (0, _mergeOptions2['default'])(options, {
21061 kind: _trackEnums.VideoTrackKind[options.kind] || ''
21064 // on IE8 this will be a document element
21065 // for every other browser this will be a normal object
21066 var track = (_this = _possibleConstructorReturn(this, _Track.call(this, settings)), _this);
21067 var selected = false;
21069 if (browser.IS_IE8) {
21070 for (var prop in VideoTrack.prototype) {
21071 if (prop !== 'constructor') {
21072 track[prop] = VideoTrack.prototype[prop];
21078 * @member {boolean} selected
21079 * If this `VideoTrack` is selected or not. When setting this will
21080 * fire {@link VideoTrack#selectedchange} if the state of selected changed.
21082 * @fires VideoTrack#selectedchange
21084 Object.defineProperty(track, 'selected', {
21085 get: function get() {
21088 set: function set(newSelected) {
21089 // an invalid or unchanged value
21090 if (typeof newSelected !== 'boolean' || newSelected === selected) {
21093 selected = newSelected;
21096 * An event that fires when selected changes on this track. This allows
21097 * the VideoTrackList that holds this track to act accordingly.
21099 * > Note: This is not part of the spec! Native tracks will do
21100 * this internally without an event.
21102 * @event VideoTrack#selectedchange
21103 * @type {EventTarget~Event}
21105 this.trigger('selectedchange');
21109 // if the user sets this track to selected then
21110 // set selected to that true value otherwise
21111 // we keep it false
21112 if (settings.selected) {
21113 track.selected = settings.selected;
21116 return _ret = track, _possibleConstructorReturn(_this, _ret);
21120 }(_track2['default']);
21122 exports['default'] = VideoTrack;
21124 },{"73":73,"75":75,"78":78,"87":87}],78:[function(_dereq_,module,exports){
21127 exports.__esModule = true;
21128 exports.BACKGROUND_SIZE_SUPPORTED = exports.TOUCH_ENABLED = exports.IS_ANY_SAFARI = exports.IS_SAFARI = exports.IE_VERSION = exports.IS_IE8 = exports.IS_CHROME = exports.IS_EDGE = exports.IS_FIREFOX = exports.IS_NATIVE_ANDROID = exports.IS_OLD_ANDROID = exports.ANDROID_VERSION = exports.IS_ANDROID = exports.IOS_VERSION = exports.IS_IOS = exports.IS_IPOD = exports.IS_IPHONE = exports.IS_IPAD = undefined;
21130 var _dom = _dereq_(81);
21132 var Dom = _interopRequireWildcard(_dom);
21134 var _window = _dereq_(95);
21136 var _window2 = _interopRequireDefault(_window);
21138 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21140 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
21146 var USER_AGENT = _window2['default'].navigator && _window2['default'].navigator.userAgent || '';
21147 var webkitVersionMap = /AppleWebKit\/([\d.]+)/i.exec(USER_AGENT);
21148 var appleWebkitVersion = webkitVersionMap ? parseFloat(webkitVersionMap.pop()) : null;
21151 * Device is an iPhone
21157 var IS_IPAD = exports.IS_IPAD = /iPad/i.test(USER_AGENT);
21159 // The Facebook app's UIWebView identifies as both an iPhone and iPad, so
21160 // to identify iPhones, we need to exclude iPads.
21161 // http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/
21162 var IS_IPHONE = exports.IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD;
21163 var IS_IPOD = exports.IS_IPOD = /iPod/i.test(USER_AGENT);
21164 var IS_IOS = exports.IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD;
21166 var IOS_VERSION = exports.IOS_VERSION = function () {
21167 var match = USER_AGENT.match(/OS (\d+)_/i);
21169 if (match && match[1]) {
21175 var IS_ANDROID = exports.IS_ANDROID = /Android/i.test(USER_AGENT);
21176 var ANDROID_VERSION = exports.ANDROID_VERSION = function () {
21177 // This matches Android Major.Minor.Patch versions
21178 // ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned
21179 var match = USER_AGENT.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i);
21185 var major = match[1] && parseFloat(match[1]);
21186 var minor = match[2] && parseFloat(match[2]);
21188 if (major && minor) {
21189 return parseFloat(match[1] + '.' + match[2]);
21190 } else if (major) {
21196 // Old Android is defined as Version older than 2.3, and requiring a webkit version of the android browser
21197 var IS_OLD_ANDROID = exports.IS_OLD_ANDROID = IS_ANDROID && /webkit/i.test(USER_AGENT) && ANDROID_VERSION < 2.3;
21198 var IS_NATIVE_ANDROID = exports.IS_NATIVE_ANDROID = IS_ANDROID && ANDROID_VERSION < 5 && appleWebkitVersion < 537;
21200 var IS_FIREFOX = exports.IS_FIREFOX = /Firefox/i.test(USER_AGENT);
21201 var IS_EDGE = exports.IS_EDGE = /Edge/i.test(USER_AGENT);
21202 var IS_CHROME = exports.IS_CHROME = !IS_EDGE && /Chrome/i.test(USER_AGENT);
21203 var IS_IE8 = exports.IS_IE8 = /MSIE\s8\.0/.test(USER_AGENT);
21204 var IE_VERSION = exports.IE_VERSION = function (result) {
21205 return result && parseFloat(result[1]);
21206 }(/MSIE\s(\d+)\.\d/.exec(USER_AGENT));
21208 var IS_SAFARI = exports.IS_SAFARI = /Safari/i.test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE;
21209 var IS_ANY_SAFARI = exports.IS_ANY_SAFARI = IS_SAFARI || IS_IOS;
21211 var TOUCH_ENABLED = exports.TOUCH_ENABLED = Dom.isReal() && ('ontouchstart' in _window2['default'] || _window2['default'].DocumentTouch && _window2['default'].document instanceof _window2['default'].DocumentTouch);
21213 var BACKGROUND_SIZE_SUPPORTED = exports.BACKGROUND_SIZE_SUPPORTED = Dom.isReal() && 'backgroundSize' in _window2['default'].document.createElement('video').style;
21215 },{"81":81,"95":95}],79:[function(_dereq_,module,exports){
21218 exports.__esModule = true;
21219 exports.bufferedPercent = bufferedPercent;
21221 var _timeRanges = _dereq_(90);
21224 * Compute the percentage of the media that has been buffered.
21226 * @param {TimeRange} buffered
21227 * The current `TimeRange` object representing buffered time ranges
21229 * @param {number} duration
21230 * Total duration of the media
21233 * Percent buffered of the total duration in decimal form.
21235 function bufferedPercent(buffered, duration) {
21236 var bufferedDuration = 0;
21237 var start = void 0;
21244 if (!buffered || !buffered.length) {
21245 buffered = (0, _timeRanges.createTimeRange)(0, 0);
21248 for (var i = 0; i < buffered.length; i++) {
21249 start = buffered.start(i);
21250 end = buffered.end(i);
21252 // buffered end can be bigger than duration by a very small fraction
21253 if (end > duration) {
21257 bufferedDuration += end - start;
21260 return bufferedDuration / duration;
21266 },{"90":90}],80:[function(_dereq_,module,exports){
21269 exports.__esModule = true;
21270 exports['default'] = computedStyle;
21272 var _window = _dereq_(95);
21274 var _window2 = _interopRequireDefault(_window);
21276 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21279 * A safe getComputedStyle with an IE8 fallback.
21281 * This is needed because in Firefox, if the player is loaded in an iframe with
21282 * `display:none`, then `getComputedStyle` returns `null`, so, we do a null-check to
21283 * make sure that the player doesn't break in these cases.
21285 * @param {Element} el
21286 * The element you want the computed style of
21288 * @param {string} prop
21289 * The property name you want
21291 * @see https://bugzilla.mozilla.org/show_bug.cgi?id=548397
21293 function computedStyle(el, prop) {
21294 if (!el || !prop) {
21298 if (typeof _window2['default'].getComputedStyle === 'function') {
21299 var cs = _window2['default'].getComputedStyle(el);
21301 return cs ? cs[prop] : '';
21304 return el.currentStyle[prop] || '';
21306 * @file computed-style.js
21307 * @module computed-style
21310 },{"95":95}],81:[function(_dereq_,module,exports){
21313 exports.__esModule = true;
21314 exports.$$ = exports.$ = undefined;
21316 var _templateObject = _taggedTemplateLiteralLoose(['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.'], ['Setting attributes in the second argument of createEl()\n has been deprecated. Use the third argument instead.\n createEl(type, properties, attributes). Attempting to set ', ' to ', '.']);
21318 exports.isReal = isReal;
21319 exports.isEl = isEl;
21320 exports.getEl = getEl;
21321 exports.createEl = createEl;
21322 exports.textContent = textContent;
21323 exports.insertElFirst = insertElFirst;
21324 exports.getElData = getElData;
21325 exports.hasElData = hasElData;
21326 exports.removeElData = removeElData;
21327 exports.hasElClass = hasElClass;
21328 exports.addElClass = addElClass;
21329 exports.removeElClass = removeElClass;
21330 exports.toggleElClass = toggleElClass;
21331 exports.setElAttributes = setElAttributes;
21332 exports.getElAttributes = getElAttributes;
21333 exports.getAttribute = getAttribute;
21334 exports.setAttribute = setAttribute;
21335 exports.removeAttribute = removeAttribute;
21336 exports.blockTextSelection = blockTextSelection;
21337 exports.unblockTextSelection = unblockTextSelection;
21338 exports.findElPosition = findElPosition;
21339 exports.getPointerPosition = getPointerPosition;
21340 exports.isTextNode = isTextNode;
21341 exports.emptyEl = emptyEl;
21342 exports.normalizeContent = normalizeContent;
21343 exports.appendContent = appendContent;
21344 exports.insertContent = insertContent;
21346 var _document = _dereq_(94);
21348 var _document2 = _interopRequireDefault(_document);
21350 var _window = _dereq_(95);
21352 var _window2 = _interopRequireDefault(_window);
21354 var _guid = _dereq_(85);
21356 var Guid = _interopRequireWildcard(_guid);
21358 var _log = _dereq_(86);
21360 var _log2 = _interopRequireDefault(_log);
21362 var _tsml = _dereq_(98);
21364 var _tsml2 = _interopRequireDefault(_tsml);
21366 var _obj = _dereq_(88);
21368 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
21370 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
21372 function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; } /**
21379 * Detect if a value is a string with any non-whitespace characters.
21381 * @param {string} str
21382 * The string to check
21384 * @return {boolean}
21385 * - True if the string is non-blank
21386 * - False otherwise
21389 function isNonBlankString(str) {
21390 return typeof str === 'string' && /\S/.test(str);
21394 * Throws an error if the passed string has whitespace. This is used by
21395 * class methods to be relatively consistent with the classList API.
21397 * @param {string} str
21398 * The string to check for whitespace.
21401 * Throws an error if there is whitespace in the string.
21404 function throwIfWhitespace(str) {
21405 if (/\s/.test(str)) {
21406 throw new Error('class has illegal whitespace characters');
21411 * Produce a regular expression for matching a className within an elements className.
21413 * @param {string} className
21414 * The className to generate the RegExp for.
21417 * The RegExp that will check for a specific `className` in an elements
21420 function classRegExp(className) {
21421 return new RegExp('(^|\\s)' + className + '($|\\s)');
21425 * Whether the current DOM interface appears to be real.
21427 * @return {Boolean}
21429 function isReal() {
21432 // Both document and window will never be undefined thanks to `global`.
21433 _document2['default'] === _window2['default'].document &&
21435 // In IE < 9, DOM methods return "object" as their type, so all we can
21436 // confidently check is that it exists.
21437 typeof _document2['default'].createElement !== 'undefined'
21442 * Determines, via duck typing, whether or not a value is a DOM element.
21444 * @param {Mixed} value
21445 * The thing to check
21447 * @return {boolean}
21448 * - True if it is a DOM element
21449 * - False otherwise
21451 function isEl(value) {
21452 return (0, _obj.isObject)(value) && value.nodeType === 1;
21456 * Creates functions to query the DOM using a given method.
21458 * @param {string} method
21459 * The method to create the query with.
21461 * @return {Function}
21464 function createQuerier(method) {
21465 return function (selector, context) {
21466 if (!isNonBlankString(selector)) {
21467 return _document2['default'][method](null);
21469 if (isNonBlankString(context)) {
21470 context = _document2['default'].querySelector(context);
21473 var ctx = isEl(context) ? context : _document2['default'];
21475 return ctx[method] && ctx[method](selector);
21480 * Shorthand for document.getElementById()
21481 * Also allows for CSS (jQuery) ID syntax. But nothing other than IDs.
21483 * @param {string} id
21484 * The id of the element to get
21486 * @return {Element|null}
21487 * Element with supplied ID or null if there wasn't one.
21489 function getEl(id) {
21490 if (id.indexOf('#') === 0) {
21494 return _document2['default'].getElementById(id);
21498 * Creates an element and applies properties.
21500 * @param {string} [tagName='div']
21501 * Name of tag to be created.
21503 * @param {Object} [properties={}]
21504 * Element properties to be applied.
21506 * @param {Object} [attributes={}]
21507 * Element attributes to be applied.
21509 * @param {String|Element|TextNode|Array|Function} [content]
21510 * Contents for the element (see: {@link dom:normalizeContent})
21512 * @return {Element}
21513 * The element that was created.
21515 function createEl() {
21516 var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div';
21517 var properties = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
21518 var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
21519 var content = arguments[3];
21521 var el = _document2['default'].createElement(tagName);
21523 Object.getOwnPropertyNames(properties).forEach(function (propName) {
21524 var val = properties[propName];
21527 // We originally were accepting both properties and attributes in the
21528 // same object, but that doesn't work so well.
21529 if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
21530 _log2['default'].warn((0, _tsml2['default'])(_templateObject, propName, val));
21531 el.setAttribute(propName, val);
21533 // Handle textContent since it's not supported everywhere and we have a
21535 } else if (propName === 'textContent') {
21536 textContent(el, val);
21538 el[propName] = val;
21542 Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
21543 el.setAttribute(attrName, attributes[attrName]);
21547 appendContent(el, content);
21554 * Injects text into an element, replacing any existing contents entirely.
21556 * @param {Element} el
21557 * The element to add text content into
21559 * @param {string} text
21560 * The text content to add.
21562 * @return {Element}
21563 * The element with added text content.
21565 function textContent(el, text) {
21566 if (typeof el.textContent === 'undefined') {
21567 el.innerText = text;
21569 el.textContent = text;
21575 * Insert an element as the first child node of another
21577 * @param {Element} child
21578 * Element to insert
21580 * @param {Element} parent
21581 * Element to insert child into
21584 function insertElFirst(child, parent) {
21585 if (parent.firstChild) {
21586 parent.insertBefore(child, parent.firstChild);
21588 parent.appendChild(child);
21593 * Element Data Store. Allows for binding data to an element without putting it directly on the element.
21594 * Ex. Event listeners are stored here.
21595 * (also from jsninja.com, slightly modified and updated for closure compiler)
21603 * Unique attribute name to store an element's guid in
21609 var elIdAttr = 'vdata' + new Date().getTime();
21612 * Returns the cache object where data for an element is stored
21614 * @param {Element} el
21615 * Element to store data for.
21618 * The cache object for that el that was passed in.
21620 function getElData(el) {
21621 var id = el[elIdAttr];
21624 id = el[elIdAttr] = Guid.newGUID();
21635 * Returns whether or not an element has cached data
21637 * @param {Element} el
21638 * Check if this element has cached data.
21640 * @return {boolean}
21641 * - True if the DOM element has cached data.
21642 * - False otherwise.
21644 function hasElData(el) {
21645 var id = el[elIdAttr];
21651 return !!Object.getOwnPropertyNames(elData[id]).length;
21655 * Delete data for the element from the cache and the guid attr from getElementById
21657 * @param {Element} el
21658 * Remove cached data for this element.
21660 function removeElData(el) {
21661 var id = el[elIdAttr];
21667 // Remove all stored data
21670 // Remove the elIdAttr property from the DOM node
21672 delete el[elIdAttr];
21674 if (el.removeAttribute) {
21675 el.removeAttribute(elIdAttr);
21677 // IE doesn't appear to support removeAttribute on the document element
21678 el[elIdAttr] = null;
21684 * Check if an element has a CSS class
21686 * @param {Element} element
21689 * @param {string} classToCheck
21690 * Class name to check for
21692 * @return {boolean}
21693 * - True if the element had the class
21694 * - False otherwise.
21697 * Throws an error if `classToCheck` has white space.
21699 function hasElClass(element, classToCheck) {
21700 throwIfWhitespace(classToCheck);
21701 if (element.classList) {
21702 return element.classList.contains(classToCheck);
21704 return classRegExp(classToCheck).test(element.className);
21708 * Add a CSS class name to an element
21710 * @param {Element} element
21711 * Element to add class name to.
21713 * @param {string} classToAdd
21714 * Class name to add.
21716 * @return {Element}
21717 * The dom element with the added class name.
21719 function addElClass(element, classToAdd) {
21720 if (element.classList) {
21721 element.classList.add(classToAdd);
21723 // Don't need to `throwIfWhitespace` here because `hasElClass` will do it
21724 // in the case of classList not being supported.
21725 } else if (!hasElClass(element, classToAdd)) {
21726 element.className = (element.className + ' ' + classToAdd).trim();
21733 * Remove a CSS class name from an element
21735 * @param {Element} element
21736 * Element to remove a class name from.
21738 * @param {string} classToRemove
21739 * Class name to remove
21741 * @return {Element}
21742 * The dom element with class name removed.
21744 function removeElClass(element, classToRemove) {
21745 if (element.classList) {
21746 element.classList.remove(classToRemove);
21748 throwIfWhitespace(classToRemove);
21749 element.className = element.className.split(/\s+/).filter(function (c) {
21750 return c !== classToRemove;
21758 * The callback definition for toggleElClass.
21760 * @callback Dom~PredicateCallback
21761 * @param {Element} element
21762 * The DOM element of the Component.
21764 * @param {string} classToToggle
21765 * The `className` that wants to be toggled
21767 * @return {boolean|undefined}
21768 * - If true the `classToToggle` will get added to `element`.
21769 * - If false the `classToToggle` will get removed from `element`.
21770 * - If undefined this callback will be ignored
21774 * Adds or removes a CSS class name on an element depending on an optional
21775 * condition or the presence/absence of the class name.
21777 * @param {Element} element
21778 * The element to toggle a class name on.
21780 * @param {string} classToToggle
21781 * The class that should be toggled
21783 * @param {boolean|PredicateCallback} [predicate]
21784 * See the return value for {@link Dom~PredicateCallback}
21786 * @return {Element}
21787 * The element with a class that has been toggled.
21789 function toggleElClass(element, classToToggle, predicate) {
21791 // This CANNOT use `classList` internally because IE does not support the
21792 // second parameter to the `classList.toggle()` method! Which is fine because
21793 // `classList` will be used by the add/remove functions.
21794 var has = hasElClass(element, classToToggle);
21796 if (typeof predicate === 'function') {
21797 predicate = predicate(element, classToToggle);
21800 if (typeof predicate !== 'boolean') {
21804 // If the necessary class operation matches the current state of the
21805 // element, no action is required.
21806 if (predicate === has) {
21811 addElClass(element, classToToggle);
21813 removeElClass(element, classToToggle);
21820 * Apply attributes to an HTML element.
21822 * @param {Element} el
21823 * Element to add attributes to.
21825 * @param {Object} [attributes]
21826 * Attributes to be applied.
21828 function setElAttributes(el, attributes) {
21829 Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
21830 var attrValue = attributes[attrName];
21832 if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) {
21833 el.removeAttribute(attrName);
21835 el.setAttribute(attrName, attrValue === true ? '' : attrValue);
21841 * Get an element's attribute values, as defined on the HTML tag
21842 * Attributes are not the same as properties. They're defined on the tag
21843 * or with setAttribute (which shouldn't be used with HTML)
21844 * This will return true or false for boolean attributes.
21846 * @param {Element} tag
21847 * Element from which to get tag attributes.
21850 * All attributes of the element.
21852 function getElAttributes(tag) {
21855 // known boolean attributes
21856 // we can check for matching boolean properties, but older browsers
21857 // won't know about HTML5 boolean attributes that we still read from
21858 var knownBooleans = ',' + 'autoplay,controls,loop,muted,default' + ',';
21860 if (tag && tag.attributes && tag.attributes.length > 0) {
21861 var attrs = tag.attributes;
21863 for (var i = attrs.length - 1; i >= 0; i--) {
21864 var attrName = attrs[i].name;
21865 var attrVal = attrs[i].value;
21867 // check for known booleans
21868 // the matching element property will return a value for typeof
21869 if (typeof tag[attrName] === 'boolean' || knownBooleans.indexOf(',' + attrName + ',') !== -1) {
21870 // the value of an included boolean attribute is typically an empty
21871 // string ('') which would equal false if we just check for a false value.
21872 // we also don't want support bad code like autoplay='false'
21873 attrVal = attrVal !== null ? true : false;
21876 obj[attrName] = attrVal;
21884 * Get the value of an element's attribute
21886 * @param {Element} el
21889 * @param {string} attribute
21890 * Attribute to get the value of
21893 * value of the attribute
21895 function getAttribute(el, attribute) {
21896 return el.getAttribute(attribute);
21900 * Set the value of an element's attribute
21902 * @param {Element} el
21905 * @param {string} attribute
21908 * @param {string} value
21909 * Value to set the attribute to
21911 function setAttribute(el, attribute, value) {
21912 el.setAttribute(attribute, value);
21916 * Remove an element's attribute
21918 * @param {Element} el
21921 * @param {string} attribute
21922 * Attribute to remove
21924 function removeAttribute(el, attribute) {
21925 el.removeAttribute(attribute);
21929 * Attempt to block the ability to select text while dragging controls
21931 function blockTextSelection() {
21932 _document2['default'].body.focus();
21933 _document2['default'].onselectstart = function () {
21939 * Turn off text selection blocking
21941 function unblockTextSelection() {
21942 _document2['default'].onselectstart = function () {
21948 * The position of a DOM element on the page.
21950 * @typedef {Object} Dom~Position
21952 * @property {number} left
21953 * Pixels to the left
21955 * @property {number} top
21961 * getBoundingClientRect technique from
21964 * @see http://ejohn.org/blog/getboundingclientrect-is-awesome/
21966 * @param {Element} el
21967 * Element from which to get offset
21969 * @return {Dom~Position}
21970 * The position of the element that was passed in.
21972 function findElPosition(el) {
21975 if (el.getBoundingClientRect && el.parentNode) {
21976 box = el.getBoundingClientRect();
21986 var docEl = _document2['default'].documentElement;
21987 var body = _document2['default'].body;
21989 var clientLeft = docEl.clientLeft || body.clientLeft || 0;
21990 var scrollLeft = _window2['default'].pageXOffset || body.scrollLeft;
21991 var left = box.left + scrollLeft - clientLeft;
21993 var clientTop = docEl.clientTop || body.clientTop || 0;
21994 var scrollTop = _window2['default'].pageYOffset || body.scrollTop;
21995 var top = box.top + scrollTop - clientTop;
21997 // Android sometimes returns slightly off decimal values, so need to round
21999 left: Math.round(left),
22000 top: Math.round(top)
22005 * x and y coordinates for a dom element or mouse pointer
22007 * @typedef {Object} Dom~Coordinates
22009 * @property {number} x
22010 * x coordinate in pixels
22012 * @property {number} y
22013 * y coordinate in pixels
22017 * Get pointer position in element
22018 * Returns an object with x and y coordinates.
22019 * The base on the coordinates are the bottom left of the element.
22021 * @param {Element} el
22022 * Element on which to get the pointer position on
22024 * @param {EventTarget~Event} event
22027 * @return {Dom~Coordinates}
22028 * A Coordinates object corresponding to the mouse position.
22031 function getPointerPosition(el, event) {
22033 var box = findElPosition(el);
22034 var boxW = el.offsetWidth;
22035 var boxH = el.offsetHeight;
22037 var boxY = box.top;
22038 var boxX = box.left;
22039 var pageY = event.pageY;
22040 var pageX = event.pageX;
22042 if (event.changedTouches) {
22043 pageX = event.changedTouches[0].pageX;
22044 pageY = event.changedTouches[0].pageY;
22047 position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH));
22048 position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));
22054 * Determines, via duck typing, whether or not a value is a text node.
22056 * @param {Mixed} value
22057 * Check if this value is a text node.
22059 * @return {boolean}
22060 * - True if it is a text node
22061 * - False otherwise
22063 function isTextNode(value) {
22064 return (0, _obj.isObject)(value) && value.nodeType === 3;
22068 * Empties the contents of an element.
22070 * @param {Element} el
22071 * The element to empty children from
22073 * @return {Element}
22074 * The element with no children
22076 function emptyEl(el) {
22077 while (el.firstChild) {
22078 el.removeChild(el.firstChild);
22084 * Normalizes content for eventual insertion into the DOM.
22086 * This allows a wide range of content definition methods, but protects
22087 * from falling into the trap of simply writing to `innerHTML`, which is
22090 * The content for an element can be passed in multiple types and
22091 * combinations, whose behavior is as follows:
22093 * @param {String|Element|TextNode|Array|Function} content
22094 * - String: Normalized into a text node.
22095 * - Element/TextNode: Passed through.
22096 * - Array: A one-dimensional array of strings, elements, nodes, or functions
22097 * (which return single strings, elements, or nodes).
22098 * - Function: If the sole argument, is expected to produce a string, element,
22099 * node, or array as defined above.
22102 * All of the content that was passed in normalized.
22104 function normalizeContent(content) {
22106 // First, invoke content if it is a function. If it produces an array,
22107 // that needs to happen before normalization.
22108 if (typeof content === 'function') {
22109 content = content();
22112 // Next up, normalize to an array, so one or many items can be normalized,
22113 // filtered, and returned.
22114 return (Array.isArray(content) ? content : [content]).map(function (value) {
22116 // First, invoke value if it is a function to produce a new value,
22117 // which will be subsequently normalized to a Node of some kind.
22118 if (typeof value === 'function') {
22122 if (isEl(value) || isTextNode(value)) {
22126 if (typeof value === 'string' && /\S/.test(value)) {
22127 return _document2['default'].createTextNode(value);
22129 }).filter(function (value) {
22135 * Normalizes and appends content to an element.
22137 * @param {Element} el
22138 * Element to append normalized content to.
22141 * @param {String|Element|TextNode|Array|Function} content
22142 * See the `content` argument of {@link dom:normalizeContent}
22144 * @return {Element}
22145 * The element with appended normalized content.
22147 function appendContent(el, content) {
22148 normalizeContent(content).forEach(function (node) {
22149 return el.appendChild(node);
22155 * Normalizes and inserts content into an element; this is identical to
22156 * `appendContent()`, except it empties the element first.
22158 * @param {Element} el
22159 * Element to insert normalized content into.
22161 * @param {String|Element|TextNode|Array|Function} content
22162 * See the `content` argument of {@link dom:normalizeContent}
22164 * @return {Element}
22165 * The element with inserted normalized content.
22168 function insertContent(el, content) {
22169 return appendContent(emptyEl(el), content);
22173 * Finds a single DOM element matching `selector` within the optional
22174 * `context` of another DOM element (defaulting to `document`).
22176 * @param {string} selector
22177 * A valid CSS selector, which will be passed to `querySelector`.
22179 * @param {Element|String} [context=document]
22180 * A DOM element within which to query. Can also be a selector
22181 * string in which case the first matching element will be used
22182 * as context. If missing (or no element matches selector), falls
22183 * back to `document`.
22185 * @return {Element|null}
22186 * The element that was found or null.
22188 var $ = exports.$ = createQuerier('querySelector');
22191 * Finds a all DOM elements matching `selector` within the optional
22192 * `context` of another DOM element (defaulting to `document`).
22194 * @param {string} selector
22195 * A valid CSS selector, which will be passed to `querySelectorAll`.
22197 * @param {Element|String} [context=document]
22198 * A DOM element within which to query. Can also be a selector
22199 * string in which case the first matching element will be used
22200 * as context. If missing (or no element matches selector), falls
22201 * back to `document`.
22203 * @return {NodeList}
22204 * A element list of elements that were found. Will be empty if none were found.
22207 var $$ = exports.$$ = createQuerier('querySelectorAll');
22209 },{"85":85,"86":86,"88":88,"94":94,"95":95,"98":98}],82:[function(_dereq_,module,exports){
22212 exports.__esModule = true;
22213 exports.fixEvent = fixEvent;
22216 exports.trigger = trigger;
22219 var _dom = _dereq_(81);
22221 var Dom = _interopRequireWildcard(_dom);
22223 var _guid = _dereq_(85);
22225 var Guid = _interopRequireWildcard(_guid);
22227 var _log = _dereq_(86);
22229 var _log2 = _interopRequireDefault(_log);
22231 var _window = _dereq_(95);
22233 var _window2 = _interopRequireDefault(_window);
22235 var _document = _dereq_(94);
22237 var _document2 = _interopRequireDefault(_document);
22239 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
22241 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
22244 * Clean up the listener cache and dispatchers
22246 * @param {Element|Object} elem
22247 * Element to clean up
22249 * @param {string} type
22250 * Type of event to clean up
22252 function _cleanUpEvents(elem, type) {
22253 var data = Dom.getElData(elem);
22255 // Remove the events of a particular type if there are none left
22256 if (data.handlers[type].length === 0) {
22257 delete data.handlers[type];
22258 // data.handlers[type] = null;
22259 // Setting to null was causing an error with data.handlers
22261 // Remove the meta-handler from the element
22262 if (elem.removeEventListener) {
22263 elem.removeEventListener(type, data.dispatcher, false);
22264 } else if (elem.detachEvent) {
22265 elem.detachEvent('on' + type, data.dispatcher);
22269 // Remove the events object if there are no types left
22270 if (Object.getOwnPropertyNames(data.handlers).length <= 0) {
22271 delete data.handlers;
22272 delete data.dispatcher;
22273 delete data.disabled;
22276 // Finally remove the element data if there is no data left
22277 if (Object.getOwnPropertyNames(data).length === 0) {
22278 Dom.removeElData(elem);
22283 * Loops through an array of event types and calls the requested method for each type.
22285 * @param {Function} fn
22286 * The event method we want to use.
22288 * @param {Element|Object} elem
22289 * Element or object to bind listeners to
22291 * @param {string} type
22292 * Type of event to bind to.
22294 * @param {EventTarget~EventListener} callback
22298 * @file events.js. An Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/)
22299 * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible)
22300 * This should work very similarly to jQuery's events, however it's based off the book version which isn't as
22301 * robust as jquery's, so there's probably some differences.
22306 function _handleMultipleEvents(fn, elem, types, callback) {
22307 types.forEach(function (type) {
22308 // Call the event method for each one of the types
22309 fn(elem, type, callback);
22314 * Fix a native event to have standard property values
22316 * @param {Object} event
22317 * Event object to fix.
22320 * Fixed event object.
22322 function fixEvent(event) {
22324 function returnTrue() {
22328 function returnFalse() {
22332 // Test if fixing up is needed
22333 // Used to check if !event.stopPropagation instead of isPropagationStopped
22334 // But native events return true for stopPropagation, but don't have
22335 // other expected methods like isPropagationStopped. Seems to be a problem
22336 // with the Javascript Ninja code. So we're just overriding all events now.
22337 if (!event || !event.isPropagationStopped) {
22339 var old = event || _window2['default'].event;
22342 // Clone the old object so that we can modify the values event = {};
22343 // IE8 Doesn't like when you mess with native event properties
22344 // Firefox returns false for event.hasOwnProperty('type') and other props
22345 // which makes copying more difficult.
22346 // TODO: Probably best to create a whitelist of event props
22347 for (var key in old) {
22348 // Safari 6.0.3 warns you if you try to copy deprecated layerX/Y
22349 // Chrome warns you if you try to copy deprecated keyboardEvent.keyLocation
22350 // and webkitMovementX/Y
22351 if (key !== 'layerX' && key !== 'layerY' && key !== 'keyLocation' && key !== 'webkitMovementX' && key !== 'webkitMovementY') {
22352 // Chrome 32+ warns if you try to copy deprecated returnValue, but
22353 // we still want to if preventDefault isn't supported (IE8).
22354 if (!(key === 'returnValue' && old.preventDefault)) {
22355 event[key] = old[key];
22360 // The event occurred on this element
22361 if (!event.target) {
22362 event.target = event.srcElement || _document2['default'];
22365 // Handle which other element the event is related to
22366 if (!event.relatedTarget) {
22367 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
22370 // Stop the default browser action
22371 event.preventDefault = function () {
22372 if (old.preventDefault) {
22373 old.preventDefault();
22375 event.returnValue = false;
22376 old.returnValue = false;
22377 event.defaultPrevented = true;
22380 event.defaultPrevented = false;
22382 // Stop the event from bubbling
22383 event.stopPropagation = function () {
22384 if (old.stopPropagation) {
22385 old.stopPropagation();
22387 event.cancelBubble = true;
22388 old.cancelBubble = true;
22389 event.isPropagationStopped = returnTrue;
22392 event.isPropagationStopped = returnFalse;
22394 // Stop the event from bubbling and executing other handlers
22395 event.stopImmediatePropagation = function () {
22396 if (old.stopImmediatePropagation) {
22397 old.stopImmediatePropagation();
22399 event.isImmediatePropagationStopped = returnTrue;
22400 event.stopPropagation();
22403 event.isImmediatePropagationStopped = returnFalse;
22405 // Handle mouse position
22406 if (event.clientX !== null && event.clientX !== undefined) {
22407 var doc = _document2['default'].documentElement;
22408 var body = _document2['default'].body;
22410 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
22411 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
22414 // Handle key presses
22415 event.which = event.charCode || event.keyCode;
22417 // Fix button for mouse clicks:
22418 // 0 == left; 1 == middle; 2 == right
22419 if (event.button !== null && event.button !== undefined) {
22421 // The following is disabled because it does not pass videojs-standard
22423 /* eslint-disable */
22424 event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0;
22425 /* eslint-enable */
22430 // Returns fixed-up instance
22435 * Add an event listener to element
22436 * It stores the handler function in a separate cache object
22437 * and adds a generic handler to the element's event,
22438 * along with a unique id (guid) to the element.
22440 * @param {Element|Object} elem
22441 * Element or object to bind listeners to
22443 * @param {string|string[]} type
22444 * Type of event to bind to.
22446 * @param {EventTarget~EventListener} fn
22449 function on(elem, type, fn) {
22450 if (Array.isArray(type)) {
22451 return _handleMultipleEvents(on, elem, type, fn);
22454 var data = Dom.getElData(elem);
22456 // We need a place to store all our handler data
22457 if (!data.handlers) {
22458 data.handlers = {};
22461 if (!data.handlers[type]) {
22462 data.handlers[type] = [];
22466 fn.guid = Guid.newGUID();
22469 data.handlers[type].push(fn);
22471 if (!data.dispatcher) {
22472 data.disabled = false;
22474 data.dispatcher = function (event, hash) {
22476 if (data.disabled) {
22480 event = fixEvent(event);
22482 var handlers = data.handlers[event.type];
22485 // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off.
22486 var handlersCopy = handlers.slice(0);
22488 for (var m = 0, n = handlersCopy.length; m < n; m++) {
22489 if (event.isImmediatePropagationStopped()) {
22493 handlersCopy[m].call(elem, event, hash);
22495 _log2['default'].error(e);
22503 if (data.handlers[type].length === 1) {
22504 if (elem.addEventListener) {
22505 elem.addEventListener(type, data.dispatcher, false);
22506 } else if (elem.attachEvent) {
22507 elem.attachEvent('on' + type, data.dispatcher);
22513 * Removes event listeners from an element
22515 * @param {Element|Object} elem
22516 * Object to remove listeners from.
22518 * @param {string|string[]} [type]
22519 * Type of listener to remove. Don't include to remove all events from element.
22521 * @param {EventTarget~EventListener} [fn]
22522 * Specific listener to remove. Don't include to remove listeners for an event
22525 function off(elem, type, fn) {
22526 // Don't want to add a cache object through getElData if not needed
22527 if (!Dom.hasElData(elem)) {
22531 var data = Dom.getElData(elem);
22533 // If no events exist, nothing to unbind
22534 if (!data.handlers) {
22538 if (Array.isArray(type)) {
22539 return _handleMultipleEvents(off, elem, type, fn);
22542 // Utility function
22543 var removeType = function removeType(t) {
22544 data.handlers[t] = [];
22545 _cleanUpEvents(elem, t);
22548 // Are we removing all bound events?
22550 for (var t in data.handlers) {
22556 var handlers = data.handlers[type];
22558 // If no handlers exist, nothing to unbind
22563 // If no listener was provided, remove all listeners for type
22569 // We're only removing a single handler
22571 for (var n = 0; n < handlers.length; n++) {
22572 if (handlers[n].guid === fn.guid) {
22573 handlers.splice(n--, 1);
22578 _cleanUpEvents(elem, type);
22582 * Trigger an event for an element
22584 * @param {Element|Object} elem
22585 * Element to trigger an event on
22587 * @param {EventTarget~Event|string} event
22588 * A string (the type) or an event object with a type attribute
22590 * @param {Object} [hash]
22591 * data hash to pass along with the event
22593 * @return {boolean|undefined}
22594 * - Returns the opposite of `defaultPrevented` if default was prevented
22595 * - Otherwise returns undefined
22597 function trigger(elem, event, hash) {
22598 // Fetches element data and a reference to the parent (for bubbling).
22599 // Don't want to add a data object to cache for every parent,
22600 // so checking hasElData first.
22601 var elemData = Dom.hasElData(elem) ? Dom.getElData(elem) : {};
22602 var parent = elem.parentNode || elem.ownerDocument;
22603 // type = event.type || event,
22606 // If an event name was passed as a string, creates an event out of it
22607 if (typeof event === 'string') {
22608 event = { type: event, target: elem };
22610 // Normalizes the event properties.
22611 event = fixEvent(event);
22613 // If the passed element has a dispatcher, executes the established handlers.
22614 if (elemData.dispatcher) {
22615 elemData.dispatcher.call(elem, event, hash);
22618 // Unless explicitly stopped or the event does not bubble (e.g. media events)
22619 // recursively calls this function to bubble the event up the DOM.
22620 if (parent && !event.isPropagationStopped() && event.bubbles === true) {
22621 trigger.call(null, parent, event, hash);
22623 // If at the top of the DOM, triggers the default action unless disabled.
22624 } else if (!parent && !event.defaultPrevented) {
22625 var targetData = Dom.getElData(event.target);
22627 // Checks if the target has a default action for this event.
22628 if (event.target[event.type]) {
22629 // Temporarily disables event dispatching on the target as we have already executed the handler.
22630 targetData.disabled = true;
22631 // Executes the default action.
22632 if (typeof event.target[event.type] === 'function') {
22633 event.target[event.type]();
22635 // Re-enables event dispatching.
22636 targetData.disabled = false;
22640 // Inform the triggerer if the default was prevented by returning false
22641 return !event.defaultPrevented;
22645 * Trigger a listener only once for an event
22647 * @param {Element|Object} elem
22648 * Element or object to bind to.
22650 * @param {string|string[]} type
22651 * Name/type of event
22653 * @param {Event~EventListener} fn
22654 * Event Listener function
22656 function one(elem, type, fn) {
22657 if (Array.isArray(type)) {
22658 return _handleMultipleEvents(one, elem, type, fn);
22660 var func = function func() {
22661 off(elem, type, func);
22662 fn.apply(this, arguments);
22665 // copy the guid to the new function so it can removed using the original function's ID
22666 func.guid = fn.guid = fn.guid || Guid.newGUID();
22667 on(elem, type, func);
22670 },{"81":81,"85":85,"86":86,"94":94,"95":95}],83:[function(_dereq_,module,exports){
22673 exports.__esModule = true;
22674 exports.throttle = exports.bind = undefined;
22676 var _guid = _dereq_(85);
22679 * Bind (a.k.a proxy or Context). A simple method for changing the context of a function
22680 * It also stores a unique id on the function so it can be easily removed from events.
22682 * @param {Mixed} context
22683 * The object to bind as scope.
22685 * @param {Function} fn
22686 * The function to be bound to a scope.
22688 * @param {number} [uid]
22689 * An optional unique ID for the function to be set
22691 * @return {Function}
22692 * The new function that will be bound into the context given
22694 var bind = exports.bind = function bind(context, fn, uid) {
22695 // Make sure the function has a unique ID
22697 fn.guid = (0, _guid.newGUID)();
22700 // Create the new function that changes the context
22701 var bound = function bound() {
22702 return fn.apply(context, arguments);
22705 // Allow for the ability to individualize this function
22706 // Needed in the case where multiple objects might share the same prototype
22707 // IF both items add an event listener with the same function, then you try to remove just one
22708 // it will remove both because they both have the same guid.
22709 // when using this, you need to use the bind method when you remove the listener as well.
22710 // currently used in text tracks
22711 bound.guid = uid ? uid + '_' + fn.guid : fn.guid;
22717 * Wraps the given function, `fn`, with a new function that only invokes `fn`
22718 * at most once per every `wait` milliseconds.
22720 * @param {Function} fn
22721 * The function to be throttled.
22723 * @param {Number} wait
22724 * The number of milliseconds by which to throttle.
22726 * @return {Function}
22732 var throttle = exports.throttle = function throttle(fn, wait) {
22733 var last = Date.now();
22735 var throttled = function throttled() {
22736 var now = Date.now();
22738 if (now - last >= wait) {
22739 fn.apply(undefined, arguments);
22747 },{"85":85}],84:[function(_dereq_,module,exports){
22750 exports.__esModule = true;
22752 * @file format-time.js
22753 * @module Format-time
22757 * Format seconds as a time string, H:MM:SS or M:SS. Supplying a guide (in seconds)
22758 * will force a number of leading zeros to cover the length of the guide.
22760 * @param {number} seconds
22761 * Number of seconds to be turned into a string
22763 * @param {number} guide
22764 * Number (in seconds) to model the string after
22767 * Time formatted as H:MM:SS or M:SS
22769 function formatTime(seconds) {
22770 var guide = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : seconds;
22772 seconds = seconds < 0 ? 0 : seconds;
22773 var s = Math.floor(seconds % 60);
22774 var m = Math.floor(seconds / 60 % 60);
22775 var h = Math.floor(seconds / 3600);
22776 var gm = Math.floor(guide / 60 % 60);
22777 var gh = Math.floor(guide / 3600);
22779 // handle invalid times
22780 if (isNaN(seconds) || seconds === Infinity) {
22781 // '-' is false for all relational operators (e.g. <, >=) so this setting
22782 // will add the minimum number of fields specified by the guide
22786 // Check if we need to show hours
22787 h = h > 0 || gh > 0 ? h + ':' : '';
22789 // If hours are showing, we may need to add a leading zero.
22790 // Always show at least one digit of minutes.
22791 m = ((h || gm >= 10) && m < 10 ? '0' + m : m) + ':';
22793 // Check if leading zero is need for seconds
22794 s = s < 10 ? '0' + s : s;
22799 exports['default'] = formatTime;
22801 },{}],85:[function(_dereq_,module,exports){
22804 exports.__esModule = true;
22805 exports.newGUID = newGUID;
22812 * Unique ID for an element or function
22818 * Get a unique auto-incrementing ID by number that has not been returned before.
22823 function newGUID() {
22827 },{}],86:[function(_dereq_,module,exports){
22830 exports.__esModule = true;
22831 exports.logByType = undefined;
22833 var _window = _dereq_(95);
22835 var _window2 = _interopRequireDefault(_window);
22837 var _browser = _dereq_(78);
22839 var _obj = _dereq_(88);
22841 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
22846 * Log messages to the console and history based on the type of message
22848 * @param {string} type
22849 * The name of the console method to use.
22851 * @param {Array} args
22852 * The arguments to be passed to the matching console method.
22854 * @param {boolean} [stringify]
22855 * By default, only old IEs should get console argument stringification,
22856 * but this is exposed as a parameter to facilitate testing.
22862 var logByType = exports.logByType = function logByType(type, args) {
22863 var stringify = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : !!_browser.IE_VERSION && _browser.IE_VERSION < 11;
22866 if (type !== 'log') {
22868 // add the type to the front of the message when it's not "log"
22869 args.unshift(type.toUpperCase() + ':');
22873 log.history.push(args);
22875 // add console prefix after adding to history
22876 args.unshift('VIDEOJS:');
22878 // If there's no console then don't try to output messages, but they will
22879 // still be stored in `log.history`.
22881 // Was setting these once outside of this function, but containing them
22882 // in the function makes it easier to test cases where console doesn't exist
22883 // when the module is executed.
22884 var fn = _window2['default'].console && _window2['default'].console[type];
22886 // Bail out if there's no console.
22891 // IEs previous to 11 log objects uselessly as "[object Object]"; so, JSONify
22892 // objects and arrays for those less-capable browsers.
22894 args = args.map(function (a) {
22895 if ((0, _obj.isObject)(a) || Array.isArray(a)) {
22897 return JSON.stringify(a);
22903 // Cast to string before joining, so we get null and undefined explicitly
22904 // included in output (as we would in a modern console).
22909 // Old IE versions do not allow .apply() for console methods (they are
22910 // reported as objects rather than functions).
22914 fn[Array.isArray(args) ? 'apply' : 'call'](_window2['default'].console, args);
22919 * Log plain debug messages
22921 * @param {Mixed[]} args
22922 * One or more messages or objects that should be logged.
22924 log = function log() {
22925 for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
22926 args[_key] = arguments[_key];
22929 logByType('log', args);
22933 * Keep a history of log messages
22940 * Log error messages
22942 * @param {Mixed[]} args
22943 * One or more messages or objects that should be logged as an error
22945 log.error = function () {
22946 for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
22947 args[_key2] = arguments[_key2];
22950 return logByType('error', args);
22954 * Log warning messages
22956 * @param {Mixed[]} args
22957 * One or more messages or objects that should be logged as a warning.
22959 log.warn = function () {
22960 for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
22961 args[_key3] = arguments[_key3];
22964 return logByType('warn', args);
22967 exports['default'] = log;
22969 },{"78":78,"88":88,"95":95}],87:[function(_dereq_,module,exports){
22972 exports.__esModule = true;
22973 exports['default'] = mergeOptions;
22975 var _obj = _dereq_(88);
22978 * Deep-merge one or more options objects, recursively merging **only** plain
22979 * object properties.
22981 * @param {Object[]} sources
22982 * One or more objects to merge into a new object.
22984 * @returns {Object}
22985 * A new object that is the merged result of all sources.
22987 function mergeOptions() {
22990 for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) {
22991 sources[_key] = arguments[_key];
22994 sources.forEach(function (source) {
22999 (0, _obj.each)(source, function (value, key) {
23000 if (!(0, _obj.isPlain)(value)) {
23001 result[key] = value;
23005 if (!(0, _obj.isPlain)(result[key])) {
23009 result[key] = mergeOptions(result[key], value);
23015 * @file merge-options.js
23016 * @module merge-options
23019 },{"88":88}],88:[function(_dereq_,module,exports){
23022 exports.__esModule = true;
23024 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
23026 exports.each = each;
23027 exports.reduce = reduce;
23028 exports.assign = assign;
23029 exports.isObject = isObject;
23030 exports.isPlain = isPlain;
23037 * @callback obj:EachCallback
23039 * @param {Mixed} value
23040 * The current key for the object that is being iterated over.
23042 * @param {string} key
23043 * The current key-value for object that is being iterated over
23047 * @callback obj:ReduceCallback
23049 * @param {Mixed} accum
23050 * The value that is accumulating over the reduce loop.
23052 * @param {Mixed} value
23053 * The current key for the object that is being iterated over.
23055 * @param {string} key
23056 * The current key-value for object that is being iterated over
23059 * The new accumulated value.
23061 var toString = Object.prototype.toString;
23064 * Array-like iteration for objects.
23066 * @param {Object} object
23067 * The object to iterate over
23069 * @param {obj:EachCallback} fn
23070 * The callback function which is called for each key in the object.
23072 function each(object, fn) {
23073 Object.keys(object).forEach(function (key) {
23074 return fn(object[key], key);
23079 * Array-like reduce for objects.
23081 * @param {Object} object
23082 * The Object that you want to reduce.
23084 * @param {Function} fn
23085 * A callback function which is called for each key in the object. It
23086 * receives the accumulated value and the per-iteration value and key
23089 * @param {Mixed} [initial = 0]
23093 * The final accumulated value.
23095 function reduce(object, fn) {
23096 var initial = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
23098 return Object.keys(object).reduce(function (accum, key) {
23099 return fn(accum, object[key], key);
23104 * Object.assign-style object shallow merge/extend.
23106 * @param {Object} target
23107 * @param {Object} ...sources
23110 function assign(target) {
23111 for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
23112 sources[_key - 1] = arguments[_key];
23115 if (Object.assign) {
23116 return Object.assign.apply(Object, [target].concat(sources));
23119 sources.forEach(function (source) {
23124 each(source, function (value, key) {
23125 target[key] = value;
23133 * Returns whether a value is an object of any kind - including DOM nodes,
23134 * arrays, regular expressions, etc. Not functions, though.
23136 * This avoids the gotcha where using `typeof` on a `null` value
23137 * results in `'object'`.
23139 * @param {Object} value
23140 * @return {Boolean}
23142 function isObject(value) {
23143 return !!value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object';
23147 * Returns whether an object appears to be a "plain" object - that is, a
23148 * direct instance of `Object`.
23150 * @param {Object} value
23151 * @return {Boolean}
23153 function isPlain(value) {
23154 return isObject(value) && toString.call(value) === '[object Object]' && value.constructor === Object;
23157 },{}],89:[function(_dereq_,module,exports){
23160 exports.__esModule = true;
23161 exports.setTextContent = exports.createStyleElement = undefined;
23163 var _document = _dereq_(94);
23165 var _document2 = _interopRequireDefault(_document);
23167 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
23170 * Create a DOM style element given a className for it.
23172 * @param {string} className
23173 * The className to add to the created style element.
23175 * @return {Element}
23176 * The element that was created.
23178 var createStyleElement = exports.createStyleElement = function createStyleElement(className) {
23179 var style = _document2['default'].createElement('style');
23181 style.className = className;
23187 * Add text to a DOM element.
23189 * @param {Element} el
23190 * The Element to add text content to.
23192 * @param {string} content
23193 * The text to add to the element.
23196 * @file stylesheet.js
23197 * @module stylesheet
23199 var setTextContent = exports.setTextContent = function setTextContent(el, content) {
23200 if (el.styleSheet) {
23201 el.styleSheet.cssText = content;
23203 el.textContent = content;
23207 },{"94":94}],90:[function(_dereq_,module,exports){
23210 exports.__esModule = true;
23211 exports.createTimeRange = undefined;
23212 exports.createTimeRanges = createTimeRanges;
23214 var _log = _dereq_(86);
23216 var _log2 = _interopRequireDefault(_log);
23218 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
23221 * Returns the time for the specified index at the start or end
23222 * of a TimeRange object.
23224 * @function time-ranges:indexFunction
23226 * @param {number} [index=0]
23227 * The range number to return the time for.
23230 * The time that offset at the specified index.
23232 * @deprecated index must be set to a value, in the future this will throw an error.
23236 * An object that contains ranges of time for various reasons.
23238 * @typedef {Object} TimeRange
23240 * @property {number} length
23241 * The number of time ranges represented by this Object
23243 * @property {time-ranges:indexFunction} start
23244 * Returns the time offset at which a specified time range begins.
23246 * @property {time-ranges:indexFunction} end
23247 * Returns the time offset at which a specified time range begins.
23249 * @see https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges
23253 * Check if any of the time ranges are over the maximum index.
23255 * @param {string} fnName
23256 * The function name to use for logging
23258 * @param {number} index
23259 * The index to check
23261 * @param {number} maxIndex
23262 * The maximum possible index
23264 * @throws {Error} if the timeRanges provided are over the maxIndex
23266 function rangeCheck(fnName, index, maxIndex) {
23267 if (index < 0 || index > maxIndex) {
23268 throw new Error('Failed to execute \'' + fnName + '\' on \'TimeRanges\': The index provided (' + index + ') is greater than or equal to the maximum bound (' + maxIndex + ').');
23273 * Check if any of the time ranges are over the maximum index.
23275 * @param {string} fnName
23276 * The function name to use for logging
23278 * @param {string} valueIndex
23279 * The proprety that should be used to get the time. should be 'start' or 'end'
23281 * @param {Array} ranges
23282 * An array of time ranges
23284 * @param {Array} [rangeIndex=0]
23285 * The index to start the search at
23288 * The time that offset at the specified index.
23291 * @deprecated rangeIndex must be set to a value, in the future this will throw an error.
23292 * @throws {Error} if rangeIndex is more than the length of ranges
23295 * @file time-ranges.js
23296 * @module time-ranges
23298 function getRange(fnName, valueIndex, ranges, rangeIndex) {
23299 if (rangeIndex === undefined) {
23300 _log2['default'].warn('DEPRECATED: Function \'' + fnName + '\' on \'TimeRanges\' called without an index argument.');
23303 rangeCheck(fnName, rangeIndex, ranges.length - 1);
23304 return ranges[rangeIndex][valueIndex];
23308 * Create a time range object givent ranges of time.
23310 * @param {Array} [ranges]
23311 * An array of time ranges.
23313 function createTimeRangesObj(ranges) {
23314 if (ranges === undefined || ranges.length === 0) {
23317 start: function start() {
23318 throw new Error('This TimeRanges object is empty');
23320 end: function end() {
23321 throw new Error('This TimeRanges object is empty');
23326 length: ranges.length,
23327 start: getRange.bind(null, 'start', 0, ranges),
23328 end: getRange.bind(null, 'end', 1, ranges)
23333 * Should create a fake `TimeRange` object which mimics an HTML5 time range instance.
23335 * @param {number|Array} start
23336 * The start of a single range or an array of ranges
23338 * @param {number} end
23339 * The end of a single range.
23343 function createTimeRanges(start, end) {
23344 if (Array.isArray(start)) {
23345 return createTimeRangesObj(start);
23346 } else if (start === undefined || end === undefined) {
23347 return createTimeRangesObj();
23349 return createTimeRangesObj([[start, end]]);
23352 exports.createTimeRange = createTimeRanges;
23354 },{"86":86}],91:[function(_dereq_,module,exports){
23357 exports.__esModule = true;
23359 * @file to-title-case.js
23360 * @module to-title-case
23364 * Uppercase the first letter of a string.
23366 * @param {string} string
23367 * String to be uppercased
23370 * The string with an uppercased first letter
23372 function toTitleCase(string) {
23373 if (typeof string !== 'string') {
23377 return string.charAt(0).toUpperCase() + string.slice(1);
23380 exports['default'] = toTitleCase;
23382 },{}],92:[function(_dereq_,module,exports){
23385 exports.__esModule = true;
23386 exports.isCrossOrigin = exports.getFileExtension = exports.getAbsoluteURL = exports.parseUrl = undefined;
23388 var _document = _dereq_(94);
23390 var _document2 = _interopRequireDefault(_document);
23392 var _window = _dereq_(95);
23394 var _window2 = _interopRequireDefault(_window);
23396 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
23399 * @typedef {Object} url:URLObject
23401 * @property {string} protocol
23402 * The protocol of the url that was parsed.
23404 * @property {string} hostname
23405 * The hostname of the url that was parsed.
23407 * @property {string} port
23408 * The port of the url that was parsed.
23410 * @property {string} pathname
23411 * The pathname of the url that was parsed.
23413 * @property {string} search
23414 * The search query of the url that was parsed.
23416 * @property {string} hash
23417 * The hash of the url that was parsed.
23419 * @property {string} host
23420 * The host of the url that was parsed.
23424 * Resolve and parse the elements of a URL.
23426 * @param {String} url
23429 * @return {url:URLObject}
23430 * An object of url details
23436 var parseUrl = exports.parseUrl = function parseUrl(url) {
23437 var props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host'];
23439 // add the url to an anchor and let the browser parse the URL
23440 var a = _document2['default'].createElement('a');
23444 // IE8 (and 9?) Fix
23445 // ie8 doesn't parse the URL correctly until the anchor is actually
23446 // added to the body, and an innerHTML is needed to trigger the parsing
23447 var addToBody = a.host === '' && a.protocol !== 'file:';
23451 div = _document2['default'].createElement('div');
23452 div.innerHTML = '<a href="' + url + '"></a>';
23453 a = div.firstChild;
23454 // prevent the div from affecting layout
23455 div.setAttribute('style', 'display:none; position:absolute;');
23456 _document2['default'].body.appendChild(div);
23459 // Copy the specific URL properties to a new object
23460 // This is also needed for IE8 because the anchor loses its
23461 // properties when it's removed from the dom
23464 for (var i = 0; i < props.length; i++) {
23465 details[props[i]] = a[props[i]];
23468 // IE9 adds the port to the host property unlike everyone else. If
23469 // a port identifier is added for standard ports, strip it.
23470 if (details.protocol === 'http:') {
23471 details.host = details.host.replace(/:80$/, '');
23474 if (details.protocol === 'https:') {
23475 details.host = details.host.replace(/:443$/, '');
23479 _document2['default'].body.removeChild(div);
23486 * Get absolute version of relative URL. Used to tell flash correct URL.
23489 * @param {string} url
23490 * URL to make absolute
23495 * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
23497 var getAbsoluteURL = exports.getAbsoluteURL = function getAbsoluteURL(url) {
23498 // Check if absolute URL
23499 if (!url.match(/^https?:\/\//)) {
23500 // Convert to absolute URL. Flash hosted off-site needs an absolute URL.
23501 var div = _document2['default'].createElement('div');
23503 div.innerHTML = '<a href="' + url + '">x</a>';
23504 url = div.firstChild.href;
23511 * Returns the extension of the passed file name. It will return an empty string
23512 * if passed an invalid path.
23514 * @param {string} path
23515 * The fileName path like '/path/to/file.mp4'
23517 * @returns {string}
23518 * The extension in lower case or an empty string if no
23519 * extension could be found.
23521 var getFileExtension = exports.getFileExtension = function getFileExtension(path) {
23522 if (typeof path === 'string') {
23523 var splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
23524 var pathParts = splitPathRe.exec(path);
23527 return pathParts.pop().toLowerCase();
23535 * Returns whether the url passed is a cross domain request or not.
23537 * @param {string} url
23538 * The url to check.
23540 * @return {boolean}
23541 * Whether it is a cross domain request or not.
23543 var isCrossOrigin = exports.isCrossOrigin = function isCrossOrigin(url) {
23544 var winLoc = _window2['default'].location;
23545 var urlInfo = parseUrl(url);
23547 // IE8 protocol relative urls will return ':' for protocol
23548 var srcProtocol = urlInfo.protocol === ':' ? winLoc.protocol : urlInfo.protocol;
23550 // Check if url is for another domain/origin
23551 // IE8 doesn't know location.origin, so we won't rely on it here
23552 var crossOrigin = srcProtocol + urlInfo.host !== winLoc.protocol + winLoc.host;
23554 return crossOrigin;
23557 },{"94":94,"95":95}],93:[function(_dereq_,module,exports){
23560 exports.__esModule = true;
23562 var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
23567 /* global define */
23569 // Include the built-in techs
23572 var _window = _dereq_(95);
23574 var _window2 = _interopRequireDefault(_window);
23576 var _document = _dereq_(94);
23578 var _document2 = _interopRequireDefault(_document);
23580 var _setup = _dereq_(56);
23582 var setup = _interopRequireWildcard(_setup);
23584 var _stylesheet = _dereq_(89);
23586 var stylesheet = _interopRequireWildcard(_stylesheet);
23588 var _component = _dereq_(5);
23590 var _component2 = _interopRequireDefault(_component);
23592 var _eventTarget = _dereq_(42);
23594 var _eventTarget2 = _interopRequireDefault(_eventTarget);
23596 var _events = _dereq_(82);
23598 var Events = _interopRequireWildcard(_events);
23600 var _player = _dereq_(51);
23602 var _player2 = _interopRequireDefault(_player);
23604 var _plugins = _dereq_(52);
23606 var _plugins2 = _interopRequireDefault(_plugins);
23608 var _mergeOptions2 = _dereq_(87);
23610 var _mergeOptions3 = _interopRequireDefault(_mergeOptions2);
23612 var _fn = _dereq_(83);
23614 var Fn = _interopRequireWildcard(_fn);
23616 var _textTrack = _dereq_(72);
23618 var _textTrack2 = _interopRequireDefault(_textTrack);
23620 var _audioTrack = _dereq_(64);
23622 var _audioTrack2 = _interopRequireDefault(_audioTrack);
23624 var _videoTrack = _dereq_(77);
23626 var _videoTrack2 = _interopRequireDefault(_videoTrack);
23628 var _timeRanges = _dereq_(90);
23630 var _formatTime = _dereq_(84);
23632 var _formatTime2 = _interopRequireDefault(_formatTime);
23634 var _log = _dereq_(86);
23636 var _log2 = _interopRequireDefault(_log);
23638 var _dom = _dereq_(81);
23640 var Dom = _interopRequireWildcard(_dom);
23642 var _browser = _dereq_(78);
23644 var browser = _interopRequireWildcard(_browser);
23646 var _url = _dereq_(92);
23648 var Url = _interopRequireWildcard(_url);
23650 var _obj = _dereq_(88);
23652 var _computedStyle = _dereq_(80);
23654 var _computedStyle2 = _interopRequireDefault(_computedStyle);
23656 var _extend = _dereq_(43);
23658 var _extend2 = _interopRequireDefault(_extend);
23660 var _xhr = _dereq_(99);
23662 var _xhr2 = _interopRequireDefault(_xhr);
23664 var _tech = _dereq_(62);
23666 var _tech2 = _interopRequireDefault(_tech);
23668 function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
23670 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
23672 // HTML5 Element Shim for IE8
23673 if (typeof HTMLVideoElement === 'undefined' && Dom.isReal()) {
23674 _document2['default'].createElement('video');
23675 _document2['default'].createElement('audio');
23676 _document2['default'].createElement('track');
23680 * Doubles as the main function for users to create a player instance and also
23681 * the main library object.
23682 * The `videojs` function can be used to initialize or retrieve a player.
23684 * @param {string|Element} id
23685 * Video element or video element ID
23687 * @param {Object} [options]
23688 * Optional options object for config/settings
23690 * @param {Component~ReadyCallback} [ready]
23691 * Optional ready callback
23694 * A player instance
23698 function videojs(id, options, ready) {
23701 // Allow for element or ID to be passed in
23703 if (typeof id === 'string') {
23705 // Adjust for jQuery ID syntax
23706 if (id.indexOf('#') === 0) {
23710 // If a player instance has already been created for this ID return it.
23711 if (videojs.getPlayers()[id]) {
23713 // If options or ready function are passed, warn
23715 _log2['default'].warn('Player "' + id + '" is already initialised. Options will not be applied.');
23719 videojs.getPlayers()[id].ready(ready);
23722 return videojs.getPlayers()[id];
23725 // Otherwise get element for ID
23726 tag = Dom.getEl(id);
23728 // ID is a media element
23733 // Check for a usable element
23734 // re: nodeName, could be a box div also
23735 if (!tag || !tag.nodeName) {
23736 throw new TypeError('The element or ID supplied is not valid. (videojs)');
23739 // Element may have a player attr referring to an already created player instance.
23740 // If so return that otherwise set up a new player below
23741 if (tag.player || _player2['default'].players[tag.playerId]) {
23742 return tag.player || _player2['default'].players[tag.playerId];
23745 options = options || {};
23747 videojs.hooks('beforesetup').forEach(function (hookFunction) {
23748 var opts = hookFunction(tag, (0, _mergeOptions3['default'])(options));
23750 if (!(0, _obj.isObject)(opts) || Array.isArray(opts)) {
23751 _log2['default'].error('please return an object in beforesetup hooks');
23755 options = (0, _mergeOptions3['default'])(options, opts);
23758 var PlayerComponent = _component2['default'].getComponent('Player');
23759 // If not, set up a new player
23760 var player = new PlayerComponent(tag, options, ready);
23762 videojs.hooks('setup').forEach(function (hookFunction) {
23763 return hookFunction(player);
23770 * An Object that contains lifecycle hooks as keys which point to an array
23771 * of functions that are run when a lifecycle is triggered
23773 videojs.hooks_ = {};
23776 * Get a list of hooks for a specific lifecycle
23778 * @param {string} type
23779 * the lifecycle to get hooks from
23781 * @param {Function} [fn]
23782 * Optionally add a hook to the lifecycle that your are getting.
23785 * an array of hooks, or an empty array if there are none.
23787 videojs.hooks = function (type, fn) {
23788 videojs.hooks_[type] = videojs.hooks_[type] || [];
23790 videojs.hooks_[type] = videojs.hooks_[type].concat(fn);
23792 return videojs.hooks_[type];
23796 * Add a function hook to a specific videojs lifecycle.
23798 * @param {string} type
23799 * the lifecycle to hook the function to.
23801 * @param {Function|Function[]}
23802 * The function or array of functions to attach.
23804 videojs.hook = function (type, fn) {
23805 videojs.hooks(type, fn);
23809 * Remove a hook from a specific videojs lifecycle.
23811 * @param {string} type
23812 * the lifecycle that the function hooked to
23814 * @param {Function} fn
23815 * The hooked function to remove
23817 * @return {boolean}
23818 * The function that was removed or undef
23820 videojs.removeHook = function (type, fn) {
23821 var index = videojs.hooks(type).indexOf(fn);
23827 videojs.hooks_[type] = videojs.hooks_[type].slice();
23828 videojs.hooks_[type].splice(index, 1);
23833 // Add default styles
23834 if (_window2['default'].VIDEOJS_NO_DYNAMIC_STYLE !== true && Dom.isReal()) {
23835 var style = Dom.$('.vjs-styles-defaults');
23838 style = stylesheet.createStyleElement('vjs-styles-defaults');
23839 var head = Dom.$('head');
23842 head.insertBefore(style, head.firstChild);
23844 stylesheet.setTextContent(style, '\n .video-js {\n width: 300px;\n height: 150px;\n }\n\n .vjs-fluid {\n padding-top: 56.25%\n }\n ');
23848 // Run Auto-load players
23849 // You have to wait at least once in case this script is loaded after your
23850 // video in the DOM (weird behavior only with minified version)
23851 setup.autoSetupTimeout(1, videojs);
23854 * Current software version. Follows semver.
23858 videojs.VERSION = '5.15.1';
23861 * The global options object. These are the settings that take effect
23862 * if no overrides are specified when the player is created.
23866 videojs.options = _player2['default'].prototype.options_;
23869 * Get an object with the currently created players, keyed by player ID
23872 * The created players
23874 videojs.getPlayers = function () {
23875 return _player2['default'].players;
23879 * Expose players object.
23881 * @memberOf videojs
23882 * @property {Object} players
23884 videojs.players = _player2['default'].players;
23887 * Get a component class object by name
23889 * @borrows Component.getComponent as videojs.getComponent
23891 videojs.getComponent = _component2['default'].getComponent;
23894 * Register a component so it can referred to by name. Used when adding to other
23895 * components, either through addChild `component.addChild('myComponent')` or through
23896 * default children options `{ children: ['myComponent'] }`.
23898 * > NOTE: You could also just initialize the component before adding.
23899 * `component.addChild(new MyComponent());`
23901 * @param {string} name
23902 * The class name of the component
23904 * @param {Component} comp
23905 * The component class
23907 * @return {Component}
23908 * The newly registered component
23910 videojs.registerComponent = function (name, comp) {
23911 if (_tech2['default'].isTech(comp)) {
23912 _log2['default'].warn('The ' + name + ' tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)');
23915 _component2['default'].registerComponent.call(_component2['default'], name, comp);
23919 * Get a Tech class object by name
23921 * @borrows Tech.getTech as videojs.getTech
23923 videojs.getTech = _tech2['default'].getTech;
23926 * Register a Tech so it can referred to by name.
23927 * This is used in the tech order for the player.
23929 * @borrows Tech.registerTech as videojs.registerTech
23931 videojs.registerTech = _tech2['default'].registerTech;
23934 * A suite of browser and device tests from {@link browser}.
23939 videojs.browser = browser;
23942 * Whether or not the browser supports touch events. Included for backward
23943 * compatibility with 4.x, but deprecated. Use `videojs.browser.TOUCH_ENABLED`
23944 * instead going forward.
23946 * @deprecated since version 5.0
23949 videojs.TOUCH_ENABLED = browser.TOUCH_ENABLED;
23952 * Subclass an existing class
23953 * Mimics ES6 subclassing with the `extend` keyword
23955 * @borrows extend:extendFn as videojs.extend
23957 videojs.extend = _extend2['default'];
23960 * Merge two options objects recursively
23961 * Performs a deep merge like lodash.merge but **only merges plain objects**
23962 * (not arrays, elements, anything else)
23963 * Other values will be copied directly from the second object.
23965 * @borrows merge-options:mergeOptions as videojs.mergeOptions
23967 videojs.mergeOptions = _mergeOptions3['default'];
23970 * Change the context (this) of a function
23972 * > NOTE: as of v5.0 we require an ES5 shim, so you should use the native
23973 * `function() {}.bind(newContext);` instead of this.
23975 * @borrows fn:bind as videojs.bind
23977 videojs.bind = Fn.bind;
23980 * Create a Video.js player plugin.
23981 * Plugins are only initialized when options for the plugin are included
23982 * in the player options, or the plugin function on the player instance is
23985 * @borrows plugin:plugin as videojs.plugin
23987 videojs.plugin = _plugins2['default'];
23990 * Adding languages so that they're available to all players.
23991 * Example: `videojs.addLanguage('es', { 'Hello': 'Hola' });`
23993 * @param {string} code
23994 * The language code or dictionary property
23996 * @param {Object} data
23997 * The data values to be translated
24000 * The resulting language dictionary object
24002 videojs.addLanguage = function (code, data) {
24005 code = ('' + code).toLowerCase();
24007 videojs.options.languages = (0, _mergeOptions3['default'])(videojs.options.languages, (_mergeOptions = {}, _mergeOptions[code] = data, _mergeOptions));
24009 return videojs.options.languages[code];
24015 * @borrows log:log as videojs.log
24017 videojs.log = _log2['default'];
24020 * Creates an emulated TimeRange object.
24022 * @borrows time-ranges:createTimeRanges as videojs.createTimeRange
24025 * @borrows time-ranges:createTimeRanges as videojs.createTimeRanges
24027 videojs.createTimeRange = videojs.createTimeRanges = _timeRanges.createTimeRanges;
24030 * Format seconds as a time string, H:MM:SS or M:SS
24031 * Supplying a guide (in seconds) will force a number of leading zeros
24032 * to cover the length of the guide
24034 * @borrows format-time:formatTime as videojs.formatTime
24036 videojs.formatTime = _formatTime2['default'];
24039 * Resolve and parse the elements of a URL
24041 * @borrows url:parseUrl as videojs.parseUrl
24043 videojs.parseUrl = Url.parseUrl;
24046 * Returns whether the url passed is a cross domain request or not.
24048 * @borrows url:isCrossOrigin as videojs.isCrossOrigin
24050 videojs.isCrossOrigin = Url.isCrossOrigin;
24053 * Event target class.
24055 * @borrows EventTarget as videojs.EventTarget
24057 videojs.EventTarget = _eventTarget2['default'];
24060 * Add an event listener to element
24061 * It stores the handler function in a separate cache object
24062 * and adds a generic handler to the element's event,
24063 * along with a unique id (guid) to the element.
24065 * @borrows events:on as videojs.on
24067 videojs.on = Events.on;
24070 * Trigger a listener only once for an event
24072 * @borrows events:one as videojs.one
24074 videojs.one = Events.one;
24077 * Removes event listeners from an element
24079 * @borrows events:off as videojs.off
24081 videojs.off = Events.off;
24084 * Trigger an event for an element
24086 * @borrows events:trigger as videojs.trigger
24088 videojs.trigger = Events.trigger;
24091 * A cross-browser XMLHttpRequest wrapper. Here's a simple example:
24093 * @param {Object} options
24094 * settings for the request.
24096 * @return {XMLHttpRequest|XDomainRequest}
24097 * The request object.
24099 * @see https://github.com/Raynos/xhr
24101 videojs.xhr = _xhr2['default'];
24106 * @borrows TextTrack as videojs.TextTrack
24108 videojs.TextTrack = _textTrack2['default'];
24111 * export the AudioTrack class so that source handlers can create
24112 * AudioTracks and then add them to the players AudioTrackList
24114 * @borrows AudioTrack as videojs.AudioTrack
24116 videojs.AudioTrack = _audioTrack2['default'];
24119 * export the VideoTrack class so that source handlers can create
24120 * VideoTracks and then add them to the players VideoTrackList
24122 * @borrows VideoTrack as videojs.VideoTrack
24124 videojs.VideoTrack = _videoTrack2['default'];
24127 * Determines, via duck typing, whether or not a value is a DOM element.
24129 * @borrows dom:isEl as videojs.isEl
24131 videojs.isEl = Dom.isEl;
24134 * Determines, via duck typing, whether or not a value is a text node.
24136 * @borrows dom:isTextNode as videojs.isTextNode
24138 videojs.isTextNode = Dom.isTextNode;
24141 * Creates an element and applies properties.
24143 * @borrows dom:createEl as videojs.createEl
24145 videojs.createEl = Dom.createEl;
24148 * Check if an element has a CSS class
24150 * @borrows dom:hasElClass as videojs.hasClass
24152 videojs.hasClass = Dom.hasElClass;
24155 * Add a CSS class name to an element
24157 * @borrows dom:addElClass as videojs.addClass
24159 videojs.addClass = Dom.addElClass;
24162 * Remove a CSS class name from an element
24164 * @borrows dom:removeElClass as videojs.removeClass
24166 videojs.removeClass = Dom.removeElClass;
24169 * Adds or removes a CSS class name on an element depending on an optional
24170 * condition or the presence/absence of the class name.
24172 * @borrows dom:toggleElClass as videojs.toggleClass
24174 videojs.toggleClass = Dom.toggleElClass;
24177 * Apply attributes to an HTML element.
24179 * @borrows dom:setElAttributes as videojs.setAttribute
24181 videojs.setAttributes = Dom.setElAttributes;
24184 * Get an element's attribute values, as defined on the HTML tag
24185 * Attributes are not the same as properties. They're defined on the tag
24186 * or with setAttribute (which shouldn't be used with HTML)
24187 * This will return true or false for boolean attributes.
24189 * @borrows dom:getElAttributes as videojs.getAttributes
24191 videojs.getAttributes = Dom.getElAttributes;
24194 * Empties the contents of an element.
24196 * @borrows dom:emptyEl as videojs.emptyEl
24198 videojs.emptyEl = Dom.emptyEl;
24201 * Normalizes and appends content to an element.
24203 * The content for an element can be passed in multiple types and
24204 * combinations, whose behavior is as follows:
24207 * Normalized into a text node.
24209 * - Element, TextNode
24213 * A one-dimensional array of strings, elements, nodes, or functions (which
24214 * return single strings, elements, or nodes).
24217 * If the sole argument, is expected to produce a string, element,
24220 * @borrows dom:appendContents as videojs.appendContet
24222 videojs.appendContent = Dom.appendContent;
24225 * Normalizes and inserts content into an element; this is identical to
24226 * `appendContent()`, except it empties the element first.
24228 * The content for an element can be passed in multiple types and
24229 * combinations, whose behavior is as follows:
24232 * Normalized into a text node.
24234 * - Element, TextNode
24238 * A one-dimensional array of strings, elements, nodes, or functions (which
24239 * return single strings, elements, or nodes).
24242 * If the sole argument, is expected to produce a string, element,
24245 * @borrows dom:insertContent as videojs.insertContent
24247 videojs.insertContent = Dom.insertContent;
24250 * A safe getComputedStyle with an IE8 fallback.
24252 * This is because in Firefox, if the player is loaded in an iframe with `display:none`,
24253 * then `getComputedStyle` returns `null`, so, we do a null-check to make sure
24254 * that the player doesn't break in these cases.
24255 * See https://bugzilla.mozilla.org/show_bug.cgi?id=548397 for more details.
24257 * @borrows computed-style:computedStyle as videojs.computedStyle
24259 videojs.computedStyle = _computedStyle2['default'];
24262 * Custom Universal Module Definition (UMD)
24264 * Video.js will never be a non-browser lib so we can simplify UMD a bunch and
24265 * still support requirejs and browserify. This also needs to be closure
24266 * compiler compatible, so string keys are used.
24268 if (typeof define === 'function' && define.amd) {
24269 define('videojs', [], function () {
24273 // checking that module is an object too because of umdjs/umd#35
24274 } else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && (typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object') {
24275 module.exports = videojs;
24278 exports['default'] = videojs;
24280 },{"42":42,"43":43,"5":5,"51":51,"52":52,"56":56,"62":62,"64":64,"72":72,"77":77,"78":78,"80":80,"81":81,"82":82,"83":83,"84":84,"86":86,"87":87,"88":88,"89":89,"90":90,"92":92,"94":94,"95":95,"99":99}],94:[function(_dereq_,module,exports){
24281 (function (global){
24282 var topLevel = typeof global !== 'undefined' ? global :
24283 typeof window !== 'undefined' ? window : {}
24284 var minDoc = _dereq_(96);
24286 if (typeof document !== 'undefined') {
24287 module.exports = document;
24289 var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
24292 doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
24295 module.exports = doccy;
24298 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
24299 },{"96":96}],95:[function(_dereq_,module,exports){
24300 (function (global){
24301 if (typeof window !== "undefined") {
24302 module.exports = window;
24303 } else if (typeof global !== "undefined") {
24304 module.exports = global;
24305 } else if (typeof self !== "undefined"){
24306 module.exports = self;
24308 module.exports = {};
24311 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
24312 },{}],96:[function(_dereq_,module,exports){
24314 },{}],97:[function(_dereq_,module,exports){
24315 module.exports = SafeParseTuple
24317 function SafeParseTuple(obj, reviver) {
24322 json = JSON.parse(obj, reviver)
24327 return [error, json]
24330 },{}],98:[function(_dereq_,module,exports){
24331 function clean (s) {
24332 return s.replace(/\n\r?\s*/g, '')
24336 module.exports = function tsml (sa) {
24340 for (; i < arguments.length; i++)
24341 s += clean(sa[i]) + (arguments[i + 1] || '')
24345 },{}],99:[function(_dereq_,module,exports){
24347 var window = _dereq_(95)
24348 var isFunction = _dereq_(100)
24349 var parseHeaders = _dereq_(103)
24350 var xtend = _dereq_(104)
24352 module.exports = createXHR
24353 createXHR.XMLHttpRequest = window.XMLHttpRequest || noop
24354 createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest
24356 forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {
24357 createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {
24358 options = initParams(uri, options, callback)
24359 options.method = method.toUpperCase()
24360 return _createXHR(options)
24364 function forEachArray(array, iterator) {
24365 for (var i = 0; i < array.length; i++) {
24370 function isEmpty(obj){
24372 if(obj.hasOwnProperty(i)) return false
24377 function initParams(uri, options, callback) {
24380 if (isFunction(options)) {
24382 if (typeof uri === "string") {
24386 params = xtend(options, {uri: uri})
24389 params.callback = callback
24393 function createXHR(uri, options, callback) {
24394 options = initParams(uri, options, callback)
24395 return _createXHR(options)
24398 function _createXHR(options) {
24399 if(typeof options.callback === "undefined"){
24400 throw new Error("callback argument missing")
24404 var callback = function cbOnce(err, response, body){
24407 options.callback(err, response, body)
24411 function readystatechange() {
24412 if (xhr.readyState === 4) {
24417 function getBody() {
24418 // Chrome with requestType=blob throws errors around when even testing access to responseText
24419 var body = undefined
24421 if (xhr.response) {
24422 body = xhr.response
24424 body = xhr.responseText || getXml(xhr)
24429 body = JSON.parse(body)
24436 var failureResponse = {
24445 function errorFunc(evt) {
24446 clearTimeout(timeoutTimer)
24447 if(!(evt instanceof Error)){
24448 evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )
24451 return callback(evt, failureResponse)
24454 // will load the data & process the response in a special response object
24455 function loadFunc() {
24456 if (aborted) return
24458 clearTimeout(timeoutTimer)
24459 if(options.useXDR && xhr.status===undefined) {
24460 //IE8 CORS GET successful response doesn't have a status field, but body is fine
24463 status = (xhr.status === 1223 ? 204 : xhr.status)
24465 var response = failureResponse
24471 statusCode: status,
24477 if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE
24478 response.headers = parseHeaders(xhr.getAllResponseHeaders())
24481 err = new Error("Internal XMLHttpRequest Error")
24483 return callback(err, response, response.body)
24486 var xhr = options.xhr || null
24489 if (options.cors || options.useXDR) {
24490 xhr = new createXHR.XDomainRequest()
24492 xhr = new createXHR.XMLHttpRequest()
24498 var uri = xhr.url = options.uri || options.url
24499 var method = xhr.method = options.method || "GET"
24500 var body = options.body || options.data || null
24501 var headers = xhr.headers = options.headers || {}
24502 var sync = !!options.sync
24506 if ("json" in options) {
24508 headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user
24509 if (method !== "GET" && method !== "HEAD") {
24510 headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user
24511 body = JSON.stringify(options.json)
24515 xhr.onreadystatechange = readystatechange
24516 xhr.onload = loadFunc
24517 xhr.onerror = errorFunc
24518 // IE9 must have onprogress be set to a unique function.
24519 xhr.onprogress = function () {
24522 xhr.ontimeout = errorFunc
24523 xhr.open(method, uri, !sync, options.username, options.password)
24524 //has to be after open
24526 xhr.withCredentials = !!options.withCredentials
24528 // Cannot set timeout with sync request
24529 // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
24530 // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
24531 if (!sync && options.timeout > 0 ) {
24532 timeoutTimer = setTimeout(function(){
24533 aborted=true//IE9 may still call readystatechange
24534 xhr.abort("timeout")
24535 var e = new Error("XMLHttpRequest timeout")
24536 e.code = "ETIMEDOUT"
24538 }, options.timeout )
24541 if (xhr.setRequestHeader) {
24542 for(key in headers){
24543 if(headers.hasOwnProperty(key)){
24544 xhr.setRequestHeader(key, headers[key])
24547 } else if (options.headers && !isEmpty(options.headers)) {
24548 throw new Error("Headers cannot be set on an XDomainRequest object")
24551 if ("responseType" in options) {
24552 xhr.responseType = options.responseType
24555 if ("beforeSend" in options &&
24556 typeof options.beforeSend === "function"
24558 options.beforeSend(xhr)
24568 function getXml(xhr) {
24569 if (xhr.responseType === "document") {
24570 return xhr.responseXML
24572 var firefoxBugTakenEffect = xhr.status === 204 && xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"
24573 if (xhr.responseType === "" && !firefoxBugTakenEffect) {
24574 return xhr.responseXML
24582 },{"100":100,"103":103,"104":104,"95":95}],100:[function(_dereq_,module,exports){
24583 module.exports = isFunction
24585 var toString = Object.prototype.toString
24587 function isFunction (fn) {
24588 var string = toString.call(fn)
24589 return string === '[object Function]' ||
24590 (typeof fn === 'function' && string !== '[object RegExp]') ||
24591 (typeof window !== 'undefined' &&
24593 (fn === window.setTimeout ||
24594 fn === window.alert ||
24595 fn === window.confirm ||
24596 fn === window.prompt))
24599 },{}],101:[function(_dereq_,module,exports){
24600 var isFunction = _dereq_(100)
24602 module.exports = forEach
24604 var toString = Object.prototype.toString
24605 var hasOwnProperty = Object.prototype.hasOwnProperty
24607 function forEach(list, iterator, context) {
24608 if (!isFunction(iterator)) {
24609 throw new TypeError('iterator must be a function')
24612 if (arguments.length < 3) {
24616 if (toString.call(list) === '[object Array]')
24617 forEachArray(list, iterator, context)
24618 else if (typeof list === 'string')
24619 forEachString(list, iterator, context)
24621 forEachObject(list, iterator, context)
24624 function forEachArray(array, iterator, context) {
24625 for (var i = 0, len = array.length; i < len; i++) {
24626 if (hasOwnProperty.call(array, i)) {
24627 iterator.call(context, array[i], i, array)
24632 function forEachString(string, iterator, context) {
24633 for (var i = 0, len = string.length; i < len; i++) {
24634 // no such thing as a sparse string.
24635 iterator.call(context, string.charAt(i), i, string)
24639 function forEachObject(object, iterator, context) {
24640 for (var k in object) {
24641 if (hasOwnProperty.call(object, k)) {
24642 iterator.call(context, object[k], k, object)
24647 },{"100":100}],102:[function(_dereq_,module,exports){
24649 exports = module.exports = trim;
24651 function trim(str){
24652 return str.replace(/^\s*|\s*$/g, '');
24655 exports.left = function(str){
24656 return str.replace(/^\s*/, '');
24659 exports.right = function(str){
24660 return str.replace(/\s*$/, '');
24663 },{}],103:[function(_dereq_,module,exports){
24664 var trim = _dereq_(102)
24665 , forEach = _dereq_(101)
24666 , isArray = function(arg) {
24667 return Object.prototype.toString.call(arg) === '[object Array]';
24670 module.exports = function (headers) {
24677 trim(headers).split('\n')
24679 var index = row.indexOf(':')
24680 , key = trim(row.slice(0, index)).toLowerCase()
24681 , value = trim(row.slice(index + 1))
24683 if (typeof(result[key]) === 'undefined') {
24684 result[key] = value
24685 } else if (isArray(result[key])) {
24686 result[key].push(value)
24688 result[key] = [ result[key], value ]
24695 },{"101":101,"102":102}],104:[function(_dereq_,module,exports){
24696 module.exports = extend
24698 var hasOwnProperty = Object.prototype.hasOwnProperty;
24700 function extend() {
24703 for (var i = 0; i < arguments.length; i++) {
24704 var source = arguments[i]
24706 for (var key in source) {
24707 if (hasOwnProperty.call(source, key)) {
24708 target[key] = source[key]
24716 },{}]},{},[93])(93)
24718 /* vtt.js - v0.12.1 (https://github.com/mozilla/vtt.js) built on 08-07-2015 */
24721 var vttjs = root.vttjs = {};
24722 var cueShim = vttjs.VTTCue;
24723 var regionShim = vttjs.VTTRegion;
24724 var oldVTTCue = root.VTTCue;
24725 var oldVTTRegion = root.VTTRegion;
24727 vttjs.shim = function() {
24728 vttjs.VTTCue = cueShim;
24729 vttjs.VTTRegion = regionShim;
24732 vttjs.restore = function() {
24733 vttjs.VTTCue = oldVTTCue;
24734 vttjs.VTTRegion = oldVTTRegion;
24739 * Copyright 2013 vtt.js Contributors
24741 * Licensed under the Apache License, Version 2.0 (the "License");
24742 * you may not use this file except in compliance with the License.
24743 * You may obtain a copy of the License at
24745 * http://www.apache.org/licenses/LICENSE-2.0
24747 * Unless required by applicable law or agreed to in writing, software
24748 * distributed under the License is distributed on an "AS IS" BASIS,
24749 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24750 * See the License for the specific language governing permissions and
24751 * limitations under the License.
24754 (function(root, vttjs) {
24756 var autoKeyword = "auto";
24757 var directionSetting = {
24762 var alignSetting = {
24770 function findDirectionSetting(value) {
24771 if (typeof value !== "string") {
24774 var dir = directionSetting[value.toLowerCase()];
24775 return dir ? value.toLowerCase() : false;
24778 function findAlignSetting(value) {
24779 if (typeof value !== "string") {
24782 var align = alignSetting[value.toLowerCase()];
24783 return align ? value.toLowerCase() : false;
24786 function extend(obj) {
24788 for (; i < arguments.length; i++) {
24789 var cobj = arguments[i];
24790 for (var p in cobj) {
24798 function VTTCue(startTime, endTime, text) {
24800 var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
24804 cue = document.createElement('custom');
24806 baseObj.enumerable = true;
24810 * Shim implementation specific properties. These properties are not in
24814 // Lets us know when the VTTCue's data has changed in such a way that we need
24815 // to recompute its display state. This lets us compute its display state
24817 cue.hasBeenReset = false;
24820 * VTTCue and TextTrackCue properties
24821 * http://dev.w3.org/html5/webvtt/#vttcue-interface
24825 var _pauseOnExit = false;
24826 var _startTime = startTime;
24827 var _endTime = endTime;
24829 var _region = null;
24830 var _vertical = "";
24831 var _snapToLines = true;
24832 var _line = "auto";
24833 var _lineAlign = "start";
24834 var _position = 50;
24835 var _positionAlign = "middle";
24837 var _align = "middle";
24839 Object.defineProperty(cue,
24840 "id", extend({}, baseObj, {
24844 set: function(value) {
24849 Object.defineProperty(cue,
24850 "pauseOnExit", extend({}, baseObj, {
24852 return _pauseOnExit;
24854 set: function(value) {
24855 _pauseOnExit = !!value;
24859 Object.defineProperty(cue,
24860 "startTime", extend({}, baseObj, {
24864 set: function(value) {
24865 if (typeof value !== "number") {
24866 throw new TypeError("Start time must be set to a number.");
24868 _startTime = value;
24869 this.hasBeenReset = true;
24873 Object.defineProperty(cue,
24874 "endTime", extend({}, baseObj, {
24878 set: function(value) {
24879 if (typeof value !== "number") {
24880 throw new TypeError("End time must be set to a number.");
24883 this.hasBeenReset = true;
24887 Object.defineProperty(cue,
24888 "text", extend({}, baseObj, {
24892 set: function(value) {
24893 _text = "" + value;
24894 this.hasBeenReset = true;
24898 Object.defineProperty(cue,
24899 "region", extend({}, baseObj, {
24903 set: function(value) {
24905 this.hasBeenReset = true;
24909 Object.defineProperty(cue,
24910 "vertical", extend({}, baseObj, {
24914 set: function(value) {
24915 var setting = findDirectionSetting(value);
24916 // Have to check for false because the setting an be an empty string.
24917 if (setting === false) {
24918 throw new SyntaxError("An invalid or illegal string was specified.");
24920 _vertical = setting;
24921 this.hasBeenReset = true;
24925 Object.defineProperty(cue,
24926 "snapToLines", extend({}, baseObj, {
24928 return _snapToLines;
24930 set: function(value) {
24931 _snapToLines = !!value;
24932 this.hasBeenReset = true;
24936 Object.defineProperty(cue,
24937 "line", extend({}, baseObj, {
24941 set: function(value) {
24942 if (typeof value !== "number" && value !== autoKeyword) {
24943 throw new SyntaxError("An invalid number or illegal string was specified.");
24946 this.hasBeenReset = true;
24950 Object.defineProperty(cue,
24951 "lineAlign", extend({}, baseObj, {
24955 set: function(value) {
24956 var setting = findAlignSetting(value);
24958 throw new SyntaxError("An invalid or illegal string was specified.");
24960 _lineAlign = setting;
24961 this.hasBeenReset = true;
24965 Object.defineProperty(cue,
24966 "position", extend({}, baseObj, {
24970 set: function(value) {
24971 if (value < 0 || value > 100) {
24972 throw new Error("Position must be between 0 and 100.");
24975 this.hasBeenReset = true;
24979 Object.defineProperty(cue,
24980 "positionAlign", extend({}, baseObj, {
24982 return _positionAlign;
24984 set: function(value) {
24985 var setting = findAlignSetting(value);
24987 throw new SyntaxError("An invalid or illegal string was specified.");
24989 _positionAlign = setting;
24990 this.hasBeenReset = true;
24994 Object.defineProperty(cue,
24995 "size", extend({}, baseObj, {
24999 set: function(value) {
25000 if (value < 0 || value > 100) {
25001 throw new Error("Size must be between 0 and 100.");
25004 this.hasBeenReset = true;
25008 Object.defineProperty(cue,
25009 "align", extend({}, baseObj, {
25013 set: function(value) {
25014 var setting = findAlignSetting(value);
25016 throw new SyntaxError("An invalid or illegal string was specified.");
25019 this.hasBeenReset = true;
25024 * Other <track> spec defined properties
25027 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state
25028 cue.displayState = undefined;
25039 VTTCue.prototype.getCueAsHTML = function() {
25040 // Assume WebVTT.convertCueToDOMTree is on the global.
25041 return WebVTT.convertCueToDOMTree(window, this.text);
25044 root.VTTCue = root.VTTCue || VTTCue;
25045 vttjs.VTTCue = VTTCue;
25046 }(this, (this.vttjs || {})));
25049 * Copyright 2013 vtt.js Contributors
25051 * Licensed under the Apache License, Version 2.0 (the "License");
25052 * you may not use this file except in compliance with the License.
25053 * You may obtain a copy of the License at
25055 * http://www.apache.org/licenses/LICENSE-2.0
25057 * Unless required by applicable law or agreed to in writing, software
25058 * distributed under the License is distributed on an "AS IS" BASIS,
25059 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25060 * See the License for the specific language governing permissions and
25061 * limitations under the License.
25064 (function(root, vttjs) {
25066 var scrollSetting = {
25071 function findScrollSetting(value) {
25072 if (typeof value !== "string") {
25075 var scroll = scrollSetting[value.toLowerCase()];
25076 return scroll ? value.toLowerCase() : false;
25079 function isValidPercentValue(value) {
25080 return typeof value === "number" && (value >= 0 && value <= 100);
25083 // VTTRegion shim http://dev.w3.org/html5/webvtt/#vttregion-interface
25084 function VTTRegion() {
25087 var _regionAnchorX = 0;
25088 var _regionAnchorY = 100;
25089 var _viewportAnchorX = 0;
25090 var _viewportAnchorY = 100;
25093 Object.defineProperties(this, {
25099 set: function(value) {
25100 if (!isValidPercentValue(value)) {
25101 throw new Error("Width must be between 0 and 100.");
25111 set: function(value) {
25112 if (typeof value !== "number") {
25113 throw new TypeError("Lines must be set to a number.");
25121 return _regionAnchorY;
25123 set: function(value) {
25124 if (!isValidPercentValue(value)) {
25125 throw new Error("RegionAnchorX must be between 0 and 100.");
25127 _regionAnchorY = value;
25133 return _regionAnchorX;
25135 set: function(value) {
25136 if(!isValidPercentValue(value)) {
25137 throw new Error("RegionAnchorY must be between 0 and 100.");
25139 _regionAnchorX = value;
25142 "viewportAnchorY": {
25145 return _viewportAnchorY;
25147 set: function(value) {
25148 if (!isValidPercentValue(value)) {
25149 throw new Error("ViewportAnchorY must be between 0 and 100.");
25151 _viewportAnchorY = value;
25154 "viewportAnchorX": {
25157 return _viewportAnchorX;
25159 set: function(value) {
25160 if (!isValidPercentValue(value)) {
25161 throw new Error("ViewportAnchorX must be between 0 and 100.");
25163 _viewportAnchorX = value;
25171 set: function(value) {
25172 var setting = findScrollSetting(value);
25173 // Have to check for false as an empty string is a legal value.
25174 if (setting === false) {
25175 throw new SyntaxError("An invalid or illegal string was specified.");
25183 root.VTTRegion = root.VTTRegion || VTTRegion;
25184 vttjs.VTTRegion = VTTRegion;
25185 }(this, (this.vttjs || {})));
25188 * Copyright 2013 vtt.js Contributors
25190 * Licensed under the Apache License, Version 2.0 (the "License");
25191 * you may not use this file except in compliance with the License.
25192 * You may obtain a copy of the License at
25194 * http://www.apache.org/licenses/LICENSE-2.0
25196 * Unless required by applicable law or agreed to in writing, software
25197 * distributed under the License is distributed on an "AS IS" BASIS,
25198 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25199 * See the License for the specific language governing permissions and
25200 * limitations under the License.
25203 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
25204 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
25206 (function(global) {
25208 var _objCreate = Object.create || (function() {
25210 return function(o) {
25211 if (arguments.length !== 1) {
25212 throw new Error('Object.create shim only accepts one parameter.');
25219 // Creates a new ParserError object from an errorData object. The errorData
25220 // object should have default code and message properties. The default message
25221 // property can be overridden by passing in a message parameter.
25222 // See ParsingError.Errors below for acceptable errors.
25223 function ParsingError(errorData, message) {
25224 this.name = "ParsingError";
25225 this.code = errorData.code;
25226 this.message = message || errorData.message;
25228 ParsingError.prototype = _objCreate(Error.prototype);
25229 ParsingError.prototype.constructor = ParsingError;
25231 // ParsingError metadata for acceptable ParsingErrors.
25232 ParsingError.Errors = {
25235 message: "Malformed WebVTT signature."
25239 message: "Malformed time stamp."
25243 // Try to parse input as a time stamp.
25244 function parseTimeStamp(input) {
25246 function computeSeconds(h, m, s, f) {
25247 return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
25250 var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
25256 // Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
25257 return computeSeconds(m[1], m[2], m[3].replace(":", ""), m[4]);
25258 } else if (m[1] > 59) {
25259 // Timestamp takes the form of [hours]:[minutes].[milliseconds]
25260 // First position is hours as it's over 59.
25261 return computeSeconds(m[1], m[2], 0, m[4]);
25263 // Timestamp takes the form of [minutes]:[seconds].[milliseconds]
25264 return computeSeconds(0, m[1], m[2], m[4]);
25268 // A settings object holds key/value pairs and will ignore anything but the first
25269 // assignment to a specific key.
25270 function Settings() {
25271 this.values = _objCreate(null);
25274 Settings.prototype = {
25275 // Only accept the first assignment to any key.
25276 set: function(k, v) {
25277 if (!this.get(k) && v !== "") {
25278 this.values[k] = v;
25281 // Return the value for a key, or a default value.
25282 // If 'defaultKey' is passed then 'dflt' is assumed to be an object with
25283 // a number of possible default values as properties where 'defaultKey' is
25284 // the key of the property that will be chosen; otherwise it's assumed to be
25286 get: function(k, dflt, defaultKey) {
25288 return this.has(k) ? this.values[k] : dflt[defaultKey];
25290 return this.has(k) ? this.values[k] : dflt;
25292 // Check whether we have a value for a key.
25294 return k in this.values;
25296 // Accept a setting if its one of the given alternatives.
25297 alt: function(k, v, a) {
25298 for (var n = 0; n < a.length; ++n) {
25305 // Accept a setting if its a valid (signed) integer.
25306 integer: function(k, v) {
25307 if (/^-?\d+$/.test(v)) { // integer
25308 this.set(k, parseInt(v, 10));
25311 // Accept a setting if its a valid percentage.
25312 percent: function(k, v) {
25314 if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) {
25316 if (v >= 0 && v <= 100) {
25325 // Helper function to parse input into groups separated by 'groupDelim', and
25326 // interpret each group as a key/value pair separated by 'keyValueDelim'.
25327 function parseOptions(input, callback, keyValueDelim, groupDelim) {
25328 var groups = groupDelim ? input.split(groupDelim) : [input];
25329 for (var i in groups) {
25330 if (typeof groups[i] !== "string") {
25333 var kv = groups[i].split(keyValueDelim);
25334 if (kv.length !== 2) {
25343 function parseCue(input, cue, regionList) {
25344 // Remember the original input if we need to throw an error.
25345 var oInput = input;
25346 // 4.1 WebVTT timestamp
25347 function consumeTimeStamp() {
25348 var ts = parseTimeStamp(input);
25350 throw new ParsingError(ParsingError.Errors.BadTimeStamp,
25351 "Malformed timestamp: " + oInput);
25353 // Remove time stamp from input.
25354 input = input.replace(/^[^\sa-zA-Z-]+/, "");
25358 // 4.4.2 WebVTT cue settings
25359 function consumeCueSettings(input, cue) {
25360 var settings = new Settings();
25362 parseOptions(input, function (k, v) {
25365 // Find the last region we parsed with the same region id.
25366 for (var i = regionList.length - 1; i >= 0; i--) {
25367 if (regionList[i].id === v) {
25368 settings.set(k, regionList[i].region);
25374 settings.alt(k, v, ["rl", "lr"]);
25377 var vals = v.split(","),
25379 settings.integer(k, vals0);
25380 settings.percent(k, vals0) ? settings.set("snapToLines", false) : null;
25381 settings.alt(k, vals0, ["auto"]);
25382 if (vals.length === 2) {
25383 settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
25387 vals = v.split(",");
25388 settings.percent(k, vals[0]);
25389 if (vals.length === 2) {
25390 settings.alt("positionAlign", vals[1], ["start", "middle", "end"]);
25394 settings.percent(k, v);
25397 settings.alt(k, v, ["start", "middle", "end", "left", "right"]);
25402 // Apply default values for any missing fields.
25403 cue.region = settings.get("region", null);
25404 cue.vertical = settings.get("vertical", "");
25405 cue.line = settings.get("line", "auto");
25406 cue.lineAlign = settings.get("lineAlign", "start");
25407 cue.snapToLines = settings.get("snapToLines", true);
25408 cue.size = settings.get("size", 100);
25409 cue.align = settings.get("align", "middle");
25410 cue.position = settings.get("position", {
25417 cue.positionAlign = settings.get("positionAlign", {
25426 function skipWhitespace() {
25427 input = input.replace(/^\s+/, "");
25430 // 4.1 WebVTT cue timings.
25432 cue.startTime = consumeTimeStamp(); // (1) collect cue start time
25434 if (input.substr(0, 3) !== "-->") { // (3) next characters must match "-->"
25435 throw new ParsingError(ParsingError.Errors.BadTimeStamp,
25436 "Malformed time stamp (time stamps must be separated by '-->'): " +
25439 input = input.substr(3);
25441 cue.endTime = consumeTimeStamp(); // (5) collect cue end time
25443 // 4.1 WebVTT cue settings list.
25445 consumeCueSettings(input, cue);
25468 var TAG_ANNOTATION = {
25473 var NEEDS_PARENT = {
25477 // Parse content into a document fragment.
25478 function parseContent(window, input) {
25479 function nextToken() {
25480 // Check for end-of-string.
25485 // Consume 'n' characters from the input.
25486 function consume(result) {
25487 input = input.substr(result.length);
25491 var m = input.match(/^([^<]*)(<[^>]+>?)?/);
25492 // If there is some text before the next tag, return it, otherwise return
25494 return consume(m[1] ? m[1] : m[2]);
25497 // Unescape a string 's'.
25498 function unescape1(e) {
25501 function unescape(s) {
25502 while ((m = s.match(/&(amp|lt|gt|lrm|rlm|nbsp);/))) {
25503 s = s.replace(m[0], unescape1);
25508 function shouldAdd(current, element) {
25509 return !NEEDS_PARENT[element.localName] ||
25510 NEEDS_PARENT[element.localName] === current.localName;
25513 // Create an element for this tag.
25514 function createElement(type, annotation) {
25515 var tagName = TAG_NAME[type];
25519 var element = window.document.createElement(tagName);
25520 element.localName = tagName;
25521 var name = TAG_ANNOTATION[type];
25522 if (name && annotation) {
25523 element[name] = annotation.trim();
25528 var rootDiv = window.document.createElement("div"),
25533 while ((t = nextToken()) !== null) {
25534 if (t[0] === '<') {
25535 if (t[1] === "/") {
25536 // If the closing tag matches, move back up to the parent node.
25537 if (tagStack.length &&
25538 tagStack[tagStack.length - 1] === t.substr(2).replace(">", "")) {
25540 current = current.parentNode;
25542 // Otherwise just ignore the end tag.
25545 var ts = parseTimeStamp(t.substr(1, t.length - 2));
25548 // Timestamps are lead nodes as well.
25549 node = window.document.createProcessingInstruction("timestamp", ts);
25550 current.appendChild(node);
25553 var m = t.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/);
25554 // If we can't parse the tag, skip to the next tag.
25558 // Try to construct an element, and ignore the tag if we couldn't.
25559 node = createElement(m[1], m[3]);
25563 // Determine if the tag should be added based on the context of where it
25564 // is placed in the cuetext.
25565 if (!shouldAdd(current, node)) {
25568 // Set the class list (as a list of classes, separated by space).
25570 node.className = m[2].substr(1).replace('.', ' ');
25572 // Append the node to the current node, and enter the scope of the new
25574 tagStack.push(m[1]);
25575 current.appendChild(node);
25580 // Text nodes are leaf nodes.
25581 current.appendChild(window.document.createTextNode(unescape(t)));
25587 // This is a list of all the Unicode characters that have a strong
25588 // right-to-left category. What this means is that these characters are
25589 // written right-to-left for sure. It was generated by pulling all the strong
25590 // right-to-left characters out of the Unicode data table. That table can
25591 // found at: http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
25592 var strongRTLChars = [0x05BE, 0x05C0, 0x05C3, 0x05C6, 0x05D0, 0x05D1,
25593 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA,
25594 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3,
25595 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x05F0, 0x05F1,
25596 0x05F2, 0x05F3, 0x05F4, 0x0608, 0x060B, 0x060D, 0x061B, 0x061E, 0x061F,
25597 0x0620, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
25598 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631,
25599 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A,
25600 0x063B, 0x063C, 0x063D, 0x063E, 0x063F, 0x0640, 0x0641, 0x0642, 0x0643,
25601 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x066D, 0x066E,
25602 0x066F, 0x0671, 0x0672, 0x0673, 0x0674, 0x0675, 0x0676, 0x0677, 0x0678,
25603 0x0679, 0x067A, 0x067B, 0x067C, 0x067D, 0x067E, 0x067F, 0x0680, 0x0681,
25604 0x0682, 0x0683, 0x0684, 0x0685, 0x0686, 0x0687, 0x0688, 0x0689, 0x068A,
25605 0x068B, 0x068C, 0x068D, 0x068E, 0x068F, 0x0690, 0x0691, 0x0692, 0x0693,
25606 0x0694, 0x0695, 0x0696, 0x0697, 0x0698, 0x0699, 0x069A, 0x069B, 0x069C,
25607 0x069D, 0x069E, 0x069F, 0x06A0, 0x06A1, 0x06A2, 0x06A3, 0x06A4, 0x06A5,
25608 0x06A6, 0x06A7, 0x06A8, 0x06A9, 0x06AA, 0x06AB, 0x06AC, 0x06AD, 0x06AE,
25609 0x06AF, 0x06B0, 0x06B1, 0x06B2, 0x06B3, 0x06B4, 0x06B5, 0x06B6, 0x06B7,
25610 0x06B8, 0x06B9, 0x06BA, 0x06BB, 0x06BC, 0x06BD, 0x06BE, 0x06BF, 0x06C0,
25611 0x06C1, 0x06C2, 0x06C3, 0x06C4, 0x06C5, 0x06C6, 0x06C7, 0x06C8, 0x06C9,
25612 0x06CA, 0x06CB, 0x06CC, 0x06CD, 0x06CE, 0x06CF, 0x06D0, 0x06D1, 0x06D2,
25613 0x06D3, 0x06D4, 0x06D5, 0x06E5, 0x06E6, 0x06EE, 0x06EF, 0x06FA, 0x06FB,
25614 0x06FC, 0x06FD, 0x06FE, 0x06FF, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704,
25615 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070A, 0x070B, 0x070C, 0x070D,
25616 0x070F, 0x0710, 0x0712, 0x0713, 0x0714, 0x0715, 0x0716, 0x0717, 0x0718,
25617 0x0719, 0x071A, 0x071B, 0x071C, 0x071D, 0x071E, 0x071F, 0x0720, 0x0721,
25618 0x0722, 0x0723, 0x0724, 0x0725, 0x0726, 0x0727, 0x0728, 0x0729, 0x072A,
25619 0x072B, 0x072C, 0x072D, 0x072E, 0x072F, 0x074D, 0x074E, 0x074F, 0x0750,
25620 0x0751, 0x0752, 0x0753, 0x0754, 0x0755, 0x0756, 0x0757, 0x0758, 0x0759,
25621 0x075A, 0x075B, 0x075C, 0x075D, 0x075E, 0x075F, 0x0760, 0x0761, 0x0762,
25622 0x0763, 0x0764, 0x0765, 0x0766, 0x0767, 0x0768, 0x0769, 0x076A, 0x076B,
25623 0x076C, 0x076D, 0x076E, 0x076F, 0x0770, 0x0771, 0x0772, 0x0773, 0x0774,
25624 0x0775, 0x0776, 0x0777, 0x0778, 0x0779, 0x077A, 0x077B, 0x077C, 0x077D,
25625 0x077E, 0x077F, 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786,
25626 0x0787, 0x0788, 0x0789, 0x078A, 0x078B, 0x078C, 0x078D, 0x078E, 0x078F,
25627 0x0790, 0x0791, 0x0792, 0x0793, 0x0794, 0x0795, 0x0796, 0x0797, 0x0798,
25628 0x0799, 0x079A, 0x079B, 0x079C, 0x079D, 0x079E, 0x079F, 0x07A0, 0x07A1,
25629 0x07A2, 0x07A3, 0x07A4, 0x07A5, 0x07B1, 0x07C0, 0x07C1, 0x07C2, 0x07C3,
25630 0x07C4, 0x07C5, 0x07C6, 0x07C7, 0x07C8, 0x07C9, 0x07CA, 0x07CB, 0x07CC,
25631 0x07CD, 0x07CE, 0x07CF, 0x07D0, 0x07D1, 0x07D2, 0x07D3, 0x07D4, 0x07D5,
25632 0x07D6, 0x07D7, 0x07D8, 0x07D9, 0x07DA, 0x07DB, 0x07DC, 0x07DD, 0x07DE,
25633 0x07DF, 0x07E0, 0x07E1, 0x07E2, 0x07E3, 0x07E4, 0x07E5, 0x07E6, 0x07E7,
25634 0x07E8, 0x07E9, 0x07EA, 0x07F4, 0x07F5, 0x07FA, 0x0800, 0x0801, 0x0802,
25635 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, 0x080A, 0x080B,
25636 0x080C, 0x080D, 0x080E, 0x080F, 0x0810, 0x0811, 0x0812, 0x0813, 0x0814,
25637 0x0815, 0x081A, 0x0824, 0x0828, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834,
25638 0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083A, 0x083B, 0x083C, 0x083D,
25639 0x083E, 0x0840, 0x0841, 0x0842, 0x0843, 0x0844, 0x0845, 0x0846, 0x0847,
25640 0x0848, 0x0849, 0x084A, 0x084B, 0x084C, 0x084D, 0x084E, 0x084F, 0x0850,
25641 0x0851, 0x0852, 0x0853, 0x0854, 0x0855, 0x0856, 0x0857, 0x0858, 0x085E,
25642 0x08A0, 0x08A2, 0x08A3, 0x08A4, 0x08A5, 0x08A6, 0x08A7, 0x08A8, 0x08A9,
25643 0x08AA, 0x08AB, 0x08AC, 0x200F, 0xFB1D, 0xFB1F, 0xFB20, 0xFB21, 0xFB22,
25644 0xFB23, 0xFB24, 0xFB25, 0xFB26, 0xFB27, 0xFB28, 0xFB2A, 0xFB2B, 0xFB2C,
25645 0xFB2D, 0xFB2E, 0xFB2F, 0xFB30, 0xFB31, 0xFB32, 0xFB33, 0xFB34, 0xFB35,
25646 0xFB36, 0xFB38, 0xFB39, 0xFB3A, 0xFB3B, 0xFB3C, 0xFB3E, 0xFB40, 0xFB41,
25647 0xFB43, 0xFB44, 0xFB46, 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C,
25648 0xFB4D, 0xFB4E, 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55,
25649 0xFB56, 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D, 0xFB5E,
25650 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63, 0xFB64, 0xFB65, 0xFB66, 0xFB67,
25651 0xFB68, 0xFB69, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70,
25652 0xFB71, 0xFB72, 0xFB73, 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79,
25653 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81, 0xFB82,
25654 0xFB83, 0xFB84, 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B,
25655 0xFB8C, 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94,
25656 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D,
25657 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, 0xFBA4, 0xFBA5, 0xFBA6,
25658 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF,
25659 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3, 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8,
25660 0xFBB9, 0xFBBA, 0xFBBB, 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1,
25661 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB,
25662 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, 0xFBE4,
25663 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB, 0xFBEC, 0xFBED,
25664 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3, 0xFBF4, 0xFBF5, 0xFBF6,
25665 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF,
25666 0xFC00, 0xFC01, 0xFC02, 0xFC03, 0xFC04, 0xFC05, 0xFC06, 0xFC07, 0xFC08,
25667 0xFC09, 0xFC0A, 0xFC0B, 0xFC0C, 0xFC0D, 0xFC0E, 0xFC0F, 0xFC10, 0xFC11,
25668 0xFC12, 0xFC13, 0xFC14, 0xFC15, 0xFC16, 0xFC17, 0xFC18, 0xFC19, 0xFC1A,
25669 0xFC1B, 0xFC1C, 0xFC1D, 0xFC1E, 0xFC1F, 0xFC20, 0xFC21, 0xFC22, 0xFC23,
25670 0xFC24, 0xFC25, 0xFC26, 0xFC27, 0xFC28, 0xFC29, 0xFC2A, 0xFC2B, 0xFC2C,
25671 0xFC2D, 0xFC2E, 0xFC2F, 0xFC30, 0xFC31, 0xFC32, 0xFC33, 0xFC34, 0xFC35,
25672 0xFC36, 0xFC37, 0xFC38, 0xFC39, 0xFC3A, 0xFC3B, 0xFC3C, 0xFC3D, 0xFC3E,
25673 0xFC3F, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, 0xFC47,
25674 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0xFC4C, 0xFC4D, 0xFC4E, 0xFC4F, 0xFC50,
25675 0xFC51, 0xFC52, 0xFC53, 0xFC54, 0xFC55, 0xFC56, 0xFC57, 0xFC58, 0xFC59,
25676 0xFC5A, 0xFC5B, 0xFC5C, 0xFC5D, 0xFC5E, 0xFC5F, 0xFC60, 0xFC61, 0xFC62,
25677 0xFC63, 0xFC64, 0xFC65, 0xFC66, 0xFC67, 0xFC68, 0xFC69, 0xFC6A, 0xFC6B,
25678 0xFC6C, 0xFC6D, 0xFC6E, 0xFC6F, 0xFC70, 0xFC71, 0xFC72, 0xFC73, 0xFC74,
25679 0xFC75, 0xFC76, 0xFC77, 0xFC78, 0xFC79, 0xFC7A, 0xFC7B, 0xFC7C, 0xFC7D,
25680 0xFC7E, 0xFC7F, 0xFC80, 0xFC81, 0xFC82, 0xFC83, 0xFC84, 0xFC85, 0xFC86,
25681 0xFC87, 0xFC88, 0xFC89, 0xFC8A, 0xFC8B, 0xFC8C, 0xFC8D, 0xFC8E, 0xFC8F,
25682 0xFC90, 0xFC91, 0xFC92, 0xFC93, 0xFC94, 0xFC95, 0xFC96, 0xFC97, 0xFC98,
25683 0xFC99, 0xFC9A, 0xFC9B, 0xFC9C, 0xFC9D, 0xFC9E, 0xFC9F, 0xFCA0, 0xFCA1,
25684 0xFCA2, 0xFCA3, 0xFCA4, 0xFCA5, 0xFCA6, 0xFCA7, 0xFCA8, 0xFCA9, 0xFCAA,
25685 0xFCAB, 0xFCAC, 0xFCAD, 0xFCAE, 0xFCAF, 0xFCB0, 0xFCB1, 0xFCB2, 0xFCB3,
25686 0xFCB4, 0xFCB5, 0xFCB6, 0xFCB7, 0xFCB8, 0xFCB9, 0xFCBA, 0xFCBB, 0xFCBC,
25687 0xFCBD, 0xFCBE, 0xFCBF, 0xFCC0, 0xFCC1, 0xFCC2, 0xFCC3, 0xFCC4, 0xFCC5,
25688 0xFCC6, 0xFCC7, 0xFCC8, 0xFCC9, 0xFCCA, 0xFCCB, 0xFCCC, 0xFCCD, 0xFCCE,
25689 0xFCCF, 0xFCD0, 0xFCD1, 0xFCD2, 0xFCD3, 0xFCD4, 0xFCD5, 0xFCD6, 0xFCD7,
25690 0xFCD8, 0xFCD9, 0xFCDA, 0xFCDB, 0xFCDC, 0xFCDD, 0xFCDE, 0xFCDF, 0xFCE0,
25691 0xFCE1, 0xFCE2, 0xFCE3, 0xFCE4, 0xFCE5, 0xFCE6, 0xFCE7, 0xFCE8, 0xFCE9,
25692 0xFCEA, 0xFCEB, 0xFCEC, 0xFCED, 0xFCEE, 0xFCEF, 0xFCF0, 0xFCF1, 0xFCF2,
25693 0xFCF3, 0xFCF4, 0xFCF5, 0xFCF6, 0xFCF7, 0xFCF8, 0xFCF9, 0xFCFA, 0xFCFB,
25694 0xFCFC, 0xFCFD, 0xFCFE, 0xFCFF, 0xFD00, 0xFD01, 0xFD02, 0xFD03, 0xFD04,
25695 0xFD05, 0xFD06, 0xFD07, 0xFD08, 0xFD09, 0xFD0A, 0xFD0B, 0xFD0C, 0xFD0D,
25696 0xFD0E, 0xFD0F, 0xFD10, 0xFD11, 0xFD12, 0xFD13, 0xFD14, 0xFD15, 0xFD16,
25697 0xFD17, 0xFD18, 0xFD19, 0xFD1A, 0xFD1B, 0xFD1C, 0xFD1D, 0xFD1E, 0xFD1F,
25698 0xFD20, 0xFD21, 0xFD22, 0xFD23, 0xFD24, 0xFD25, 0xFD26, 0xFD27, 0xFD28,
25699 0xFD29, 0xFD2A, 0xFD2B, 0xFD2C, 0xFD2D, 0xFD2E, 0xFD2F, 0xFD30, 0xFD31,
25700 0xFD32, 0xFD33, 0xFD34, 0xFD35, 0xFD36, 0xFD37, 0xFD38, 0xFD39, 0xFD3A,
25701 0xFD3B, 0xFD3C, 0xFD3D, 0xFD50, 0xFD51, 0xFD52, 0xFD53, 0xFD54, 0xFD55,
25702 0xFD56, 0xFD57, 0xFD58, 0xFD59, 0xFD5A, 0xFD5B, 0xFD5C, 0xFD5D, 0xFD5E,
25703 0xFD5F, 0xFD60, 0xFD61, 0xFD62, 0xFD63, 0xFD64, 0xFD65, 0xFD66, 0xFD67,
25704 0xFD68, 0xFD69, 0xFD6A, 0xFD6B, 0xFD6C, 0xFD6D, 0xFD6E, 0xFD6F, 0xFD70,
25705 0xFD71, 0xFD72, 0xFD73, 0xFD74, 0xFD75, 0xFD76, 0xFD77, 0xFD78, 0xFD79,
25706 0xFD7A, 0xFD7B, 0xFD7C, 0xFD7D, 0xFD7E, 0xFD7F, 0xFD80, 0xFD81, 0xFD82,
25707 0xFD83, 0xFD84, 0xFD85, 0xFD86, 0xFD87, 0xFD88, 0xFD89, 0xFD8A, 0xFD8B,
25708 0xFD8C, 0xFD8D, 0xFD8E, 0xFD8F, 0xFD92, 0xFD93, 0xFD94, 0xFD95, 0xFD96,
25709 0xFD97, 0xFD98, 0xFD99, 0xFD9A, 0xFD9B, 0xFD9C, 0xFD9D, 0xFD9E, 0xFD9F,
25710 0xFDA0, 0xFDA1, 0xFDA2, 0xFDA3, 0xFDA4, 0xFDA5, 0xFDA6, 0xFDA7, 0xFDA8,
25711 0xFDA9, 0xFDAA, 0xFDAB, 0xFDAC, 0xFDAD, 0xFDAE, 0xFDAF, 0xFDB0, 0xFDB1,
25712 0xFDB2, 0xFDB3, 0xFDB4, 0xFDB5, 0xFDB6, 0xFDB7, 0xFDB8, 0xFDB9, 0xFDBA,
25713 0xFDBB, 0xFDBC, 0xFDBD, 0xFDBE, 0xFDBF, 0xFDC0, 0xFDC1, 0xFDC2, 0xFDC3,
25714 0xFDC4, 0xFDC5, 0xFDC6, 0xFDC7, 0xFDF0, 0xFDF1, 0xFDF2, 0xFDF3, 0xFDF4,
25715 0xFDF5, 0xFDF6, 0xFDF7, 0xFDF8, 0xFDF9, 0xFDFA, 0xFDFB, 0xFDFC, 0xFE70,
25716 0xFE71, 0xFE72, 0xFE73, 0xFE74, 0xFE76, 0xFE77, 0xFE78, 0xFE79, 0xFE7A,
25717 0xFE7B, 0xFE7C, 0xFE7D, 0xFE7E, 0xFE7F, 0xFE80, 0xFE81, 0xFE82, 0xFE83,
25718 0xFE84, 0xFE85, 0xFE86, 0xFE87, 0xFE88, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C,
25719 0xFE8D, 0xFE8E, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, 0xFE93, 0xFE94, 0xFE95,
25720 0xFE96, 0xFE97, 0xFE98, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, 0xFE9D, 0xFE9E,
25721 0xFE9F, 0xFEA0, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, 0xFEA5, 0xFEA6, 0xFEA7,
25722 0xFEA8, 0xFEA9, 0xFEAA, 0xFEAB, 0xFEAC, 0xFEAD, 0xFEAE, 0xFEAF, 0xFEB0,
25723 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, 0xFEB9,
25724 0xFEBA, 0xFEBB, 0xFEBC, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, 0xFEC1, 0xFEC2,
25725 0xFEC3, 0xFEC4, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, 0xFEC9, 0xFECA, 0xFECB,
25726 0xFECC, 0xFECD, 0xFECE, 0xFECF, 0xFED0, 0xFED1, 0xFED2, 0xFED3, 0xFED4,
25727 0xFED5, 0xFED6, 0xFED7, 0xFED8, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, 0xFEDD,
25728 0xFEDE, 0xFEDF, 0xFEE0, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, 0xFEE5, 0xFEE6,
25729 0xFEE7, 0xFEE8, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, 0xFEED, 0xFEEE, 0xFEEF,
25730 0xFEF0, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, 0xFEF5, 0xFEF6, 0xFEF7, 0xFEF8,
25731 0xFEF9, 0xFEFA, 0xFEFB, 0xFEFC, 0x10800, 0x10801, 0x10802, 0x10803,
25732 0x10804, 0x10805, 0x10808, 0x1080A, 0x1080B, 0x1080C, 0x1080D, 0x1080E,
25733 0x1080F, 0x10810, 0x10811, 0x10812, 0x10813, 0x10814, 0x10815, 0x10816,
25734 0x10817, 0x10818, 0x10819, 0x1081A, 0x1081B, 0x1081C, 0x1081D, 0x1081E,
25735 0x1081F, 0x10820, 0x10821, 0x10822, 0x10823, 0x10824, 0x10825, 0x10826,
25736 0x10827, 0x10828, 0x10829, 0x1082A, 0x1082B, 0x1082C, 0x1082D, 0x1082E,
25737 0x1082F, 0x10830, 0x10831, 0x10832, 0x10833, 0x10834, 0x10835, 0x10837,
25738 0x10838, 0x1083C, 0x1083F, 0x10840, 0x10841, 0x10842, 0x10843, 0x10844,
25739 0x10845, 0x10846, 0x10847, 0x10848, 0x10849, 0x1084A, 0x1084B, 0x1084C,
25740 0x1084D, 0x1084E, 0x1084F, 0x10850, 0x10851, 0x10852, 0x10853, 0x10854,
25741 0x10855, 0x10857, 0x10858, 0x10859, 0x1085A, 0x1085B, 0x1085C, 0x1085D,
25742 0x1085E, 0x1085F, 0x10900, 0x10901, 0x10902, 0x10903, 0x10904, 0x10905,
25743 0x10906, 0x10907, 0x10908, 0x10909, 0x1090A, 0x1090B, 0x1090C, 0x1090D,
25744 0x1090E, 0x1090F, 0x10910, 0x10911, 0x10912, 0x10913, 0x10914, 0x10915,
25745 0x10916, 0x10917, 0x10918, 0x10919, 0x1091A, 0x1091B, 0x10920, 0x10921,
25746 0x10922, 0x10923, 0x10924, 0x10925, 0x10926, 0x10927, 0x10928, 0x10929,
25747 0x1092A, 0x1092B, 0x1092C, 0x1092D, 0x1092E, 0x1092F, 0x10930, 0x10931,
25748 0x10932, 0x10933, 0x10934, 0x10935, 0x10936, 0x10937, 0x10938, 0x10939,
25749 0x1093F, 0x10980, 0x10981, 0x10982, 0x10983, 0x10984, 0x10985, 0x10986,
25750 0x10987, 0x10988, 0x10989, 0x1098A, 0x1098B, 0x1098C, 0x1098D, 0x1098E,
25751 0x1098F, 0x10990, 0x10991, 0x10992, 0x10993, 0x10994, 0x10995, 0x10996,
25752 0x10997, 0x10998, 0x10999, 0x1099A, 0x1099B, 0x1099C, 0x1099D, 0x1099E,
25753 0x1099F, 0x109A0, 0x109A1, 0x109A2, 0x109A3, 0x109A4, 0x109A5, 0x109A6,
25754 0x109A7, 0x109A8, 0x109A9, 0x109AA, 0x109AB, 0x109AC, 0x109AD, 0x109AE,
25755 0x109AF, 0x109B0, 0x109B1, 0x109B2, 0x109B3, 0x109B4, 0x109B5, 0x109B6,
25756 0x109B7, 0x109BE, 0x109BF, 0x10A00, 0x10A10, 0x10A11, 0x10A12, 0x10A13,
25757 0x10A15, 0x10A16, 0x10A17, 0x10A19, 0x10A1A, 0x10A1B, 0x10A1C, 0x10A1D,
25758 0x10A1E, 0x10A1F, 0x10A20, 0x10A21, 0x10A22, 0x10A23, 0x10A24, 0x10A25,
25759 0x10A26, 0x10A27, 0x10A28, 0x10A29, 0x10A2A, 0x10A2B, 0x10A2C, 0x10A2D,
25760 0x10A2E, 0x10A2F, 0x10A30, 0x10A31, 0x10A32, 0x10A33, 0x10A40, 0x10A41,
25761 0x10A42, 0x10A43, 0x10A44, 0x10A45, 0x10A46, 0x10A47, 0x10A50, 0x10A51,
25762 0x10A52, 0x10A53, 0x10A54, 0x10A55, 0x10A56, 0x10A57, 0x10A58, 0x10A60,
25763 0x10A61, 0x10A62, 0x10A63, 0x10A64, 0x10A65, 0x10A66, 0x10A67, 0x10A68,
25764 0x10A69, 0x10A6A, 0x10A6B, 0x10A6C, 0x10A6D, 0x10A6E, 0x10A6F, 0x10A70,
25765 0x10A71, 0x10A72, 0x10A73, 0x10A74, 0x10A75, 0x10A76, 0x10A77, 0x10A78,
25766 0x10A79, 0x10A7A, 0x10A7B, 0x10A7C, 0x10A7D, 0x10A7E, 0x10A7F, 0x10B00,
25767 0x10B01, 0x10B02, 0x10B03, 0x10B04, 0x10B05, 0x10B06, 0x10B07, 0x10B08,
25768 0x10B09, 0x10B0A, 0x10B0B, 0x10B0C, 0x10B0D, 0x10B0E, 0x10B0F, 0x10B10,
25769 0x10B11, 0x10B12, 0x10B13, 0x10B14, 0x10B15, 0x10B16, 0x10B17, 0x10B18,
25770 0x10B19, 0x10B1A, 0x10B1B, 0x10B1C, 0x10B1D, 0x10B1E, 0x10B1F, 0x10B20,
25771 0x10B21, 0x10B22, 0x10B23, 0x10B24, 0x10B25, 0x10B26, 0x10B27, 0x10B28,
25772 0x10B29, 0x10B2A, 0x10B2B, 0x10B2C, 0x10B2D, 0x10B2E, 0x10B2F, 0x10B30,
25773 0x10B31, 0x10B32, 0x10B33, 0x10B34, 0x10B35, 0x10B40, 0x10B41, 0x10B42,
25774 0x10B43, 0x10B44, 0x10B45, 0x10B46, 0x10B47, 0x10B48, 0x10B49, 0x10B4A,
25775 0x10B4B, 0x10B4C, 0x10B4D, 0x10B4E, 0x10B4F, 0x10B50, 0x10B51, 0x10B52,
25776 0x10B53, 0x10B54, 0x10B55, 0x10B58, 0x10B59, 0x10B5A, 0x10B5B, 0x10B5C,
25777 0x10B5D, 0x10B5E, 0x10B5F, 0x10B60, 0x10B61, 0x10B62, 0x10B63, 0x10B64,
25778 0x10B65, 0x10B66, 0x10B67, 0x10B68, 0x10B69, 0x10B6A, 0x10B6B, 0x10B6C,
25779 0x10B6D, 0x10B6E, 0x10B6F, 0x10B70, 0x10B71, 0x10B72, 0x10B78, 0x10B79,
25780 0x10B7A, 0x10B7B, 0x10B7C, 0x10B7D, 0x10B7E, 0x10B7F, 0x10C00, 0x10C01,
25781 0x10C02, 0x10C03, 0x10C04, 0x10C05, 0x10C06, 0x10C07, 0x10C08, 0x10C09,
25782 0x10C0A, 0x10C0B, 0x10C0C, 0x10C0D, 0x10C0E, 0x10C0F, 0x10C10, 0x10C11,
25783 0x10C12, 0x10C13, 0x10C14, 0x10C15, 0x10C16, 0x10C17, 0x10C18, 0x10C19,
25784 0x10C1A, 0x10C1B, 0x10C1C, 0x10C1D, 0x10C1E, 0x10C1F, 0x10C20, 0x10C21,
25785 0x10C22, 0x10C23, 0x10C24, 0x10C25, 0x10C26, 0x10C27, 0x10C28, 0x10C29,
25786 0x10C2A, 0x10C2B, 0x10C2C, 0x10C2D, 0x10C2E, 0x10C2F, 0x10C30, 0x10C31,
25787 0x10C32, 0x10C33, 0x10C34, 0x10C35, 0x10C36, 0x10C37, 0x10C38, 0x10C39,
25788 0x10C3A, 0x10C3B, 0x10C3C, 0x10C3D, 0x10C3E, 0x10C3F, 0x10C40, 0x10C41,
25789 0x10C42, 0x10C43, 0x10C44, 0x10C45, 0x10C46, 0x10C47, 0x10C48, 0x1EE00,
25790 0x1EE01, 0x1EE02, 0x1EE03, 0x1EE05, 0x1EE06, 0x1EE07, 0x1EE08, 0x1EE09,
25791 0x1EE0A, 0x1EE0B, 0x1EE0C, 0x1EE0D, 0x1EE0E, 0x1EE0F, 0x1EE10, 0x1EE11,
25792 0x1EE12, 0x1EE13, 0x1EE14, 0x1EE15, 0x1EE16, 0x1EE17, 0x1EE18, 0x1EE19,
25793 0x1EE1A, 0x1EE1B, 0x1EE1C, 0x1EE1D, 0x1EE1E, 0x1EE1F, 0x1EE21, 0x1EE22,
25794 0x1EE24, 0x1EE27, 0x1EE29, 0x1EE2A, 0x1EE2B, 0x1EE2C, 0x1EE2D, 0x1EE2E,
25795 0x1EE2F, 0x1EE30, 0x1EE31, 0x1EE32, 0x1EE34, 0x1EE35, 0x1EE36, 0x1EE37,
25796 0x1EE39, 0x1EE3B, 0x1EE42, 0x1EE47, 0x1EE49, 0x1EE4B, 0x1EE4D, 0x1EE4E,
25797 0x1EE4F, 0x1EE51, 0x1EE52, 0x1EE54, 0x1EE57, 0x1EE59, 0x1EE5B, 0x1EE5D,
25798 0x1EE5F, 0x1EE61, 0x1EE62, 0x1EE64, 0x1EE67, 0x1EE68, 0x1EE69, 0x1EE6A,
25799 0x1EE6C, 0x1EE6D, 0x1EE6E, 0x1EE6F, 0x1EE70, 0x1EE71, 0x1EE72, 0x1EE74,
25800 0x1EE75, 0x1EE76, 0x1EE77, 0x1EE79, 0x1EE7A, 0x1EE7B, 0x1EE7C, 0x1EE7E,
25801 0x1EE80, 0x1EE81, 0x1EE82, 0x1EE83, 0x1EE84, 0x1EE85, 0x1EE86, 0x1EE87,
25802 0x1EE88, 0x1EE89, 0x1EE8B, 0x1EE8C, 0x1EE8D, 0x1EE8E, 0x1EE8F, 0x1EE90,
25803 0x1EE91, 0x1EE92, 0x1EE93, 0x1EE94, 0x1EE95, 0x1EE96, 0x1EE97, 0x1EE98,
25804 0x1EE99, 0x1EE9A, 0x1EE9B, 0x1EEA1, 0x1EEA2, 0x1EEA3, 0x1EEA5, 0x1EEA6,
25805 0x1EEA7, 0x1EEA8, 0x1EEA9, 0x1EEAB, 0x1EEAC, 0x1EEAD, 0x1EEAE, 0x1EEAF,
25806 0x1EEB0, 0x1EEB1, 0x1EEB2, 0x1EEB3, 0x1EEB4, 0x1EEB5, 0x1EEB6, 0x1EEB7,
25807 0x1EEB8, 0x1EEB9, 0x1EEBA, 0x1EEBB, 0x10FFFD];
25809 function determineBidi(cueDiv) {
25810 var nodeStack = [],
25814 if (!cueDiv || !cueDiv.childNodes) {
25818 function pushNodes(nodeStack, node) {
25819 for (var i = node.childNodes.length - 1; i >= 0; i--) {
25820 nodeStack.push(node.childNodes[i]);
25824 function nextTextNode(nodeStack) {
25825 if (!nodeStack || !nodeStack.length) {
25829 var node = nodeStack.pop(),
25830 text = node.textContent || node.innerText;
25832 // TODO: This should match all unicode type B characters (paragraph
25833 // separator characters). See issue #115.
25834 var m = text.match(/^.*(\n|\r)/);
25836 nodeStack.length = 0;
25841 if (node.tagName === "ruby") {
25842 return nextTextNode(nodeStack);
25844 if (node.childNodes) {
25845 pushNodes(nodeStack, node);
25846 return nextTextNode(nodeStack);
25850 pushNodes(nodeStack, cueDiv);
25851 while ((text = nextTextNode(nodeStack))) {
25852 for (var i = 0; i < text.length; i++) {
25853 charCode = text.charCodeAt(i);
25854 for (var j = 0; j < strongRTLChars.length; j++) {
25855 if (strongRTLChars[j] === charCode) {
25864 function computeLinePos(cue) {
25865 if (typeof cue.line === "number" &&
25866 (cue.snapToLines || (cue.line >= 0 && cue.line <= 100))) {
25869 if (!cue.track || !cue.track.textTrackList ||
25870 !cue.track.textTrackList.mediaElement) {
25873 var track = cue.track,
25874 trackList = track.textTrackList,
25876 for (var i = 0; i < trackList.length && trackList[i] !== track; i++) {
25877 if (trackList[i].mode === "showing") {
25881 return ++count * -1;
25884 function StyleBox() {
25887 // Apply styles to a div. If there is no div passed then it defaults to the
25889 StyleBox.prototype.applyStyles = function(styles, div) {
25890 div = div || this.div;
25891 for (var prop in styles) {
25892 if (styles.hasOwnProperty(prop)) {
25893 div.style[prop] = styles[prop];
25898 StyleBox.prototype.formatStyle = function(val, unit) {
25899 return val === 0 ? 0 : val + unit;
25902 // Constructs the computed display state of the cue (a div). Places the div
25903 // into the overlay which should be a block level element (usually a div).
25904 function CueStyleBox(window, cue, styleOptions) {
25905 var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
25906 var color = "rgba(255, 255, 255, 1)";
25907 var backgroundColor = "rgba(0, 0, 0, 0.8)";
25910 color = "rgb(255, 255, 255)";
25911 backgroundColor = "rgb(0, 0, 0)";
25914 StyleBox.call(this);
25917 // Parse our cue's text into a DOM tree rooted at 'cueDiv'. This div will
25918 // have inline positioning and will function as the cue background box.
25919 this.cueDiv = parseContent(window, cue.text);
25922 backgroundColor: backgroundColor,
25923 position: "relative",
25932 styles.writingMode = cue.vertical === "" ? "horizontal-tb"
25933 : cue.vertical === "lr" ? "vertical-lr"
25935 styles.unicodeBidi = "plaintext";
25937 this.applyStyles(styles, this.cueDiv);
25939 // Create an absolutely positioned div that will be used to position the cue
25940 // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS
25941 // mirrors of them except "middle" which is "center" in CSS.
25942 this.div = window.document.createElement("div");
25944 textAlign: cue.align === "middle" ? "center" : cue.align,
25945 font: styleOptions.font,
25946 whiteSpace: "pre-line",
25947 position: "absolute"
25951 styles.direction = determineBidi(this.cueDiv);
25952 styles.writingMode = cue.vertical === "" ? "horizontal-tb"
25953 : cue.vertical === "lr" ? "vertical-lr"
25955 stylesunicodeBidi = "plaintext";
25958 this.applyStyles(styles);
25960 this.div.appendChild(this.cueDiv);
25962 // Calculate the distance from the reference edge of the viewport to the text
25963 // position of the cue box. The reference edge will be resolved later when
25964 // the box orientation styles are applied.
25966 switch (cue.positionAlign) {
25968 textPos = cue.position;
25971 textPos = cue.position - (cue.size / 2);
25974 textPos = cue.position - cue.size;
25978 // Horizontal box orientation; textPos is the distance from the left edge of the
25979 // area to the left edge of the box and cue.size is the distance extending to
25980 // the right from there.
25981 if (cue.vertical === "") {
25983 left: this.formatStyle(textPos, "%"),
25984 width: this.formatStyle(cue.size, "%")
25986 // Vertical box orientation; textPos is the distance from the top edge of the
25987 // area to the top edge of the box and cue.size is the height extending
25988 // downwards from there.
25991 top: this.formatStyle(textPos, "%"),
25992 height: this.formatStyle(cue.size, "%")
25996 this.move = function(box) {
25998 top: this.formatStyle(box.top, "px"),
25999 bottom: this.formatStyle(box.bottom, "px"),
26000 left: this.formatStyle(box.left, "px"),
26001 right: this.formatStyle(box.right, "px"),
26002 height: this.formatStyle(box.height, "px"),
26003 width: this.formatStyle(box.width, "px")
26007 CueStyleBox.prototype = _objCreate(StyleBox.prototype);
26008 CueStyleBox.prototype.constructor = CueStyleBox;
26010 // Represents the coordinates of an Element in a way that we can easily
26011 // compute things with such as if it overlaps or intersects with another Element.
26012 // Can initialize it with either a StyleBox or another BoxPosition.
26013 function BoxPosition(obj) {
26014 var isIE8 = (/MSIE\s8\.0/).test(navigator.userAgent);
26016 // Either a BoxPosition was passed in and we need to copy it, or a StyleBox
26017 // was passed in and we need to copy the results of 'getBoundingClientRect'
26018 // as the object returned is readonly. All coordinate values are in reference
26019 // to the viewport origin (top left).
26020 var lh, height, width, top;
26022 height = obj.div.offsetHeight;
26023 width = obj.div.offsetWidth;
26024 top = obj.div.offsetTop;
26026 var rects = (rects = obj.div.childNodes) && (rects = rects[0]) &&
26027 rects.getClientRects && rects.getClientRects();
26028 obj = obj.div.getBoundingClientRect();
26029 // In certain cases the outer div will be slightly larger then the sum of
26030 // the inner div's lines. This could be due to bold text, etc, on some platforms.
26031 // In this case we should get the average line height and use that. This will
26032 // result in the desired behaviour.
26033 lh = rects ? Math.max((rects[0] && rects[0].height) || 0, obj.height / rects.length)
26037 this.left = obj.left;
26038 this.right = obj.right;
26039 this.top = obj.top || top;
26040 this.height = obj.height || height;
26041 this.bottom = obj.bottom || (top + (obj.height || height));
26042 this.width = obj.width || width;
26043 this.lineHeight = lh !== undefined ? lh : obj.lineHeight;
26045 if (isIE8 && !this.lineHeight) {
26046 this.lineHeight = 13;
26050 // Move the box along a particular axis. Optionally pass in an amount to move
26051 // the box. If no amount is passed then the default is the line height of the
26053 BoxPosition.prototype.move = function(axis, toMove) {
26054 toMove = toMove !== undefined ? toMove : this.lineHeight;
26057 this.left += toMove;
26058 this.right += toMove;
26061 this.left -= toMove;
26062 this.right -= toMove;
26065 this.top += toMove;
26066 this.bottom += toMove;
26069 this.top -= toMove;
26070 this.bottom -= toMove;
26075 // Check if this box overlaps another box, b2.
26076 BoxPosition.prototype.overlaps = function(b2) {
26077 return this.left < b2.right &&
26078 this.right > b2.left &&
26079 this.top < b2.bottom &&
26080 this.bottom > b2.top;
26083 // Check if this box overlaps any other boxes in boxes.
26084 BoxPosition.prototype.overlapsAny = function(boxes) {
26085 for (var i = 0; i < boxes.length; i++) {
26086 if (this.overlaps(boxes[i])) {
26093 // Check if this box is within another box.
26094 BoxPosition.prototype.within = function(container) {
26095 return this.top >= container.top &&
26096 this.bottom <= container.bottom &&
26097 this.left >= container.left &&
26098 this.right <= container.right;
26101 // Check if this box is entirely within the container or it is overlapping
26102 // on the edge opposite of the axis direction passed. For example, if "+x" is
26103 // passed and the box is overlapping on the left edge of the container, then
26105 BoxPosition.prototype.overlapsOppositeAxis = function(container, axis) {
26108 return this.left < container.left;
26110 return this.right > container.right;
26112 return this.top < container.top;
26114 return this.bottom > container.bottom;
26118 // Find the percentage of the area that this box is overlapping with another
26120 BoxPosition.prototype.intersectPercentage = function(b2) {
26121 var x = Math.max(0, Math.min(this.right, b2.right) - Math.max(this.left, b2.left)),
26122 y = Math.max(0, Math.min(this.bottom, b2.bottom) - Math.max(this.top, b2.top)),
26123 intersectArea = x * y;
26124 return intersectArea / (this.height * this.width);
26127 // Convert the positions from this box to CSS compatible positions using
26128 // the reference container's positions. This has to be done because this
26129 // box's positions are in reference to the viewport origin, whereas, CSS
26130 // values are in reference to their respective edges.
26131 BoxPosition.prototype.toCSSCompatValues = function(reference) {
26133 top: this.top - reference.top,
26134 bottom: reference.bottom - this.bottom,
26135 left: this.left - reference.left,
26136 right: reference.right - this.right,
26137 height: this.height,
26142 // Get an object that represents the box's position without anything extra.
26143 // Can pass a StyleBox, HTMLElement, or another BoxPositon.
26144 BoxPosition.getSimpleBoxPosition = function(obj) {
26145 var height = obj.div ? obj.div.offsetHeight : obj.tagName ? obj.offsetHeight : 0;
26146 var width = obj.div ? obj.div.offsetWidth : obj.tagName ? obj.offsetWidth : 0;
26147 var top = obj.div ? obj.div.offsetTop : obj.tagName ? obj.offsetTop : 0;
26149 obj = obj.div ? obj.div.getBoundingClientRect() :
26150 obj.tagName ? obj.getBoundingClientRect() : obj;
26154 top: obj.top || top,
26155 height: obj.height || height,
26156 bottom: obj.bottom || (top + (obj.height || height)),
26157 width: obj.width || width
26162 // Move a StyleBox to its specified, or next best, position. The containerBox
26163 // is the box that contains the StyleBox, such as a div. boxPositions are
26164 // a list of other boxes that the styleBox can't overlap with.
26165 function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) {
26167 // Find the best position for a cue box, b, on the video. The axis parameter
26168 // is a list of axis, the order of which, it will move the box along. For example:
26169 // Passing ["+x", "-x"] will move the box first along the x axis in the positive
26170 // direction. If it doesn't find a good position for it there it will then move
26171 // it along the x axis in the negative direction.
26172 function findBestPosition(b, axis) {
26174 specifiedPosition = new BoxPosition(b),
26175 percentage = 1; // Highest possible so the first thing we get is better.
26177 for (var i = 0; i < axis.length; i++) {
26178 while (b.overlapsOppositeAxis(containerBox, axis[i]) ||
26179 (b.within(containerBox) && b.overlapsAny(boxPositions))) {
26182 // We found a spot where we aren't overlapping anything. This is our
26184 if (b.within(containerBox)) {
26187 var p = b.intersectPercentage(containerBox);
26188 // If we're outside the container box less then we were on our last try
26189 // then remember this position as the best position.
26190 if (percentage > p) {
26191 bestPosition = new BoxPosition(b);
26194 // Reset the box position to the specified position.
26195 b = new BoxPosition(specifiedPosition);
26197 return bestPosition || specifiedPosition;
26200 var boxPosition = new BoxPosition(styleBox),
26201 cue = styleBox.cue,
26202 linePos = computeLinePos(cue),
26205 // If we have a line number to align the cue to.
26206 if (cue.snapToLines) {
26208 switch (cue.vertical) {
26210 axis = [ "+y", "-y" ];
26214 axis = [ "+x", "-x" ];
26218 axis = [ "-x", "+x" ];
26223 var step = boxPosition.lineHeight,
26224 position = step * Math.round(linePos),
26225 maxPosition = containerBox[size] + step,
26226 initialAxis = axis[0];
26228 // If the specified initial position is greater then the max position then
26229 // clamp the box to the amount of steps it would take for the box to
26230 // reach the max position.
26231 if (Math.abs(position) > maxPosition) {
26232 position = position < 0 ? -1 : 1;
26233 position *= Math.ceil(maxPosition / step) * step;
26236 // If computed line position returns negative then line numbers are
26237 // relative to the bottom of the video instead of the top. Therefore, we
26238 // need to increase our initial position by the length or width of the
26239 // video, depending on the writing direction, and reverse our axis directions.
26241 position += cue.vertical === "" ? containerBox.height : containerBox.width;
26242 axis = axis.reverse();
26245 // Move the box to the specified position. This may not be its best
26247 boxPosition.move(initialAxis, position);
26250 // If we have a percentage line value for the cue.
26251 var calculatedPercentage = (boxPosition.lineHeight / containerBox.height) * 100;
26253 switch (cue.lineAlign) {
26255 linePos -= (calculatedPercentage / 2);
26258 linePos -= calculatedPercentage;
26262 // Apply initial line position to the cue box.
26263 switch (cue.vertical) {
26265 styleBox.applyStyles({
26266 top: styleBox.formatStyle(linePos, "%")
26270 styleBox.applyStyles({
26271 left: styleBox.formatStyle(linePos, "%")
26275 styleBox.applyStyles({
26276 right: styleBox.formatStyle(linePos, "%")
26281 axis = [ "+y", "-x", "+x", "-y" ];
26283 // Get the box position again after we've applied the specified positioning
26285 boxPosition = new BoxPosition(styleBox);
26288 var bestPosition = findBestPosition(boxPosition, axis);
26289 styleBox.move(bestPosition.toCSSCompatValues(containerBox));
26292 function WebVTT() {
26296 // Helper to allow strings to be decoded instead of the default binary utf8 data.
26297 WebVTT.StringDecoder = function() {
26299 decode: function(data) {
26303 if (typeof data !== "string") {
26304 throw new Error("Error - expected string data.");
26306 return decodeURIComponent(encodeURIComponent(data));
26311 WebVTT.convertCueToDOMTree = function(window, cuetext) {
26312 if (!window || !cuetext) {
26315 return parseContent(window, cuetext);
26318 var FONT_SIZE_PERCENT = 0.05;
26319 var FONT_STYLE = "sans-serif";
26320 var CUE_BACKGROUND_PADDING = "1.5%";
26322 // Runs the processing model over the cues and regions passed to it.
26323 // @param overlay A block level element (usually a div) that the computed cues
26324 // and regions will be placed into.
26325 WebVTT.processCues = function(window, cues, overlay) {
26326 if (!window || !cues || !overlay) {
26330 // Remove all previous children.
26331 while (overlay.firstChild) {
26332 overlay.removeChild(overlay.firstChild);
26335 var paddedOverlay = window.document.createElement("div");
26336 paddedOverlay.style.position = "absolute";
26337 paddedOverlay.style.left = "0";
26338 paddedOverlay.style.right = "0";
26339 paddedOverlay.style.top = "0";
26340 paddedOverlay.style.bottom = "0";
26341 paddedOverlay.style.margin = CUE_BACKGROUND_PADDING;
26342 overlay.appendChild(paddedOverlay);
26344 // Determine if we need to compute the display states of the cues. This could
26345 // be the case if a cue's state has been changed since the last computation or
26346 // if it has not been computed yet.
26347 function shouldCompute(cues) {
26348 for (var i = 0; i < cues.length; i++) {
26349 if (cues[i].hasBeenReset || !cues[i].displayState) {
26356 // We don't need to recompute the cues' display states. Just reuse them.
26357 if (!shouldCompute(cues)) {
26358 for (var i = 0; i < cues.length; i++) {
26359 paddedOverlay.appendChild(cues[i].displayState);
26364 var boxPositions = [],
26365 containerBox = BoxPosition.getSimpleBoxPosition(paddedOverlay),
26366 fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100;
26367 var styleOptions = {
26368 font: fontSize + "px " + FONT_STYLE
26374 for (var i = 0; i < cues.length; i++) {
26377 // Compute the initial position and styles of the cue div.
26378 styleBox = new CueStyleBox(window, cue, styleOptions);
26379 paddedOverlay.appendChild(styleBox.div);
26381 // Move the cue div to it's correct line position.
26382 moveBoxToLinePosition(window, styleBox, containerBox, boxPositions);
26384 // Remember the computed div so that we don't have to recompute it later
26385 // if we don't have too.
26386 cue.displayState = styleBox.div;
26388 boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox));
26393 WebVTT.Parser = function(window, vttjs, decoder) {
26402 this.window = window;
26403 this.vttjs = vttjs;
26404 this.state = "INITIAL";
26406 this.decoder = decoder || new TextDecoder("utf8");
26407 this.regionList = [];
26410 WebVTT.Parser.prototype = {
26411 // If the error is a ParsingError then report it to the consumer if
26412 // possible. If it's not a ParsingError then throw it like normal.
26413 reportOrThrowError: function(e) {
26414 if (e instanceof ParsingError) {
26415 this.onparsingerror && this.onparsingerror(e);
26420 parse: function (data) {
26423 // If there is no data then we won't decode it, but will just try to parse
26424 // whatever is in buffer already. This may occur in circumstances, for
26425 // example when flush() is called.
26427 // Try to decode the data that we received.
26428 self.buffer += self.decoder.decode(data, {stream: true});
26431 function collectNextLine() {
26432 var buffer = self.buffer;
26434 while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
26437 var line = buffer.substr(0, pos);
26438 // Advance the buffer early in case we fail below.
26439 if (buffer[pos] === '\r') {
26442 if (buffer[pos] === '\n') {
26445 self.buffer = buffer.substr(pos);
26449 // 3.4 WebVTT region and WebVTT region settings syntax
26450 function parseRegion(input) {
26451 var settings = new Settings();
26453 parseOptions(input, function (k, v) {
26456 settings.set(k, v);
26459 settings.percent(k, v);
26462 settings.integer(k, v);
26464 case "regionanchor":
26465 case "viewportanchor":
26466 var xy = v.split(',');
26467 if (xy.length !== 2) {
26470 // We have to make sure both x and y parse, so use a temporary
26471 // settings object here.
26472 var anchor = new Settings();
26473 anchor.percent("x", xy[0]);
26474 anchor.percent("y", xy[1]);
26475 if (!anchor.has("x") || !anchor.has("y")) {
26478 settings.set(k + "X", anchor.get("x"));
26479 settings.set(k + "Y", anchor.get("y"));
26482 settings.alt(k, v, ["up"]);
26487 // Create the region, using default values for any values that were not
26489 if (settings.has("id")) {
26490 var region = new (self.vttjs.VTTRegion || self.window.VTTRegion)();
26491 region.width = settings.get("width", 100);
26492 region.lines = settings.get("lines", 3);
26493 region.regionAnchorX = settings.get("regionanchorX", 0);
26494 region.regionAnchorY = settings.get("regionanchorY", 100);
26495 region.viewportAnchorX = settings.get("viewportanchorX", 0);
26496 region.viewportAnchorY = settings.get("viewportanchorY", 100);
26497 region.scroll = settings.get("scroll", "");
26498 // Register the region.
26499 self.onregion && self.onregion(region);
26500 // Remember the VTTRegion for later in case we parse any VTTCues that
26502 self.regionList.push({
26503 id: settings.get("id"),
26509 // 3.2 WebVTT metadata header syntax
26510 function parseHeader(input) {
26511 parseOptions(input, function (k, v) {
26514 // 3.3 WebVTT region metadata header syntax
26521 // 5.1 WebVTT file parsing.
26524 if (self.state === "INITIAL") {
26525 // We can't start parsing until we have the first line.
26526 if (!/\r\n|\n/.test(self.buffer)) {
26530 line = collectNextLine();
26532 var m = line.match(/^WEBVTT([ \t].*)?$/);
26534 throw new ParsingError(ParsingError.Errors.BadSignature);
26537 self.state = "HEADER";
26540 var alreadyCollectedLine = false;
26541 while (self.buffer) {
26542 // We can't parse a line until we have the full line.
26543 if (!/\r\n|\n/.test(self.buffer)) {
26547 if (!alreadyCollectedLine) {
26548 line = collectNextLine();
26550 alreadyCollectedLine = false;
26553 switch (self.state) {
26555 // 13-18 - Allow a header (metadata) under the WEBVTT line.
26556 if (/:/.test(line)) {
26558 } else if (!line) {
26559 // An empty line terminates the header and starts the body (cues).
26564 // Ignore NOTE blocks.
26570 // Check for the start of NOTE blocks.
26571 if (/^NOTE($|[ \t])/.test(line)) {
26572 self.state = "NOTE";
26575 // 19-29 - Allow any number of line terminators, then initialize new cue values.
26579 self.cue = new (self.vttjs.VTTCue || self.window.VTTCue)(0, 0, "");
26580 self.state = "CUE";
26581 // 30-39 - Check if self line contains an optional identifier or timing data.
26582 if (line.indexOf("-->") === -1) {
26583 self.cue.id = line;
26586 // Process line as start of a cue.
26589 // 40 - Collect cue timings and settings.
26591 parseCue(line, self.cue, self.regionList);
26593 self.reportOrThrowError(e);
26594 // In case of an error ignore rest of the cue.
26596 self.state = "BADCUE";
26599 self.state = "CUETEXT";
26602 var hasSubstring = line.indexOf("-->") !== -1;
26603 // 34 - If we have an empty line then report the cue.
26604 // 35 - If we have the special substring '-->' then report the cue,
26605 // but do not collect the line as we need to process the current
26606 // one as a new cue.
26607 if (!line || hasSubstring && (alreadyCollectedLine = true)) {
26608 // We are done parsing self cue.
26609 self.oncue && self.oncue(self.cue);
26614 if (self.cue.text) {
26615 self.cue.text += "\n";
26617 self.cue.text += line;
26619 case "BADCUE": // BADCUE
26620 // 54-62 - Collect and discard the remaining cue.
26628 self.reportOrThrowError(e);
26630 // If we are currently parsing a cue, report what we have.
26631 if (self.state === "CUETEXT" && self.cue && self.oncue) {
26632 self.oncue(self.cue);
26635 // Enter BADWEBVTT state if header was not parsed correctly otherwise
26636 // another exception occurred so enter BADCUE state.
26637 self.state = self.state === "INITIAL" ? "BADWEBVTT" : "BADCUE";
26641 flush: function () {
26644 // Finish decoding the stream.
26645 self.buffer += self.decoder.decode();
26646 // Synthesize the end of the current cue or region.
26647 if (self.cue || self.state === "HEADER") {
26648 self.buffer += "\n\n";
26651 // If we've flushed, parsed, and we're still on the INITIAL state then
26652 // that means we don't have enough of the stream to parse the first
26654 if (self.state === "INITIAL") {
26655 throw new ParsingError(ParsingError.Errors.BadSignature);
26658 self.reportOrThrowError(e);
26660 self.onflush && self.onflush();
26665 global.WebVTT = WebVTT;
26667 }(this, (this.vttjs || {})));