/**
* @license
* video.js 5.19.2
* copyright brightcove, inc.
* available under apache license version 2.0
*
*
* includes vtt.js
* available under apache license version 2.0
*
*/
(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 0 && arguments[0] !== undefined ? arguments[0] : 'button';
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
props = (0, _obj.assign)({
classname: this.buildcssclass()
}, props);
if (tag !== 'button') {
_log2['default'].warn('creating a button with an html element of ' + tag + ' is deprecated; use clickablecomponent instead.');
// add properties for clickable element which is not a native html button
props = (0, _obj.assign)({
tabindex: 0
}, props);
// add aria attributes for clickable element which is not a native html button
attributes = (0, _obj.assign)({
role: 'button'
}, attributes);
}
// add attributes for button element
attributes = (0, _obj.assign)({
// necessary since the default button type is "submit"
'type': 'button',
// let the screen reader user know that the text of the button may change
'aria-live': 'polite'
}, attributes);
var el = _component2['default'].prototype.createel.call(this, tag, props, attributes);
this.createcontroltextel(el);
return el;
};
/**
* add a child `component` inside of this `button`.
*
* @param {string|component} child
* the name or instance of a child to add.
*
* @param {object} [options={}]
* the key/value store of options that will get passed to children of
* the child.
*
* @return {component}
* the `component` that gets added as a child. when using a string the
* `component` will get created by this process.
*
* @deprecated since version 5
*/
button.prototype.addchild = function addchild(child) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var classname = this.constructor.name;
_log2['default'].warn('adding an actionable (user controllable) child to a button (' + classname + ') is not supported; use a clickablecomponent instead.');
// avoid the error message generated by clickablecomponent's addchild method
return _component2['default'].prototype.addchild.call(this, child, options);
};
/**
* enable the `button` element so that it can be activated or clicked. use this with
* {@link button#disable}.
*/
button.prototype.enable = function enable() {
_clickablecomponent.prototype.enable.call(this);
this.el_.removeattribute('disabled');
};
/**
* enable the `button` element so that it cannot be activated or clicked. use this with
* {@link button#enable}.
*/
button.prototype.disable = function disable() {
_clickablecomponent.prototype.disable.call(this);
this.el_.setattribute('disabled', 'disabled');
};
/**
* this gets called when a `button` has focus and `keydown` is triggered via a key
* press.
*
* @param {eventtarget~event} event
* the event that caused this function to get called.
*
* @listens keydown
*/
button.prototype.handlekeypress = function handlekeypress(event) {
// ignore space (32) or enter (13) key operation, which is handled by the browser for a button.
if (event.which === 32 || event.which === 13) {
return;
}
// pass keypress handling up for unsupported keys
_clickablecomponent.prototype.handlekeypress.call(this, event);
};
return button;
}(_clickablecomponent2['default']);
_component2['default'].registercomponent('button', button);
exports['default'] = button;
},{"3":3,"5":5,"86":86,"88":88}],3:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _events = _dereq_(82);
var events = _interoprequirewildcard(_events);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _log = _dereq_(86);
var _log2 = _interoprequiredefault(_log);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
var _obj = _dereq_(88);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file button.js
*/
/**
* clickable component which is clickable or keyboard actionable,
* but is not a native html button.
*
* @extends component
*/
var clickablecomponent = function (_component) {
_inherits(clickablecomponent, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function clickablecomponent(player, options) {
_classcallcheck(this, clickablecomponent);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.emittapevents();
_this.enable();
return _this;
}
/**
* create the `component`s dom element.
*
* @param {string} [tag=div]
* the element's node type.
*
* @param {object} [props={}]
* an object of properties that should be set on the element.
*
* @param {object} [attributes={}]
* an object of attributes that should be set on the element.
*
* @return {element}
* the element that gets created.
*/
clickablecomponent.prototype.createel = function createel() {
var tag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div';
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
props = (0, _obj.assign)({
classname: this.buildcssclass(),
tabindex: 0
}, props);
if (tag === 'button') {
_log2['default'].error('creating a clickablecomponent with an html element of ' + tag + ' is not supported; use a button instead.');
}
// add aria attributes for clickable element which is not a native html button
attributes = (0, _obj.assign)({
'role': 'button',
// let the screen reader user know that the text of the element may change
'aria-live': 'polite'
}, attributes);
this.tabindex_ = props.tabindex;
var el = _component.prototype.createel.call(this, tag, props, attributes);
this.createcontroltextel(el);
return el;
};
/**
* create a control text element on this `component`
*
* @param {element} [el]
* parent element for the control text.
*
* @return {element}
* the control text element that gets created.
*/
clickablecomponent.prototype.createcontroltextel = function createcontroltextel(el) {
this.controltextel_ = dom.createel('span', {
classname: 'vjs-control-text'
});
if (el) {
el.appendchild(this.controltextel_);
}
this.controltext(this.controltext_, el);
return this.controltextel_;
};
/**
* get or set the localize text to use for the controls on the `component`.
*
* @param {string} [text]
* control text for element.
*
* @param {element} [el=this.el()]
* element to set the title on.
*
* @return {string|clickablecomponent}
* - the control text when getting
* - returns itself when setting; method can be chained.
*/
clickablecomponent.prototype.controltext = function controltext(text) {
var el = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.el();
if (!text) {
return this.controltext_ || 'need text';
}
var localizedtext = this.localize(text);
this.controltext_ = text;
this.controltextel_.innerhtml = localizedtext;
if (!this.noniconcontrol) {
// set title attribute if only an icon is shown
el.setattribute('title', localizedtext);
}
return this;
};
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
clickablecomponent.prototype.buildcssclass = function buildcssclass() {
return 'vjs-control vjs-button ' + _component.prototype.buildcssclass.call(this);
};
/**
* enable this `component`s element.
*
* @return {clickablecomponent}
* returns itself; method can be chained.
*/
clickablecomponent.prototype.enable = function enable() {
this.removeclass('vjs-disabled');
this.el_.setattribute('aria-disabled', 'false');
if (typeof this.tabindex_ !== 'undefined') {
this.el_.setattribute('tabindex', this.tabindex_);
}
this.on('tap', this.handleclick);
this.on('click', this.handleclick);
this.on('focus', this.handlefocus);
this.on('blur', this.handleblur);
return this;
};
/**
* disable this `component`s element.
*
* @return {clickablecomponent}
* returns itself; method can be chained.
*/
clickablecomponent.prototype.disable = function disable() {
this.addclass('vjs-disabled');
this.el_.setattribute('aria-disabled', 'true');
if (typeof this.tabindex_ !== 'undefined') {
this.el_.removeattribute('tabindex');
}
this.off('tap', this.handleclick);
this.off('click', this.handleclick);
this.off('focus', this.handlefocus);
this.off('blur', this.handleblur);
return this;
};
/**
* this gets called when a `clickablecomponent` gets:
* - clicked (via the `click` event, listening starts in the constructor)
* - tapped (via the `tap` event, listening starts in the constructor)
* - the following things happen in order:
* 1. {@link clickablecomponent#handlefocus} is called via a `focus` event on the
* `clickablecomponent`.
* 2. {@link clickablecomponent#handlefocus} adds a listener for `keydown` on using
* {@link clickablecomponent#handlekeypress}.
* 3. `clickablecomponent` has not had a `blur` event (`blur` means that focus was lost). the user presses
* the space or enter key.
* 4. {@link clickablecomponent#handlekeypress} calls this function with the `keydown`
* event as a parameter.
*
* @param {eventtarget~event} event
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
* @abstract
*/
clickablecomponent.prototype.handleclick = function handleclick(event) {};
/**
* this gets called when a `clickablecomponent` gains focus via a `focus` event.
* turns on listening for `keydown` events. when they happen it
* calls `this.handlekeypress`.
*
* @param {eventtarget~event} event
* the `focus` event that caused this function to be called.
*
* @listens focus
*/
clickablecomponent.prototype.handlefocus = function handlefocus(event) {
events.on(_document2['default'], 'keydown', fn.bind(this, this.handlekeypress));
};
/**
* called when this clickablecomponent has focus and a key gets pressed down. by
* default it will call `this.handleclick` when the key is space or enter.
*
* @param {eventtarget~event} event
* the `keydown` event that caused this function to be called.
*
* @listens keydown
*/
clickablecomponent.prototype.handlekeypress = function handlekeypress(event) {
// support space (32) or enter (13) key operation to fire a click event
if (event.which === 32 || event.which === 13) {
event.preventdefault();
this.handleclick(event);
} else if (_component.prototype.handlekeypress) {
// pass keypress handling up for unsupported keys
_component.prototype.handlekeypress.call(this, event);
}
};
/**
* called when a `clickablecomponent` loses focus. turns off the listener for
* `keydown` events. which stops `this.handlekeypress` from getting called.
*
* @param {eventtarget~event} event
* the `blur` event that caused this function to be called.
*
* @listens blur
*/
clickablecomponent.prototype.handleblur = function handleblur(event) {
events.off(_document2['default'], 'keydown', fn.bind(this, this.handlekeypress));
};
return clickablecomponent;
}(_component2['default']);
_component2['default'].registercomponent('clickablecomponent', clickablecomponent);
exports['default'] = clickablecomponent;
},{"5":5,"81":81,"82":82,"83":83,"86":86,"88":88,"94":94}],4:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _button = _dereq_(2);
var _button2 = _interoprequiredefault(_button);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file close-button.js
*/
/**
* the `closebutton` is a `{@link button}` that fires a `close` event when
* it gets clicked.
*
* @extends button
*/
var closebutton = function (_button) {
_inherits(closebutton, _button);
/**
* creates an instance of the this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function closebutton(player, options) {
_classcallcheck(this, closebutton);
var _this = _possibleconstructorreturn(this, _button.call(this, player, options));
_this.controltext(options && options.controltext || _this.localize('close'));
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
closebutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-close-button ' + _button.prototype.buildcssclass.call(this);
};
/**
* this gets called when a `closebutton` gets clicked. see
* {@link clickablecomponent#handleclick} for more information on when this will be
* triggered
*
* @param {eventtarget~event} event
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
* @fires closebutton#close
*/
closebutton.prototype.handleclick = function handleclick(event) {
/**
* triggered when the a `closebutton` is clicked.
*
* @event closebutton#close
* @type {eventtarget~event}
*
* @property {boolean} [bubbles=false]
* set to false so that the close event does not
* bubble up to parents if there is no listener
*/
this.trigger({ type: 'close', bubbles: false });
};
return closebutton;
}(_button2['default']);
_component2['default'].registercomponent('closebutton', closebutton);
exports['default'] = closebutton;
},{"2":2,"5":5}],5:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _guid = _dereq_(85);
var guid = _interoprequirewildcard(_guid);
var _events = _dereq_(82);
var events = _interoprequirewildcard(_events);
var _log = _dereq_(86);
var _log2 = _interoprequiredefault(_log);
var _totitlecase = _dereq_(91);
var _totitlecase2 = _interoprequiredefault(_totitlecase);
var _mergeoptions = _dereq_(87);
var _mergeoptions2 = _interoprequiredefault(_mergeoptions);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } } /**
* player component - base class for all ui objects
*
* @file component.js
*/
/**
* base class for all ui components.
* components are ui objects which represent both a javascript object and an element
* in the dom. they can be children of other components, and can have
* children themselves.
*
* components can also use methods from {@link eventtarget}
*/
var component = function () {
/**
* a callback that is called when a component is ready. does not have any
* paramters and any callback value will be ignored.
*
* @callback component~readycallback
* @this component
*/
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
#
* @param {object[]} [options.children]
* an array of children objects to intialize this component with. children objects have
* a name property that will be used if more than one component of the same type needs to be
* added.
*
* @param {component~readycallback} [ready]
* function that gets called when the `component` is ready.
*/
function component(player, options, ready) {
_classcallcheck(this, component);
// the component might be the player itself and we can't pass `this` to super
if (!player && this.play) {
this.player_ = player = this; // eslint-disable-line
} else {
this.player_ = player;
}
// make a copy of prototype.options_ to protect against overriding defaults
this.options_ = (0, _mergeoptions2['default'])({}, this.options_);
// updated options with supplied options
options = this.options_ = (0, _mergeoptions2['default'])(this.options_, options);
// get id from options or options element if one is supplied
this.id_ = options.id || options.el && options.el.id;
// if there was no id from the options, generate one
if (!this.id_) {
// don't require the player id function in the case of mock players
var id = player && player.id && player.id() || 'no_player';
this.id_ = id + '_component_' + guid.newguid();
}
this.name_ = options.name || null;
// create element if one wasn't provided in options
if (options.el) {
this.el_ = options.el;
} else if (options.createel !== false) {
this.el_ = this.createel();
}
this.children_ = [];
this.childindex_ = {};
this.childnameindex_ = {};
// add any child components in options
if (options.initchildren !== false) {
this.initchildren();
}
this.ready(ready);
// don't want to trigger ready here or it will before init is actually
// finished for all children that run this constructor
if (options.reporttouchactivity !== false) {
this.enabletouchactivity();
}
}
/**
* dispose of the `component` and all child components.
*
* @fires component#dispose
*/
component.prototype.dispose = function dispose() {
/**
* triggered when a `component` is disposed.
*
* @event component#dispose
* @type {eventtarget~event}
*
* @property {boolean} [bubbles=false]
* set to false so that the close event does not
* bubble up
*/
this.trigger({ type: 'dispose', bubbles: false });
// dispose all children.
if (this.children_) {
for (var i = this.children_.length - 1; i >= 0; i--) {
if (this.children_[i].dispose) {
this.children_[i].dispose();
}
}
}
// delete child references
this.children_ = null;
this.childindex_ = null;
this.childnameindex_ = null;
// remove all event listeners.
this.off();
// remove element from dom
if (this.el_.parentnode) {
this.el_.parentnode.removechild(this.el_);
}
dom.removeeldata(this.el_);
this.el_ = null;
};
/**
* return the {@link player} that the `component` has attached to.
*
* @return {player}
* the player that this `component` has attached to.
*/
component.prototype.player = function player() {
return this.player_;
};
/**
* deep merge of options objects with new options.
* > note: when both `obj` and `options` contain properties whose values are objects.
* the two properties get merged using {@link module:mergeoptions}
*
* @param {object} obj
* the object that contains new options.
*
* @return {object}
* a new object of `this.options_` and `obj` merged together.
*
* @deprecated since version 5
*/
component.prototype.options = function options(obj) {
_log2['default'].warn('this.options() has been deprecated and will be moved to the constructor in 6.0');
if (!obj) {
return this.options_;
}
this.options_ = (0, _mergeoptions2['default'])(this.options_, obj);
return this.options_;
};
/**
* get the `component`s dom element
*
* @return {element}
* the dom element for this `component`.
*/
component.prototype.el = function el() {
return this.el_;
};
/**
* create the `component`s dom element.
*
* @param {string} [tagname]
* element's dom node type. e.g. 'div'
*
* @param {object} [properties]
* an object of properties that should be set.
*
* @param {object} [attributes]
* an object of attributes that should be set.
*
* @return {element}
* the element that gets created.
*/
component.prototype.createel = function createel(tagname, properties, attributes) {
return dom.createel(tagname, properties, attributes);
};
/**
* localize a string given the string in english.
*
* @param {string} string
* the string to localize.
*
* @return {string}
* the localized string or if no localization exists the english string.
*/
component.prototype.localize = function localize(string) {
var code = this.player_.language && this.player_.language();
var languages = this.player_.languages && this.player_.languages();
if (!code || !languages) {
return string;
}
var language = languages[code];
if (language && language[string]) {
return language[string];
}
var primarycode = code.split('-')[0];
var primarylang = languages[primarycode];
if (primarylang && primarylang[string]) {
return primarylang[string];
}
return string;
};
/**
* return the `component`s dom element. this is where children get inserted.
* this will usually be the the same as the element returned in {@link component#el}.
*
* @return {element}
* the content element for this `component`.
*/
component.prototype.contentel = function contentel() {
return this.contentel_ || this.el_;
};
/**
* get this `component`s id
*
* @return {string}
* the id of this `component`
*/
component.prototype.id = function id() {
return this.id_;
};
/**
* get the `component`s name. the name gets used to reference the `component`
* and is set during registration.
*
* @return {string}
* the name of this `component`.
*/
component.prototype.name = function name() {
return this.name_;
};
/**
* get an array of all child components
*
* @return {array}
* the children
*/
component.prototype.children = function children() {
return this.children_;
};
/**
* returns the child `component` with the given `id`.
*
* @param {string} id
* the id of the child `component` to get.
*
* @return {component|undefined}
* the child `component` with the given `id` or undefined.
*/
component.prototype.getchildbyid = function getchildbyid(id) {
return this.childindex_[id];
};
/**
* returns the child `component` with the given `name`.
*
* @param {string} name
* the name of the child `component` to get.
*
* @return {component|undefined}
* the child `component` with the given `name` or undefined.
*/
component.prototype.getchild = function getchild(name) {
if (!name) {
return;
}
name = (0, _totitlecase2['default'])(name);
return this.childnameindex_[name];
};
/**
* add a child `component` inside the current `component`.
*
*
* @param {string|component} child
* the name or instance of a child to add.
*
* @param {object} [options={}]
* the key/value store of options that will get passed to children of
* the child.
*
* @param {number} [index=this.children_.length]
* the index to attempt to add a child into.
*
* @return {component}
* the `component` that gets added as a child. when using a string the
* `component` will get created by this process.
*/
component.prototype.addchild = function addchild(child) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.children_.length;
var component = void 0;
var componentname = void 0;
// if child is a string, create component with options
if (typeof child === 'string') {
componentname = (0, _totitlecase2['default'])(child);
// options can also be specified as a boolean,
// so convert to an empty object if false.
if (!options) {
options = {};
}
// same as above, but true is deprecated so show a warning.
if (options === true) {
_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`.');
options = {};
}
var componentclassname = options.componentclass || componentname;
// set name through options
options.name = componentname;
// create a new object & element for this controls set
// if there's no .player_, this is a player
var componentclass = component.getcomponent(componentclassname);
if (!componentclass) {
throw new error('component ' + componentclassname + ' does not exist');
}
// data stored directly on the videojs object may be
// misidentified as a component to retain
// backwards-compatibility with 4.x. check to make sure the
// component class can be instantiated.
if (typeof componentclass !== 'function') {
return null;
}
component = new componentclass(this.player_ || this, options);
// child is a component instance
} else {
component = child;
}
this.children_.splice(index, 0, component);
if (typeof component.id === 'function') {
this.childindex_[component.id()] = component;
}
// if a name wasn't used to create the component, check if we can use the
// name function of the component
componentname = componentname || component.name && (0, _totitlecase2['default'])(component.name());
if (componentname) {
this.childnameindex_[componentname] = component;
}
// add the ui object's element to the container div (box)
// having an element is not required
if (typeof component.el === 'function' && component.el()) {
var childnodes = this.contentel().children;
var refnode = childnodes[index] || null;
this.contentel().insertbefore(component.el(), refnode);
}
// return so it can stored on parent object if desired.
return component;
};
/**
* remove a child `component` from this `component`s list of children. also removes
* the child `component`s element from this `component`s element.
*
* @param {component} component
* the child `component` to remove.
*/
component.prototype.removechild = function removechild(component) {
if (typeof component === 'string') {
component = this.getchild(component);
}
if (!component || !this.children_) {
return;
}
var childfound = false;
for (var i = this.children_.length - 1; i >= 0; i--) {
if (this.children_[i] === component) {
childfound = true;
this.children_.splice(i, 1);
break;
}
}
if (!childfound) {
return;
}
this.childindex_[component.id()] = null;
this.childnameindex_[component.name()] = null;
var compel = component.el();
if (compel && compel.parentnode === this.contentel()) {
this.contentel().removechild(component.el());
}
};
/**
* add and initialize default child `component`s based upon options.
*/
component.prototype.initchildren = function initchildren() {
var _this = this;
var children = this.options_.children;
if (children) {
// `this` is `parent`
var parentoptions = this.options_;
var handleadd = function handleadd(child) {
var name = child.name;
var opts = child.opts;
// allow options for children to be set at the parent options
// e.g. videojs(id, { controlbar: false });
// instead of videojs(id, { children: { controlbar: false });
if (parentoptions[name] !== undefined) {
opts = parentoptions[name];
}
// allow for disabling default components
// e.g. options['children']['posterimage'] = false
if (opts === false) {
return;
}
// allow options to be passed as a simple boolean if no configuration
// is necessary.
if (opts === true) {
opts = {};
}
// we also want to pass the original player options
// to each component as well so they don't need to
// reach back into the player for options later.
opts.playeroptions = _this.options_.playeroptions;
// create and add the child component.
// add a direct reference to the child by name on the parent instance.
// if two of the same component are used, different names should be supplied
// for each
var newchild = _this.addchild(name, opts);
if (newchild) {
_this[name] = newchild;
}
};
// allow for an array of children details to passed in the options
var workingchildren = void 0;
var tech = component.getcomponent('tech');
if (array.isarray(children)) {
workingchildren = children;
} else {
workingchildren = object.keys(children);
}
workingchildren
// children that are in this.options_ but also in workingchildren would
// give us extra children we do not want. so, we want to filter them out.
.concat(object.keys(this.options_).filter(function (child) {
return !workingchildren.some(function (wchild) {
if (typeof wchild === 'string') {
return child === wchild;
}
return child === wchild.name;
});
})).map(function (child) {
var name = void 0;
var opts = void 0;
if (typeof child === 'string') {
name = child;
opts = children[name] || _this.options_[name] || {};
} else {
name = child.name;
opts = child;
}
return { name: name, opts: opts };
}).filter(function (child) {
// we have to make sure that child.name isn't in the techorder since
// techs are registerd as components but can't aren't compatible
// see https://github.com/videojs/video.js/issues/2772
var c = component.getcomponent(child.opts.componentclass || (0, _totitlecase2['default'])(child.name));
return c && !tech.istech(c);
}).foreach(handleadd);
}
};
/**
* builds the default dom class name. should be overriden by sub-components.
*
* @return {string}
* the dom class name for this object.
*
* @abstract
*/
component.prototype.buildcssclass = function buildcssclass() {
// child classes can include a function that does:
// return 'class name' + this._super();
return '';
};
/**
* add an `event listener` to this `component`s element.
*
* the benefit of using this over the following:
* - `vjsevents.on(otherelement, 'eventname', myfunc)`
* - `othercomponent.on('eventname', myfunc)`
*
* 1. is that the listeners will get cleaned up when either component gets disposed.
* 1. it will also bind `mycomponent` as the context of `myfunc`.
* > note: if you remove the element from the dom that has used `on` you need to
* clean up references using: `mycomponent.trigger(el, 'dispose')`
* this will also allow the browser to garbage collect it. in special
* cases such as with `window` and `document`, which are both permanent,
* this is not necessary.
*
* @param {string|component|string[]} [first]
* the event name, and array of event names, or another `component`.
*
* @param {eventtarget~eventlistener|string|string[]} [second]
* the listener function, an event name, or an array of events names.
*
* @param {eventtarget~eventlistener} [third]
* the event handler if `first` is a `component` and `second` is an event name
* or an array of event names.
*
* @return {component}
* returns itself; method can be chained.
*
* @listens component#dispose
*/
component.prototype.on = function on(first, second, third) {
var _this2 = this;
if (typeof first === 'string' || array.isarray(first)) {
events.on(this.el_, first, fn.bind(this, second));
// targeting another component or element
} else {
var target = first;
var type = second;
var fn = fn.bind(this, third);
// when this component is disposed, remove the listener from the other component
var removeondispose = function removeondispose() {
return _this2.off(target, type, fn);
};
// use the same function id so we can remove it later it using the id
// of the original listener
removeondispose.guid = fn.guid;
this.on('dispose', removeondispose);
// if the other component is disposed first we need to clean the reference
// to the other component in this component's removeondispose listener
// otherwise we create a memory leak.
var cleanremover = function cleanremover() {
return _this2.off('dispose', removeondispose);
};
// add the same function id so we can easily remove it later
cleanremover.guid = fn.guid;
// check if this is a dom node
if (first.nodename) {
// add the listener to the other element
events.on(target, type, fn);
events.on(target, 'dispose', cleanremover);
// should be a component
// not using `instanceof component` because it makes mock players difficult
} else if (typeof first.on === 'function') {
// add the listener to the other component
target.on(type, fn);
target.on('dispose', cleanremover);
}
}
return this;
};
/**
* remove an event listener from this `component`s element. if the second argument is
* exluded all listeners for the type passed in as the first argument will be removed.
*
* @param {string|component|string[]} [first]
* the event name, and array of event names, or another `component`.
*
* @param {eventtarget~eventlistener|string|string[]} [second]
* the listener function, an event name, or an array of events names.
*
* @param {eventtarget~eventlistener} [third]
* the event handler if `first` is a `component` and `second` is an event name
* or an array of event names.
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.off = function off(first, second, third) {
if (!first || typeof first === 'string' || array.isarray(first)) {
events.off(this.el_, first, second);
} else {
var target = first;
var type = second;
// ensure there's at least a guid, even if the function hasn't been used
var fn = fn.bind(this, third);
// remove the dispose listener on this component,
// which was given the same guid as the event listener
this.off('dispose', fn);
if (first.nodename) {
// remove the listener
events.off(target, type, fn);
// remove the listener for cleaning the dispose listener
events.off(target, 'dispose', fn);
} else {
target.off(type, fn);
target.off('dispose', fn);
}
}
return this;
};
/**
* add an event listener that gets triggered only once and then gets removed.
*
* @param {string|component|string[]} [first]
* the event name, and array of event names, or another `component`.
*
* @param {eventtarget~eventlistener|string|string[]} [second]
* the listener function, an event name, or an array of events names.
*
* @param {eventtarget~eventlistener} [third]
* the event handler if `first` is a `component` and `second` is an event name
* or an array of event names.
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.one = function one(first, second, third) {
var _this3 = this,
_arguments = arguments;
if (typeof first === 'string' || array.isarray(first)) {
events.one(this.el_, first, fn.bind(this, second));
} else {
var target = first;
var type = second;
var fn = fn.bind(this, third);
var newfunc = function newfunc() {
_this3.off(target, type, newfunc);
fn.apply(null, _arguments);
};
// keep the same function id so we can remove it later
newfunc.guid = fn.guid;
this.on(target, type, newfunc);
}
return this;
};
/**
* trigger an event on an element.
*
* @param {eventtarget~event|object|string} event
* the event name, and event, or an event-like object with a type attribute
* set to the event name.
*
* @param {object} [hash]
* data hash to pass along with the event
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.trigger = function trigger(event, hash) {
events.trigger(this.el_, event, hash);
return this;
};
/**
* bind a listener to the component's ready state. if the ready event has already
* happened it will trigger the function immediately.
*
* @param {component~readycallback} fn
* a function to call when ready is triggered.
*
* @param {boolean} [sync=false]
* execute the listener synchronously if `component` is ready.
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.ready = function ready(fn) {
var sync = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (fn) {
if (this.isready_) {
if (sync) {
fn.call(this);
} else {
// call the function asynchronously by default for consistency
this.settimeout(fn, 1);
}
} else {
this.readyqueue_ = this.readyqueue_ || [];
this.readyqueue_.push(fn);
}
}
return this;
};
/**
* trigger all the ready listeners for this `component`.
*
* @fires component#ready
*/
component.prototype.triggerready = function triggerready() {
this.isready_ = true;
// ensure ready is triggerd asynchronously
this.settimeout(function () {
var readyqueue = this.readyqueue_;
// reset ready queue
this.readyqueue_ = [];
if (readyqueue && readyqueue.length > 0) {
readyqueue.foreach(function (fn) {
fn.call(this);
}, this);
}
// allow for using event listeners also
/**
* triggered when a `component` is ready.
*
* @event component#ready
* @type {eventtarget~event}
*/
this.trigger('ready');
}, 1);
};
/**
* find a single dom element matching a `selector`. this can be within the `component`s
* `contentel()` or another custom context.
*
* @param {string} selector
* a valid css selector, which will be passed to `queryselector`.
*
* @param {element|string} [context=this.contentel()]
* a dom element within which to query. can also be a selector string in
* which case the first matching element will get used as context. if
* missing `this.contentel()` gets used. if `this.contentel()` returns
* nothing it falls back to `document`.
*
* @return {element|null}
* the dom element that was found, or null
*
* @see [information on css selectors](https://developer.mozilla.org/en-us/docs/web/guide/css/getting_started/selectors)
*/
component.prototype.$ = function $(selector, context) {
return dom.$(selector, context || this.contentel());
};
/**
* finds all dom element matching a `selector`. this can be within the `component`s
* `contentel()` or another custom context.
*
* @param {string} selector
* a valid css selector, which will be passed to `queryselectorall`.
*
* @param {element|string} [context=this.contentel()]
* a dom element within which to query. can also be a selector string in
* which case the first matching element will get used as context. if
* missing `this.contentel()` gets used. if `this.contentel()` returns
* nothing it falls back to `document`.
*
* @return {nodelist}
* a list of dom elements that were found
*
* @see [information on css selectors](https://developer.mozilla.org/en-us/docs/web/guide/css/getting_started/selectors)
*/
component.prototype.$$ = function $$(selector, context) {
return dom.$$(selector, context || this.contentel());
};
/**
* check if a component's element has a css class name.
*
* @param {string} classtocheck
* css class name to check.
*
* @return {boolean}
* - true if the `component` has the class.
* - false if the `component` does not have the class`
*/
component.prototype.hasclass = function hasclass(classtocheck) {
return dom.haselclass(this.el_, classtocheck);
};
/**
* add a css class name to the `component`s element.
*
* @param {string} classtoadd
* css class name to add
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.addclass = function addclass(classtoadd) {
dom.addelclass(this.el_, classtoadd);
return this;
};
/**
* remove a css class name from the `component`s element.
*
* @param {string} classtoremove
* css class name to remove
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.removeclass = function removeclass(classtoremove) {
dom.removeelclass(this.el_, classtoremove);
return this;
};
/**
* add or remove a css class name from the component's element.
* - `classtotoggle` gets added when {@link component#hasclass} would return false.
* - `classtotoggle` gets removed when {@link component#hasclass} would return true.
*
* @param {string} classtotoggle
* the class to add or remove based on (@link component#hasclass}
*
* @param {boolean|dom~predicate} [predicate]
* an {@link dom~predicate} function or a boolean
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.toggleclass = function toggleclass(classtotoggle, predicate) {
dom.toggleelclass(this.el_, classtotoggle, predicate);
return this;
};
/**
* show the `component`s element if it is hidden by removing the
* 'vjs-hidden' class name from it.
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.show = function show() {
this.removeclass('vjs-hidden');
return this;
};
/**
* hide the `component`s element if it is currently showing by adding the
* 'vjs-hidden` class name to it.
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.hide = function hide() {
this.addclass('vjs-hidden');
return this;
};
/**
* lock a `component`s element in its visible state by adding the 'vjs-lock-showing'
* class name to it. used during fadein/fadeout.
*
* @return {component}
* returns itself; method can be chained.
*
* @private
*/
component.prototype.lockshowing = function lockshowing() {
this.addclass('vjs-lock-showing');
return this;
};
/**
* unlock a `component`s element from its visible state by removing the 'vjs-lock-showing'
* class name from it. used during fadein/fadeout.
*
* @return {component}
* returns itself; method can be chained.
*
* @private
*/
component.prototype.unlockshowing = function unlockshowing() {
this.removeclass('vjs-lock-showing');
return this;
};
/**
* get the value of an attribute on the `component`s element.
*
* @param {string} attribute
* name of the attribute to get the value from.
*
* @return {string|null}
* - the value of the attribute that was asked for.
* - can be an empty string on some browsers if the attribute does not exist
* or has no value
* - most browsers will return null if the attibute does not exist or has
* no value.
*
* @see [dom api]{@link https://developer.mozilla.org/en-us/docs/web/api/element/getattribute}
*/
component.prototype.getattribute = function getattribute(attribute) {
return dom.getattribute(this.el_, attribute);
};
/**
* set the value of an attribute on the `component`'s element
*
* @param {string} attribute
* name of the attribute to set.
*
* @param {string} value
* value to set the attribute to.
*
* @return {component}
* returns itself; method can be chained.
*
* @see [dom api]{@link https://developer.mozilla.org/en-us/docs/web/api/element/setattribute}
*/
component.prototype.setattribute = function setattribute(attribute, value) {
dom.setattribute(this.el_, attribute, value);
return this;
};
/**
* remove an attribute from the `component`s element.
*
* @param {string} attribute
* name of the attribute to remove.
*
* @return {component}
* returns itself; method can be chained.
*
* @see [dom api]{@link https://developer.mozilla.org/en-us/docs/web/api/element/removeattribute}
*/
component.prototype.removeattribute = function removeattribute(attribute) {
dom.removeattribute(this.el_, attribute);
return this;
};
/**
* get or set the width of the component based upon the css styles.
* see {@link component#dimension} for more detailed information.
*
* @param {number|string} [num]
* the width that you want to set postfixed with '%', 'px' or nothing.
*
* @param {boolean} [skiplisteners]
* skip the resize event trigger
*
* @return {component|number|string}
* - the width when getting, zero if there is no width. can be a string
* postpixed with '%' or 'px'.
* - returns itself when setting; method can be chained.
*/
component.prototype.width = function width(num, skiplisteners) {
return this.dimension('width', num, skiplisteners);
};
/**
* get or set the height of the component based upon the css styles.
* see {@link component#dimension} for more detailed information.
*
* @param {number|string} [num]
* the height that you want to set postfixed with '%', 'px' or nothing.
*
* @param {boolean} [skiplisteners]
* skip the resize event trigger
*
* @return {component|number|string}
* - the width when getting, zero if there is no width. can be a string
* postpixed with '%' or 'px'.
* - returns itself when setting; method can be chained.
*/
component.prototype.height = function height(num, skiplisteners) {
return this.dimension('height', num, skiplisteners);
};
/**
* set both the width and height of the `component` element at the same time.
*
* @param {number|string} width
* width to set the `component`s element to.
*
* @param {number|string} height
* height to set the `component`s element to.
*
* @return {component}
* returns itself; method can be chained.
*/
component.prototype.dimensions = function dimensions(width, height) {
// skip resize listeners on width for optimization
return this.width(width, true).height(height);
};
/**
* get or set width or height of the `component` element. this is the shared code
* for the {@link component#width} and {@link component#height}.
*
* things to know:
* - if the width or height in an number this will return the number postfixed with 'px'.
* - if the width/height is a percent this will return the percent postfixed with '%'
* - hidden elements have a width of 0 with `window.getcomputedstyle`. this function
* defaults to the `component`s `style.width` and falls back to `window.getcomputedstyle`.
* see [this]{@link http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/}
* for more information
* - if you want the computed style of the component, use {@link component#currentwidth}
* and {@link {component#currentheight}
*
* @fires component#resize
*
* @param {string} widthorheight
8 'width' or 'height'
*
* @param {number|string} [num]
8 new dimension
*
* @param {boolean} [skiplisteners]
* skip resize event trigger
*
* @return {component}
* - the dimension when getting or 0 if unset
* - returns itself when setting; method can be chained.
*/
component.prototype.dimension = function dimension(widthorheight, num, skiplisteners) {
if (num !== undefined) {
// set to zero if null or literally nan (nan !== nan)
if (num === null || num !== num) {
num = 0;
}
// check if using css width/height (% or px) and adjust
if (('' + num).indexof('%') !== -1 || ('' + num).indexof('px') !== -1) {
this.el_.style[widthorheight] = num;
} else if (num === 'auto') {
this.el_.style[widthorheight] = '';
} else {
this.el_.style[widthorheight] = num + 'px';
}
// skiplisteners allows us to avoid triggering the resize event when setting both width and height
if (!skiplisteners) {
/**
* triggered when a component is resized.
*
* @event component#resize
* @type {eventtarget~event}
*/
this.trigger('resize');
}
// return component
return this;
}
// not setting a value, so getting it
// make sure element exists
if (!this.el_) {
return 0;
}
// get dimension value from style
var val = this.el_.style[widthorheight];
var pxindex = val.indexof('px');
if (pxindex !== -1) {
// return the pixel value with no 'px'
return parseint(val.slice(0, pxindex), 10);
}
// no px so using % or no style was set, so falling back to offsetwidth/height
// if component has display:none, offset will return 0
// todo: handle display:none and no dimension style using px
return parseint(this.el_['offset' + (0, _totitlecase2['default'])(widthorheight)], 10);
};
/**
* get the width or the height of the `component` elements computed style. uses
* `window.getcomputedstyle`.
*
* @param {string} widthorheight
* a string containing 'width' or 'height'. whichever one you want to get.
*
* @return {number}
* the dimension that gets asked for or 0 if nothing was set
* for that dimension.
*/
component.prototype.currentdimension = function currentdimension(widthorheight) {
var computedwidthorheight = 0;
if (widthorheight !== 'width' && widthorheight !== 'height') {
throw new error('currentdimension only accepts width or height value');
}
if (typeof _window2['default'].getcomputedstyle === 'function') {
var computedstyle = _window2['default'].getcomputedstyle(this.el_);
computedwidthorheight = computedstyle.getpropertyvalue(widthorheight) || computedstyle[widthorheight];
}
// remove 'px' from variable and parse as integer
computedwidthorheight = parsefloat(computedwidthorheight);
// if the computed value is still 0, it's possible that the browser is lying
// and we want to check the offset values.
// this code also runs on ie8 and wherever getcomputedstyle doesn't exist.
if (computedwidthorheight === 0) {
var rule = 'offset' + (0, _totitlecase2['default'])(widthorheight);
computedwidthorheight = this.el_[rule];
}
return computedwidthorheight;
};
/**
* an object that contains width and height values of the `component`s
* computed style. uses `window.getcomputedstyle`.
*
* @typedef {object} component~dimensionobject
*
* @property {number} width
* the width of the `component`s computed style.
*
* @property {number} height
* the height of the `component`s computed style.
*/
/**
* get an object that contains width and height values of the `component`s
* computed style.
*
* @return {component~dimensionobject}
* the dimensions of the components element
*/
component.prototype.currentdimensions = function currentdimensions() {
return {
width: this.currentdimension('width'),
height: this.currentdimension('height')
};
};
/**
* get the width of the `component`s computed style. uses `window.getcomputedstyle`.
*
* @return {number} width
* the width of the `component`s computed style.
*/
component.prototype.currentwidth = function currentwidth() {
return this.currentdimension('width');
};
/**
* get the height of the `component`s computed style. uses `window.getcomputedstyle`.
*
* @return {number} height
* the height of the `component`s computed style.
*/
component.prototype.currentheight = function currentheight() {
return this.currentdimension('height');
};
/**
* set the focus to this component
*/
component.prototype.focus = function focus() {
this.el_.focus();
};
/**
* remove the focus from this component
*/
component.prototype.blur = function blur() {
this.el_.blur();
};
/**
* emit a 'tap' events when touch event support gets detected. this gets used to
* support toggling the controls through a tap on the video. they get enabled
* because every sub-component would have extra overhead otherwise.
*
* @private
* @fires component#tap
* @listens component#touchstart
* @listens component#touchmove
* @listens component#touchleave
* @listens component#touchcancel
* @listens component#touchend
*/
component.prototype.emittapevents = function emittapevents() {
// track the start time so we can determine how long the touch lasted
var touchstart = 0;
var firsttouch = null;
// maximum movement allowed during a touch event to still be considered a tap
// other popular libs use anywhere from 2 (hammer.js) to 15,
// so 10 seems like a nice, round number.
var tapmovementthreshold = 10;
// the maximum length a touch can be while still being considered a tap
var touchtimethreshold = 200;
var couldbetap = void 0;
this.on('touchstart', function (event) {
// if more than one finger, don't consider treating this as a click
if (event.touches.length === 1) {
// copy pagex/pagey from the object
firsttouch = {
pagex: event.touches[0].pagex,
pagey: event.touches[0].pagey
};
// record start time so we can detect a tap vs. "touch and hold"
touchstart = new date().gettime();
// reset couldbetap tracking
couldbetap = true;
}
});
this.on('touchmove', function (event) {
// if more than one finger, don't consider treating this as a click
if (event.touches.length > 1) {
couldbetap = false;
} else if (firsttouch) {
// some devices will throw touchmoves for all but the slightest of taps.
// so, if we moved only a small distance, this could still be a tap
var xdiff = event.touches[0].pagex - firsttouch.pagex;
var ydiff = event.touches[0].pagey - firsttouch.pagey;
var touchdistance = math.sqrt(xdiff * xdiff + ydiff * ydiff);
if (touchdistance > tapmovementthreshold) {
couldbetap = false;
}
}
});
var notap = function notap() {
couldbetap = false;
};
// todo: listen to the original target. http://youtu.be/dujfpxokup8?t=13m8s
this.on('touchleave', notap);
this.on('touchcancel', notap);
// when the touch ends, measure how long it took and trigger the appropriate
// event
this.on('touchend', function (event) {
firsttouch = null;
// proceed only if the touchmove/leave/cancel event didn't happen
if (couldbetap === true) {
// measure how long the touch lasted
var touchtime = new date().gettime() - touchstart;
// make sure the touch was less than the threshold to be considered a tap
if (touchtime < touchtimethreshold) {
// don't let browser turn this into a click
event.preventdefault();
/**
* triggered when a `component` is tapped.
*
* @event component#tap
* @type {eventtarget~event}
*/
this.trigger('tap');
// it may be good to copy the touchend event object and change the
// type to tap, if the other event properties aren't exact after
// events.fixevent runs (e.g. event.target)
}
}
});
};
/**
* this function reports user activity whenever touch events happen. this can get
* turned off by any sub-components that wants touch events to act another way.
*
* report user touch activity when touch events occur. user activity gets used to
* determine when controls should show/hide. it is simple when it comes to mouse
* events, because any mouse event should show the controls. so we capture mouse
* events that bubble up to the player and report activity when that happens.
* with touch events it isn't as easy as `touchstart` and `touchend` toggle player
* controls. so touch events can't help us at the player level either.
*
* user activity gets checked asynchronously. so what could happen is a tap event
* on the video turns the controls off. then the `touchend` event bubbles up to
* the player. which, if it reported user activity, would turn the controls right
* back on. we also don't want to completely block touch events from bubbling up.
* furthermore a `touchmove` event and anything other than a tap, should not turn
* controls back on.
*
* @listens component#touchstart
* @listens component#touchmove
* @listens component#touchend
* @listens component#touchcancel
*/
component.prototype.enabletouchactivity = function enabletouchactivity() {
// don't continue if the root player doesn't support reporting user activity
if (!this.player() || !this.player().reportuseractivity) {
return;
}
// listener for reporting that the user is active
var report = fn.bind(this.player(), this.player().reportuseractivity);
var touchholding = void 0;
this.on('touchstart', function () {
report();
// for as long as the they are touching the device or have their mouse down,
// we consider them active even if they're not moving their finger or mouse.
// so we want to continue to update that they are active
this.clearinterval(touchholding);
// report at the same interval as activitycheck
touchholding = this.setinterval(report, 250);
});
var touchend = function touchend(event) {
report();
// stop the interval that maintains activity if the touch is holding
this.clearinterval(touchholding);
};
this.on('touchmove', report);
this.on('touchend', touchend);
this.on('touchcancel', touchend);
};
/**
* a callback that has no parameters and is bound into `component`s context.
*
* @callback component~genericcallback
* @this component
*/
/**
* creates a function that runs after an `x` millisecond timeout. this function is a
* wrapper around `window.settimeout`. there are a few reasons to use this one
* instead though:
* 1. it gets cleared via {@link component#cleartimeout} when
* {@link component#dispose} gets called.
* 2. the function callback will gets turned into a {@link component~genericcallback}
*
* > note: you can use `window.cleartimeout` on the id returned by this function. this
* will cause its dispose listener not to get cleaned up! please use
* {@link component#cleartimeout} or {@link component#dispose}.
*
* @param {component~genericcallback} fn
* the function that will be run after `timeout`.
*
* @param {number} timeout
* timeout in milliseconds to delay before executing the specified function.
*
* @return {number}
* returns a timeout id that gets used to identify the timeout. it can also
* get used in {@link component#cleartimeout} to clear the timeout that
* was set.
*
* @listens component#dispose
* @see [similar to]{@link https://developer.mozilla.org/en-us/docs/web/api/windowtimers/settimeout}
*/
component.prototype.settimeout = function settimeout(fn, timeout) {
fn = fn.bind(this, fn);
var timeoutid = _window2['default'].settimeout(fn, timeout);
var disposefn = function disposefn() {
this.cleartimeout(timeoutid);
};
disposefn.guid = 'vjs-timeout-' + timeoutid;
this.on('dispose', disposefn);
return timeoutid;
};
/**
* clears a timeout that gets created via `window.settimeout` or
* {@link component#settimeout}. if you set a timeout via {@link component#settimeout}
* use this function instead of `window.cleartimout`. if you don't your dispose
* listener will not get cleaned up until {@link component#dispose}!
*
* @param {number} timeoutid
* the id of the timeout to clear. the return value of
* {@link component#settimeout} or `window.settimeout`.
*
* @return {number}
* returns the timeout id that was cleared.
*
* @see [similar to]{@link https://developer.mozilla.org/en-us/docs/web/api/windowtimers/cleartimeout}
*/
component.prototype.cleartimeout = function cleartimeout(timeoutid) {
_window2['default'].cleartimeout(timeoutid);
var disposefn = function disposefn() {};
disposefn.guid = 'vjs-timeout-' + timeoutid;
this.off('dispose', disposefn);
return timeoutid;
};
/**
* creates a function that gets run every `x` milliseconds. this function is a wrapper
* around `window.setinterval`. there are a few reasons to use this one instead though.
* 1. it gets cleared via {@link component#clearinterval} when
* {@link component#dispose} gets called.
* 2. the function callback will be a {@link component~genericcallback}
*
* @param {component~genericcallback} fn
* the function to run every `x` seconds.
*
* @param {number} interval
* execute the specified function every `x` milliseconds.
*
* @return {number}
* returns an id that can be used to identify the interval. it can also be be used in
* {@link component#clearinterval} to clear the interval.
*
* @listens component#dispose
* @see [similar to]{@link https://developer.mozilla.org/en-us/docs/web/api/windowtimers/setinterval}
*/
component.prototype.setinterval = function setinterval(fn, interval) {
fn = fn.bind(this, fn);
var intervalid = _window2['default'].setinterval(fn, interval);
var disposefn = function disposefn() {
this.clearinterval(intervalid);
};
disposefn.guid = 'vjs-interval-' + intervalid;
this.on('dispose', disposefn);
return intervalid;
};
/**
* clears an interval that gets created via `window.setinterval` or
* {@link component#setinterval}. if you set an inteval via {@link component#setinterval}
* use this function instead of `window.clearinterval`. if you don't your dispose
* listener will not get cleaned up until {@link component#dispose}!
*
* @param {number} intervalid
* the id of the interval to clear. the return value of
* {@link component#setinterval} or `window.setinterval`.
*
* @return {number}
* returns the interval id that was cleared.
*
* @see [similar to]{@link https://developer.mozilla.org/en-us/docs/web/api/windowtimers/clearinterval}
*/
component.prototype.clearinterval = function clearinterval(intervalid) {
_window2['default'].clearinterval(intervalid);
var disposefn = function disposefn() {};
disposefn.guid = 'vjs-interval-' + intervalid;
this.off('dispose', disposefn);
return intervalid;
};
/**
* register a `component` with `videojs` given the name and the component.
*
* > note: {@link tech}s should not be registered as a `component`. {@link tech}s
* should be registered using {@link tech.registertech} or
* {@link videojs:videojs.registertech}.
*
* > note: this function can also be seen on videojs as
* {@link videojs:videojs.registercomponent}.
*
* @param {string} name
* the name of the `component` to register.
*
* @param {component} comp
* the `component` class to register.
*
* @return {component}
* the `component` that was registered.
*/
component.registercomponent = function registercomponent(name, comp) {
if (!name) {
return;
}
name = (0, _totitlecase2['default'])(name);
if (!component.components_) {
component.components_ = {};
}
if (name === 'player' && component.components_[name]) {
var player = component.components_[name];
// if we have players that were disposed, then their name will still be
// in players.players. so, we must loop through and verify that the value
// for each item is not null. this allows registration of the player component
// after all players have been disposed or before any were created.
if (player.players && object.keys(player.players).length > 0 && object.keys(player.players).map(function (playername) {
return player.players[playername];
}).every(boolean)) {
throw new error('can not register player component after player has been created');
}
}
component.components_[name] = comp;
return comp;
};
/**
* get a `component` based on the name it was registered with.
*
* @param {string} name
* the name of the component to get.
*
* @return {component}
* the `component` that got registered under the given name.
*
* @deprecated in `videojs` 6 this will not return `component`s that were not
* registered using {@link component.registercomponent}. currently we
* check the global `videojs` object for a `component` name and
* return that if it exists.
*/
component.getcomponent = function getcomponent(name) {
if (!name) {
return;
}
name = (0, _totitlecase2['default'])(name);
if (component.components_ && component.components_[name]) {
return component.components_[name];
}
if (_window2['default'] && _window2['default'].videojs && _window2['default'].videojs[name]) {
_log2['default'].warn('the ' + name + ' component was added to the videojs object when it should be registered using videojs.registercomponent(name, component)');
return _window2['default'].videojs[name];
}
};
/**
* sets up the constructor using the supplied init method or uses the init of the
* parent object.
*
* @param {object} [props={}]
* an object of properties.
*
* @return {object}
* the extended object.
*
* @deprecated since version 5
*/
component.extend = function extend(props) {
props = props || {};
_log2['default'].warn('component.extend({}) has been deprecated, ' + ' use videojs.extend(component, {}) instead');
// set up the constructor using the supplied init method
// or using the init of the parent object
// make sure to check the unobfuscated version for external libs
var init = props.init || props.init || this.prototype.init || this.prototype.init || function () {};
// in resig's simple class inheritance (previously used) the constructor
// is a function that calls `this.init.apply(arguments)`
// however that would prevent us from using `parentobject.call(this);`
// in a child constructor because the `this` in `this.init`
// would still refer to the child and cause an infinite loop.
// we would instead have to do
// `parentobject.prototype.init.apply(this, arguments);`
// bleh. we're not creating a _super() function, so it's good to keep
// the parent constructor reference simple.
var subobj = function subobj() {
init.apply(this, arguments);
};
// inherit from this object's prototype
subobj.prototype = object.create(this.prototype);
// reset the constructor property for subobj otherwise
// instances of subobj would have the constructor of the parent object
subobj.prototype.constructor = subobj;
// make the class extendable
subobj.extend = component.extend;
// extend subobj's prototype with functions and other properties from props
for (var name in props) {
if (props.hasownproperty(name)) {
subobj.prototype[name] = props[name];
}
}
return subobj;
};
return component;
}();
component.registercomponent('component', component);
exports['default'] = component;
},{"81":81,"82":82,"83":83,"85":85,"86":86,"87":87,"91":91,"95":95}],6:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _trackbutton = _dereq_(36);
var _trackbutton2 = _interoprequiredefault(_trackbutton);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _audiotrackmenuitem = _dereq_(7);
var _audiotrackmenuitem2 = _interoprequiredefault(_audiotrackmenuitem);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file audio-track-button.js
*/
/**
* the base class for buttons that toggle specific {@link audiotrack} types.
*
* @extends trackbutton
*/
var audiotrackbutton = function (_trackbutton) {
_inherits(audiotrackbutton, _trackbutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options={}]
* the key/value store of player options.
*/
function audiotrackbutton(player) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classcallcheck(this, audiotrackbutton);
options.tracks = player.audiotracks && player.audiotracks();
var _this = _possibleconstructorreturn(this, _trackbutton.call(this, player, options));
_this.el_.setattribute('aria-label', 'audio menu');
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
audiotrackbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-audio-button ' + _trackbutton.prototype.buildcssclass.call(this);
};
/**
* create a menu item for each audio track
*
* @param {audiotrackmenuitem[]} [items=[]]
* an array of existing menu items to use.
*
* @return {audiotrackmenuitem[]}
* an array of menu items
*/
audiotrackbutton.prototype.createitems = function createitems() {
var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
// if there's only one audio track, there no point in showing it
this.hidethreshold_ = 1;
var tracks = this.player_.audiotracks && this.player_.audiotracks();
if (!tracks) {
return items;
}
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
items.push(new _audiotrackmenuitem2['default'](this.player_, {
track: track,
// menuitem is selectable
selectable: true
}));
}
return items;
};
return audiotrackbutton;
}(_trackbutton2['default']);
/**
* the text that should display over the `audiotrackbutton`s controls. added for localization.
*
* @type {string}
* @private
*/
audiotrackbutton.prototype.controltext_ = 'audio track';
_component2['default'].registercomponent('audiotrackbutton', audiotrackbutton);
exports['default'] = audiotrackbutton;
},{"36":36,"5":5,"7":7}],7:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _menuitem = _dereq_(48);
var _menuitem2 = _interoprequiredefault(_menuitem);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file audio-track-menu-item.js
*/
/**
* an {@link audiotrack} {@link menuitem}
*
* @extends menuitem
*/
var audiotrackmenuitem = function (_menuitem) {
_inherits(audiotrackmenuitem, _menuitem);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function audiotrackmenuitem(player, options) {
_classcallcheck(this, audiotrackmenuitem);
var track = options.track;
var tracks = player.audiotracks();
// modify options for parent menuitem class's init.
options.label = track.label || track.language || 'unknown';
options.selected = track.enabled;
var _this = _possibleconstructorreturn(this, _menuitem.call(this, player, options));
_this.track = track;
if (tracks) {
var changehandler = fn.bind(_this, _this.handletrackschange);
tracks.addeventlistener('change', changehandler);
_this.on('dispose', function () {
tracks.removeeventlistener('change', changehandler);
});
}
return _this;
}
/**
* this gets called when an `audiotrackmenuitem is "clicked". see {@link clickablecomponent}
* for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
audiotrackmenuitem.prototype.handleclick = function handleclick(event) {
var tracks = this.player_.audiotracks();
_menuitem.prototype.handleclick.call(this, event);
if (!tracks) {
return;
}
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
track.enabled = track === this.track;
}
};
/**
* handle any {@link audiotrack} change.
*
* @param {eventtarget~event} [event]
* the {@link audiotracklist#change} event that caused this to run.
*
* @listens audiotracklist#change
*/
audiotrackmenuitem.prototype.handletrackschange = function handletrackschange(event) {
this.selected(this.track.enabled);
};
return audiotrackmenuitem;
}(_menuitem2['default']);
_component2['default'].registercomponent('audiotrackmenuitem', audiotrackmenuitem);
exports['default'] = audiotrackmenuitem;
},{"48":48,"5":5,"83":83}],8:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
_dereq_(12);
_dereq_(32);
_dereq_(33);
_dereq_(35);
_dereq_(34);
_dereq_(10);
_dereq_(18);
_dereq_(9);
_dereq_(38);
_dereq_(40);
_dereq_(11);
_dereq_(25);
_dereq_(27);
_dereq_(29);
_dereq_(24);
_dereq_(6);
_dereq_(13);
_dereq_(21);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file control-bar.js
*/
// required children
/**
* container of main controls.
*
* @extends component
*/
var controlbar = function (_component) {
_inherits(controlbar, _component);
function controlbar() {
_classcallcheck(this, controlbar);
return _possibleconstructorreturn(this, _component.apply(this, arguments));
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
controlbar.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-control-bar',
dir: 'ltr'
}, {
// the control bar is a group, so it can contain menuitems
role: 'group'
});
};
return controlbar;
}(_component2['default']);
/**
* default options for `controlbar`
*
* @type {object}
* @private
*/
controlbar.prototype.options_ = {
children: ['playtoggle', 'volumemenubutton', 'currenttimedisplay', 'timedivider', 'durationdisplay', 'progresscontrol', 'livedisplay', 'remainingtimedisplay', 'customcontrolspacer', 'playbackratemenubutton', 'chaptersbutton', 'descriptionsbutton', 'subtitlesbutton', 'captionsbutton', 'audiotrackbutton', 'fullscreentoggle']
};
_component2['default'].registercomponent('controlbar', controlbar);
exports['default'] = controlbar;
},{"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){
'use strict';
exports.__esmodule = true;
var _button = _dereq_(2);
var _button2 = _interoprequiredefault(_button);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file fullscreen-toggle.js
*/
/**
* toggle fullscreen video
*
* @extends button
*/
var fullscreentoggle = function (_button) {
_inherits(fullscreentoggle, _button);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function fullscreentoggle(player, options) {
_classcallcheck(this, fullscreentoggle);
var _this = _possibleconstructorreturn(this, _button.call(this, player, options));
_this.on(player, 'fullscreenchange', _this.handlefullscreenchange);
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
fullscreentoggle.prototype.buildcssclass = function buildcssclass() {
return 'vjs-fullscreen-control ' + _button.prototype.buildcssclass.call(this);
};
/**
* handles fullscreenchange on the player and change control text accordingly.
*
* @param {eventtarget~event} [event]
* the {@link player#fullscreenchange} event that caused this function to be
* called.
*
* @listens player#fullscreenchange
*/
fullscreentoggle.prototype.handlefullscreenchange = function handlefullscreenchange(event) {
if (this.player_.isfullscreen()) {
this.controltext('non-fullscreen');
} else {
this.controltext('fullscreen');
}
};
/**
* this gets called when an `fullscreentoggle` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
fullscreentoggle.prototype.handleclick = function handleclick(event) {
if (!this.player_.isfullscreen()) {
this.player_.requestfullscreen();
} else {
this.player_.exitfullscreen();
}
};
return fullscreentoggle;
}(_button2['default']);
/**
* the text that should display over the `fullscreentoggle`s controls. added for localization.
*
* @type {string}
* @private
*/
fullscreentoggle.prototype.controltext_ = 'fullscreen';
_component2['default'].registercomponent('fullscreentoggle', fullscreentoggle);
exports['default'] = fullscreentoggle;
},{"2":2,"5":5}],10:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file live-display.js
*/
// todo - future make it click to snap to live
/**
* displays the live indicator when duration is infinity.
*
* @extends component
*/
var livedisplay = function (_component) {
_inherits(livedisplay, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function livedisplay(player, options) {
_classcallcheck(this, livedisplay);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.updateshowing();
_this.on(_this.player(), 'durationchange', _this.updateshowing);
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
livedisplay.prototype.createel = function createel() {
var el = _component.prototype.createel.call(this, 'div', {
classname: 'vjs-live-control vjs-control'
});
this.contentel_ = dom.createel('div', {
classname: 'vjs-live-display',
innerhtml: '' + this.localize('stream type') + '' + this.localize('live')
}, {
'aria-live': 'off'
});
el.appendchild(this.contentel_);
return el;
};
/**
* check the duration to see if the livedisplay should be showing or not. then show/hide
* it accordingly
*
* @param {eventtarget~event} [event]
* the {@link player#durationchange} event that caused this function to run.
*
* @listens player#durationchange
*/
livedisplay.prototype.updateshowing = function updateshowing(event) {
if (this.player().duration() === infinity) {
this.show();
} else {
this.hide();
}
};
return livedisplay;
}(_component2['default']);
_component2['default'].registercomponent('livedisplay', livedisplay);
exports['default'] = livedisplay;
},{"5":5,"81":81}],11:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _button = _dereq_(2);
var _button2 = _interoprequiredefault(_button);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file mute-toggle.js
*/
/**
* a button component for muting the audio.
*
* @extends button
*/
var mutetoggle = function (_button) {
_inherits(mutetoggle, _button);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function mutetoggle(player, options) {
_classcallcheck(this, mutetoggle);
var _this = _possibleconstructorreturn(this, _button.call(this, player, options));
_this.on(player, 'volumechange', _this.update);
// hide mute toggle if the current tech doesn't support volume control
if (player.tech_ && player.tech_.featuresvolumecontrol === false) {
_this.addclass('vjs-hidden');
}
_this.on(player, 'loadstart', function () {
// we need to update the button to account for a default muted state.
this.update();
if (player.tech_.featuresvolumecontrol === false) {
this.addclass('vjs-hidden');
} else {
this.removeclass('vjs-hidden');
}
});
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
mutetoggle.prototype.buildcssclass = function buildcssclass() {
return 'vjs-mute-control ' + _button.prototype.buildcssclass.call(this);
};
/**
* this gets called when an `mutetoggle` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
mutetoggle.prototype.handleclick = function handleclick(event) {
this.player_.muted(this.player_.muted() ? false : true);
};
/**
* update the state of volume.
*
* @param {eventtarget~event} [event]
* the {@link player#loadstart} event if this function was called through an
* event.
*
* @listens player#loadstart
*/
mutetoggle.prototype.update = function update(event) {
var vol = this.player_.volume();
var level = 3;
if (vol === 0 || this.player_.muted()) {
level = 0;
} else if (vol < 0.33) {
level = 1;
} else if (vol < 0.67) {
level = 2;
}
// don't rewrite the button text if the actual text doesn't change.
// this causes unnecessary and confusing information for screen reader users.
// this check is needed because this function gets called every time the volume level is changed.
var tomute = this.player_.muted() ? 'unmute' : 'mute';
if (this.controltext() !== tomute) {
this.controltext(tomute);
}
// todo improve muted icon classes
for (var i = 0; i < 4; i++) {
dom.removeelclass(this.el_, 'vjs-vol-' + i);
}
dom.addelclass(this.el_, 'vjs-vol-' + level);
};
return mutetoggle;
}(_button2['default']);
/**
* the text that should display over the `mutetoggle`s controls. added for localization.
*
* @type {string}
* @private
*/
mutetoggle.prototype.controltext_ = 'mute';
_component2['default'].registercomponent('mutetoggle', mutetoggle);
exports['default'] = mutetoggle;
},{"2":2,"5":5,"81":81}],12:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _button = _dereq_(2);
var _button2 = _interoprequiredefault(_button);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file play-toggle.js
*/
/**
* button to toggle between play and pause.
*
* @extends button
*/
var playtoggle = function (_button) {
_inherits(playtoggle, _button);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function playtoggle(player, options) {
_classcallcheck(this, playtoggle);
var _this = _possibleconstructorreturn(this, _button.call(this, player, options));
_this.on(player, 'play', _this.handleplay);
_this.on(player, 'pause', _this.handlepause);
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
playtoggle.prototype.buildcssclass = function buildcssclass() {
return 'vjs-play-control ' + _button.prototype.buildcssclass.call(this);
};
/**
* this gets called when an `playtoggle` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
playtoggle.prototype.handleclick = function handleclick(event) {
if (this.player_.paused()) {
this.player_.play();
} else {
this.player_.pause();
}
};
/**
* add the vjs-playing class to the element so it can change appearance.
*
* @param {eventtarget~event} [event]
* the event that caused this function to run.
*
* @listens player#play
*/
playtoggle.prototype.handleplay = function handleplay(event) {
this.removeclass('vjs-paused');
this.addclass('vjs-playing');
// change the button text to "pause"
this.controltext('pause');
};
/**
* add the vjs-paused class to the element so it can change appearance.
*
* @param {eventtarget~event} [event]
* the event that caused this function to run.
*
* @listens player#pause
*/
playtoggle.prototype.handlepause = function handlepause(event) {
this.removeclass('vjs-playing');
this.addclass('vjs-paused');
// change the button text to "play"
this.controltext('play');
};
return playtoggle;
}(_button2['default']);
/**
* the text that should display over the `playtoggle`s controls. added for localization.
*
* @type {string}
* @private
*/
playtoggle.prototype.controltext_ = 'play';
_component2['default'].registercomponent('playtoggle', playtoggle);
exports['default'] = playtoggle;
},{"2":2,"5":5}],13:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _menubutton = _dereq_(47);
var _menubutton2 = _interoprequiredefault(_menubutton);
var _menu = _dereq_(49);
var _menu2 = _interoprequiredefault(_menu);
var _playbackratemenuitem = _dereq_(14);
var _playbackratemenuitem2 = _interoprequiredefault(_playbackratemenuitem);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file playback-rate-menu-button.js
*/
/**
* the component for controlling the playback rate.
*
* @extends menubutton
*/
var playbackratemenubutton = function (_menubutton) {
_inherits(playbackratemenubutton, _menubutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function playbackratemenubutton(player, options) {
_classcallcheck(this, playbackratemenubutton);
var _this = _possibleconstructorreturn(this, _menubutton.call(this, player, options));
_this.updatevisibility();
_this.updatelabel();
_this.on(player, 'loadstart', _this.updatevisibility);
_this.on(player, 'ratechange', _this.updatelabel);
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
playbackratemenubutton.prototype.createel = function createel() {
var el = _menubutton.prototype.createel.call(this);
this.labelel_ = dom.createel('div', {
classname: 'vjs-playback-rate-value',
innerhtml: 1.0
});
el.appendchild(this.labelel_);
return el;
};
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
playbackratemenubutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-playback-rate ' + _menubutton.prototype.buildcssclass.call(this);
};
/**
* create the playback rate menu
*
* @return {menu}
* menu object populated with {@link playbackratemenuitem}s
*/
playbackratemenubutton.prototype.createmenu = function createmenu() {
var menu = new _menu2['default'](this.player());
var rates = this.playbackrates();
if (rates) {
for (var i = rates.length - 1; i >= 0; i--) {
menu.addchild(new _playbackratemenuitem2['default'](this.player(), { rate: rates[i] + 'x' }));
}
}
return menu;
};
/**
* updates aria accessibility attributes
*/
playbackratemenubutton.prototype.updateariaattributes = function updateariaattributes() {
// current playback rate
this.el().setattribute('aria-valuenow', this.player().playbackrate());
};
/**
* this gets called when an `playbackratemenubutton` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
playbackratemenubutton.prototype.handleclick = function handleclick(event) {
// select next rate option
var currentrate = this.player().playbackrate();
var rates = this.playbackrates();
// this will select first one if the last one currently selected
var newrate = rates[0];
for (var i = 0; i < rates.length; i++) {
if (rates[i] > currentrate) {
newrate = rates[i];
break;
}
}
this.player().playbackrate(newrate);
};
/**
* get possible playback rates
*
* @return {array}
* all possible playback rates
*/
playbackratemenubutton.prototype.playbackrates = function playbackrates() {
return this.options_.playbackrates || this.options_.playeroptions && this.options_.playeroptions.playbackrates;
};
/**
* get whether playback rates is supported by the tech
* and an array of playback rates exists
*
* @return {boolean}
* whether changing playback rate is supported
*/
playbackratemenubutton.prototype.playbackratesupported = function playbackratesupported() {
return this.player().tech_ && this.player().tech_.featuresplaybackrate && this.playbackrates() && this.playbackrates().length > 0;
};
/**
* hide playback rate controls when they're no playback rate options to select
*
* @param {eventtarget~event} [event]
* the event that caused this function to run.
*
* @listens player#loadstart
*/
playbackratemenubutton.prototype.updatevisibility = function updatevisibility(event) {
if (this.playbackratesupported()) {
this.removeclass('vjs-hidden');
} else {
this.addclass('vjs-hidden');
}
};
/**
* update button label when rate changed
*
* @param {eventtarget~event} [event]
* the event that caused this function to run.
*
* @listens player#ratechange
*/
playbackratemenubutton.prototype.updatelabel = function updatelabel(event) {
if (this.playbackratesupported()) {
this.labelel_.innerhtml = this.player().playbackrate() + 'x';
}
};
return playbackratemenubutton;
}(_menubutton2['default']);
/**
* the text that should display over the `fullscreentoggle`s controls. added for localization.
*
* @type {string}
* @private
*/
playbackratemenubutton.prototype.controltext_ = 'playback rate';
_component2['default'].registercomponent('playbackratemenubutton', playbackratemenubutton);
exports['default'] = playbackratemenubutton;
},{"14":14,"47":47,"49":49,"5":5,"81":81}],14:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _menuitem = _dereq_(48);
var _menuitem2 = _interoprequiredefault(_menuitem);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file playback-rate-menu-item.js
*/
/**
* the specific menu item type for selecting a playback rate.
*
* @extends menuitem
*/
var playbackratemenuitem = function (_menuitem) {
_inherits(playbackratemenuitem, _menuitem);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function playbackratemenuitem(player, options) {
_classcallcheck(this, playbackratemenuitem);
var label = options.rate;
var rate = parsefloat(label, 10);
// modify options for parent menuitem class's init.
options.label = label;
options.selected = rate === 1;
options.selectable = true;
var _this = _possibleconstructorreturn(this, _menuitem.call(this, player, options));
_this.label = label;
_this.rate = rate;
_this.on(player, 'ratechange', _this.update);
return _this;
}
/**
* this gets called when an `playbackratemenuitem` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
playbackratemenuitem.prototype.handleclick = function handleclick(event) {
_menuitem.prototype.handleclick.call(this);
this.player().playbackrate(this.rate);
};
/**
* update the playbackratemenuitem when the playbackrate changes.
*
* @param {eventtarget~event} [event]
* the `ratechange` event that caused this function to run.
*
* @listens player#ratechange
*/
playbackratemenuitem.prototype.update = function update(event) {
this.selected(this.player().playbackrate() === this.rate);
};
return playbackratemenuitem;
}(_menuitem2['default']);
/**
* the text that should display over the `playbackratemenuitem`s controls. added for localization.
*
* @type {string}
* @private
*/
playbackratemenuitem.prototype.contenteltype = 'button';
_component2['default'].registercomponent('playbackratemenuitem', playbackratemenuitem);
exports['default'] = playbackratemenuitem;
},{"48":48,"5":5}],15:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file load-progress-bar.js
*/
/**
* shows loading progress
*
* @extends component
*/
var loadprogressbar = function (_component) {
_inherits(loadprogressbar, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function loadprogressbar(player, options) {
_classcallcheck(this, loadprogressbar);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.partels_ = [];
_this.on(player, 'progress', _this.update);
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
loadprogressbar.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-load-progress',
innerhtml: '' + this.localize('loaded') + ': 0%'
});
};
/**
* update progress bar
*
* @param {eventtarget~event} [event]
* the `progress` event that caused this function to run.
*
* @listens player#progress
*/
loadprogressbar.prototype.update = function update(event) {
var buffered = this.player_.buffered();
var duration = this.player_.duration();
var bufferedend = this.player_.bufferedend();
var children = this.partels_;
// get the percent width of a time compared to the total end
var percentify = function percentify(time, end) {
// no nan
var percent = time / end || 0;
return (percent >= 1 ? 1 : percent) * 100 + '%';
};
// update the width of the progress bar
this.el_.style.width = percentify(bufferedend, duration);
// add child elements to represent the individual buffered time ranges
for (var i = 0; i < buffered.length; i++) {
var start = buffered.start(i);
var end = buffered.end(i);
var part = children[i];
if (!part) {
part = this.el_.appendchild(dom.createel());
children[i] = part;
}
// set the percent based on the width of the progress bar (bufferedend)
part.style.left = percentify(start, bufferedend);
part.style.width = percentify(end - start, bufferedend);
}
// remove unused buffered range elements
for (var _i = children.length; _i > buffered.length; _i--) {
this.el_.removechild(children[_i - 1]);
}
children.length = buffered.length;
};
return loadprogressbar;
}(_component2['default']);
_component2['default'].registercomponent('loadprogressbar', loadprogressbar);
exports['default'] = loadprogressbar;
},{"5":5,"81":81}],16:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _formattime = _dereq_(84);
var _formattime2 = _interoprequiredefault(_formattime);
var _computedstyle = _dereq_(80);
var _computedstyle2 = _interoprequiredefault(_computedstyle);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file mouse-time-display.js
*/
/**
* the mouse time display component shows the time you will seek to
* when hovering over the progress bar
*
* @extends component
*/
var mousetimedisplay = function (_component) {
_inherits(mousetimedisplay, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function mousetimedisplay(player, options) {
_classcallcheck(this, mousetimedisplay);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
if (options.playeroptions && options.playeroptions.controlbar && options.playeroptions.controlbar.progresscontrol && options.playeroptions.controlbar.progresscontrol.keeptooltipsinside) {
_this.keeptooltipsinside = options.playeroptions.controlbar.progresscontrol.keeptooltipsinside;
}
if (_this.keeptooltipsinside) {
_this.tooltip = dom.createel('div', { classname: 'vjs-time-tooltip' });
_this.el().appendchild(_this.tooltip);
_this.addclass('vjs-keep-tooltips-inside');
}
_this.update(0, 0);
player.on('ready', function () {
_this.on(player.controlbar.progresscontrol.el(), 'mousemove', fn.throttle(fn.bind(_this, _this.handlemousemove), 25));
});
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
mousetimedisplay.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-mouse-display'
});
};
/**
* handle the mouse move event on the `mousetimedisplay`.
*
* @param {eventtarget~event} event
* the `mousemove` event that caused this to event to run.
*
* @listen mousemove
*/
mousetimedisplay.prototype.handlemousemove = function handlemousemove(event) {
var duration = this.player_.duration();
var newtime = this.calculatedistance(event) * duration;
var position = event.pagex - dom.findelposition(this.el().parentnode).left;
this.update(newtime, position);
};
/**
* update the time and posistion of the `mousetimedisplay`.
*
* @param {number} newtime
* time to change the `mousetimedisplay` to.
*
* @param {nubmer} position
* postion from the left of the in pixels.
*/
mousetimedisplay.prototype.update = function update(newtime, position) {
var time = (0, _formattime2['default'])(newtime, this.player_.duration());
this.el().style.left = position + 'px';
this.el().setattribute('data-current-time', time);
if (this.keeptooltipsinside) {
var clampedposition = this.clampposition_(position);
var difference = position - clampedposition + 1;
var tooltipwidth = parsefloat((0, _computedstyle2['default'])(this.tooltip, 'width'));
var tooltipwidthhalf = tooltipwidth / 2;
this.tooltip.innerhtml = time;
this.tooltip.style.right = '-' + (tooltipwidthhalf - difference) + 'px';
}
};
/**
* get the mouse pointers x coordinate in pixels.
*
* @param {eventtarget~event} [event]
* the `mousemove` event that was passed to this function by
* {@link mousetimedisplay#handlemousemove}
*
* @return {number}
* the x position in pixels of the mouse pointer.
*/
mousetimedisplay.prototype.calculatedistance = function calculatedistance(event) {
return dom.getpointerposition(this.el().parentnode, event).x;
};
/**
* this takes in a horizontal position for the bar and returns a clamped position.
* clamped position means that it will keep the position greater than half the width
* of the tooltip and smaller than the player width minus half the width o the tooltip.
* it will only clamp the position if `keeptooltipsinside` option is set.
*
* @param {number} position
* the position the bar wants to be
*
* @return {number}
* the (potentially) new clamped position.
*
* @private
*/
mousetimedisplay.prototype.clampposition_ = function clampposition_(position) {
if (!this.keeptooltipsinside) {
return position;
}
var playerwidth = parsefloat((0, _computedstyle2['default'])(this.player().el(), 'width'));
var tooltipwidth = parsefloat((0, _computedstyle2['default'])(this.tooltip, 'width'));
var tooltipwidthhalf = tooltipwidth / 2;
var actualposition = position;
if (position < tooltipwidthhalf) {
actualposition = math.ceil(tooltipwidthhalf);
} else if (position > playerwidth - tooltipwidthhalf) {
actualposition = math.floor(playerwidth - tooltipwidthhalf);
}
return actualposition;
};
return mousetimedisplay;
}(_component2['default']);
_component2['default'].registercomponent('mousetimedisplay', mousetimedisplay);
exports['default'] = mousetimedisplay;
},{"5":5,"80":80,"81":81,"83":83,"84":84}],17:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _formattime = _dereq_(84);
var _formattime2 = _interoprequiredefault(_formattime);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file play-progress-bar.js
*/
/**
* shows play progress
*
* @extends component
*/
var playprogressbar = function (_component) {
_inherits(playprogressbar, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function playprogressbar(player, options) {
_classcallcheck(this, playprogressbar);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.updatedataattr();
_this.on(player, 'timeupdate', _this.updatedataattr);
player.ready(fn.bind(_this, _this.updatedataattr));
if (options.playeroptions && options.playeroptions.controlbar && options.playeroptions.controlbar.progresscontrol && options.playeroptions.controlbar.progresscontrol.keeptooltipsinside) {
_this.keeptooltipsinside = options.playeroptions.controlbar.progresscontrol.keeptooltipsinside;
}
if (_this.keeptooltipsinside) {
_this.addclass('vjs-keep-tooltips-inside');
}
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
playprogressbar.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-play-progress vjs-slider-bar',
innerhtml: '' + this.localize('progress') + ': 0%'
});
};
/**
* update the data-current-time attribute on the `playprogressbar`.
*
* @param {eventtarget~event} [event]
* the `timeupdate` event that caused this to run.
*
* @listens player#timeupdate
*/
playprogressbar.prototype.updatedataattr = function updatedataattr(event) {
var time = this.player_.scrubbing() ? this.player_.getcache().currenttime : this.player_.currenttime();
this.el_.setattribute('data-current-time', (0, _formattime2['default'])(time, this.player_.duration()));
};
return playprogressbar;
}(_component2['default']);
_component2['default'].registercomponent('playprogressbar', playprogressbar);
exports['default'] = playprogressbar;
},{"5":5,"83":83,"84":84}],18:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
_dereq_(19);
_dereq_(16);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file progress-control.js
*/
/**
* the progress control component contains the seek bar, load progress,
* and play progress.
*
* @extends component
*/
var progresscontrol = function (_component) {
_inherits(progresscontrol, _component);
function progresscontrol() {
_classcallcheck(this, progresscontrol);
return _possibleconstructorreturn(this, _component.apply(this, arguments));
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
progresscontrol.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-progress-control vjs-control'
});
};
return progresscontrol;
}(_component2['default']);
/**
* default options for `progresscontrol`
*
* @type {object}
* @private
*/
progresscontrol.prototype.options_ = {
children: ['seekbar']
};
_component2['default'].registercomponent('progresscontrol', progresscontrol);
exports['default'] = progresscontrol;
},{"16":16,"19":19,"5":5}],19:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _slider = _dereq_(57);
var _slider2 = _interoprequiredefault(_slider);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _formattime = _dereq_(84);
var _formattime2 = _interoprequiredefault(_formattime);
var _computedstyle = _dereq_(80);
var _computedstyle2 = _interoprequiredefault(_computedstyle);
_dereq_(15);
_dereq_(17);
_dereq_(20);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file seek-bar.js
*/
/**
* seek bar and holder for the progress bars
*
* @extends slider
*/
var seekbar = function (_slider) {
_inherits(seekbar, _slider);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function seekbar(player, options) {
_classcallcheck(this, seekbar);
var _this = _possibleconstructorreturn(this, _slider.call(this, player, options));
_this.on(player, 'timeupdate', _this.updateprogress);
_this.on(player, 'ended', _this.updateprogress);
player.ready(fn.bind(_this, _this.updateprogress));
if (options.playeroptions && options.playeroptions.controlbar && options.playeroptions.controlbar.progresscontrol && options.playeroptions.controlbar.progresscontrol.keeptooltipsinside) {
_this.keeptooltipsinside = options.playeroptions.controlbar.progresscontrol.keeptooltipsinside;
}
if (_this.keeptooltipsinside) {
_this.tooltipprogressbar = _this.addchild('tooltipprogressbar');
}
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
seekbar.prototype.createel = function createel() {
return _slider.prototype.createel.call(this, 'div', {
classname: 'vjs-progress-holder'
}, {
'aria-label': 'progress bar'
});
};
/**
* update the seek bars tooltip and width.
*
* @param {eventtarget~event} [event]
* the `timeupdate` or `ended` event that caused this to run.
*
* @listens player#timeupdate
* @listens player#ended
*/
seekbar.prototype.updateprogress = function updateprogress(event) {
this.updateariaattributes(this.el_);
if (this.keeptooltipsinside) {
this.updateariaattributes(this.tooltipprogressbar.el_);
this.tooltipprogressbar.el_.style.width = this.bar.el_.style.width;
var playerwidth = parsefloat((0, _computedstyle2['default'])(this.player().el(), 'width'));
var tooltipwidth = parsefloat((0, _computedstyle2['default'])(this.tooltipprogressbar.tooltip, 'width'));
var tooltipstyle = this.tooltipprogressbar.el().style;
tooltipstyle.maxwidth = math.floor(playerwidth - tooltipwidth / 2) + 'px';
tooltipstyle.minwidth = math.ceil(tooltipwidth / 2) + 'px';
tooltipstyle.right = '-' + tooltipwidth / 2 + 'px';
}
};
/**
* update aria accessibility attributes
*
* @param {element} el
* the element to update with aria accessibility attributes.
*/
seekbar.prototype.updateariaattributes = function updateariaattributes(el) {
// allows for smooth scrubbing, when player can't keep up.
var time = this.player_.scrubbing() ? this.player_.getcache().currenttime : this.player_.currenttime();
// machine readable value of progress bar (percentage complete)
el.setattribute('aria-valuenow', (this.getpercent() * 100).tofixed(2));
// human readable value of progress bar (time complete)
el.setattribute('aria-valuetext', (0, _formattime2['default'])(time, this.player_.duration()));
};
/**
* get percentage of video played
*
* @return {number}
* the percentage played
*/
seekbar.prototype.getpercent = function getpercent() {
var percent = this.player_.currenttime() / this.player_.duration();
return percent >= 1 ? 1 : percent;
};
/**
* handle mouse down on seek bar
*
* @param {eventtarget~event} event
* the `mousedown` event that caused this to run.
*
* @listens mousedown
*/
seekbar.prototype.handlemousedown = function handlemousedown(event) {
this.player_.scrubbing(true);
this.videowasplaying = !this.player_.paused();
this.player_.pause();
_slider.prototype.handlemousedown.call(this, event);
};
/**
* handle mouse move on seek bar
*
* @param {eventtarget~event} event
* the `mousemove` event that caused this to run.
*
* @listens mousemove
*/
seekbar.prototype.handlemousemove = function handlemousemove(event) {
var newtime = this.calculatedistance(event) * this.player_.duration();
// don't let video end while scrubbing.
if (newtime === this.player_.duration()) {
newtime = newtime - 0.1;
}
// set new time (tell player to seek to new time)
this.player_.currenttime(newtime);
};
/**
* handle mouse up on seek bar
*
* @param {eventtarget~event} event
* the `mouseup` event that caused this to run.
*
* @listens mouseup
*/
seekbar.prototype.handlemouseup = function handlemouseup(event) {
_slider.prototype.handlemouseup.call(this, event);
this.player_.scrubbing(false);
if (this.videowasplaying) {
this.player_.play();
}
};
/**
* move more quickly fast forward for keyboard-only users
*/
seekbar.prototype.stepforward = function stepforward() {
// more quickly fast forward for keyboard-only users
this.player_.currenttime(this.player_.currenttime() + 5);
};
/**
* move more quickly rewind for keyboard-only users
*/
seekbar.prototype.stepback = function stepback() {
// more quickly rewind for keyboard-only users
this.player_.currenttime(this.player_.currenttime() - 5);
};
return seekbar;
}(_slider2['default']);
/**
* default options for the `seekbar`
*
* @type {object}
* @private
*/
seekbar.prototype.options_ = {
children: ['loadprogressbar', 'mousetimedisplay', 'playprogressbar'],
barname: 'playprogressbar'
};
/**
* call the update event for this slider when this event happens on the player.
*
* @type {string}
*/
seekbar.prototype.playerevent = 'timeupdate';
_component2['default'].registercomponent('seekbar', seekbar);
exports['default'] = seekbar;
},{"15":15,"17":17,"20":20,"5":5,"57":57,"80":80,"83":83,"84":84}],20:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _formattime = _dereq_(84);
var _formattime2 = _interoprequiredefault(_formattime);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file play-progress-bar.js
*/
/**
* shows play progress
*
* @extends component
*/
var tooltipprogressbar = function (_component) {
_inherits(tooltipprogressbar, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function tooltipprogressbar(player, options) {
_classcallcheck(this, tooltipprogressbar);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.updatedataattr();
_this.on(player, 'timeupdate', _this.updatedataattr);
player.ready(fn.bind(_this, _this.updatedataattr));
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
tooltipprogressbar.prototype.createel = function createel() {
var el = _component.prototype.createel.call(this, 'div', {
classname: 'vjs-tooltip-progress-bar vjs-slider-bar',
innerhtml: '\n ' + this.localize('progress') + ': 0%'
});
this.tooltip = el.queryselector('.vjs-time-tooltip');
return el;
};
/**
* updatet the data-current-time attribute for tooltipprogressbar
*
* @param {eventtarget~event} [event]
* the `timeupdate` event that caused this function to run.
*
* @listens player#timeupdate
*/
tooltipprogressbar.prototype.updatedataattr = function updatedataattr(event) {
var time = this.player_.scrubbing() ? this.player_.getcache().currenttime : this.player_.currenttime();
var formattedtime = (0, _formattime2['default'])(time, this.player_.duration());
this.el_.setattribute('data-current-time', formattedtime);
this.tooltip.innerhtml = formattedtime;
};
return tooltipprogressbar;
}(_component2['default']);
_component2['default'].registercomponent('tooltipprogressbar', tooltipprogressbar);
exports['default'] = tooltipprogressbar;
},{"5":5,"83":83,"84":84}],21:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _spacer = _dereq_(22);
var _spacer2 = _interoprequiredefault(_spacer);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file custom-control-spacer.js
*/
/**
* spacer specifically meant to be used as an insertion point for new plugins, etc.
*
* @extends spacer
*/
var customcontrolspacer = function (_spacer) {
_inherits(customcontrolspacer, _spacer);
function customcontrolspacer() {
_classcallcheck(this, customcontrolspacer);
return _possibleconstructorreturn(this, _spacer.apply(this, arguments));
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
customcontrolspacer.prototype.buildcssclass = function buildcssclass() {
return 'vjs-custom-control-spacer ' + _spacer.prototype.buildcssclass.call(this);
};
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
customcontrolspacer.prototype.createel = function createel() {
var el = _spacer.prototype.createel.call(this, {
classname: this.buildcssclass()
});
// no-flex/table-cell mode requires there be some content
// in the cell to fill the remaining space of the table.
el.innerhtml = ' ';
return el;
};
return customcontrolspacer;
}(_spacer2['default']);
_component2['default'].registercomponent('customcontrolspacer', customcontrolspacer);
exports['default'] = customcontrolspacer;
},{"22":22,"5":5}],22:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file spacer.js
*/
/**
* just an empty spacer element that can be used as an append point for plugins, etc.
* also can be used to create space between elements when necessary.
*
* @extends component
*/
var spacer = function (_component) {
_inherits(spacer, _component);
function spacer() {
_classcallcheck(this, spacer);
return _possibleconstructorreturn(this, _component.apply(this, arguments));
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
spacer.prototype.buildcssclass = function buildcssclass() {
return 'vjs-spacer ' + _component.prototype.buildcssclass.call(this);
};
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
spacer.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: this.buildcssclass()
});
};
return spacer;
}(_component2['default']);
_component2['default'].registercomponent('spacer', spacer);
exports['default'] = spacer;
},{"5":5}],23:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _texttrackmenuitem = _dereq_(31);
var _texttrackmenuitem2 = _interoprequiredefault(_texttrackmenuitem);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file caption-settings-menu-item.js
*/
/**
* the menu item for caption track settings menu
*
* @extends texttrackmenuitem
*/
var captionsettingsmenuitem = function (_texttrackmenuitem) {
_inherits(captionsettingsmenuitem, _texttrackmenuitem);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function captionsettingsmenuitem(player, options) {
_classcallcheck(this, captionsettingsmenuitem);
options.track = {
player: player,
kind: options.kind,
label: options.kind + ' settings',
selectable: false,
'default': false,
mode: 'disabled'
};
// captionsettingsmenuitem has no concept of 'selected'
options.selectable = false;
var _this = _possibleconstructorreturn(this, _texttrackmenuitem.call(this, player, options));
_this.addclass('vjs-texttrack-settings');
_this.controltext(', opens ' + options.kind + ' settings dialog');
return _this;
}
/**
* this gets called when an `captionsettingsmenuitem` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
captionsettingsmenuitem.prototype.handleclick = function handleclick(event) {
this.player().getchild('texttracksettings').show();
this.player().getchild('texttracksettings').el_.focus();
};
return captionsettingsmenuitem;
}(_texttrackmenuitem2['default']);
_component2['default'].registercomponent('captionsettingsmenuitem', captionsettingsmenuitem);
exports['default'] = captionsettingsmenuitem;
},{"31":31,"5":5}],24:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _texttrackbutton = _dereq_(30);
var _texttrackbutton2 = _interoprequiredefault(_texttrackbutton);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _captionsettingsmenuitem = _dereq_(23);
var _captionsettingsmenuitem2 = _interoprequiredefault(_captionsettingsmenuitem);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file captions-button.js
*/
/**
* the button component for toggling and selecting captions
*
* @extends texttrackbutton
*/
var captionsbutton = function (_texttrackbutton) {
_inherits(captionsbutton, _texttrackbutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} [ready]
* the function to call when this component is ready.
*/
function captionsbutton(player, options, ready) {
_classcallcheck(this, captionsbutton);
var _this = _possibleconstructorreturn(this, _texttrackbutton.call(this, player, options, ready));
_this.el_.setattribute('aria-label', 'captions menu');
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
captionsbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-captions-button ' + _texttrackbutton.prototype.buildcssclass.call(this);
};
/**
* create caption menu items
*
* @return {captionsettingsmenuitem[]}
* the array of current menu items.
*/
captionsbutton.prototype.createitems = function createitems() {
var items = [];
if (!(this.player().tech_ && this.player().tech_.featuresnativetexttracks)) {
items.push(new _captionsettingsmenuitem2['default'](this.player_, { kind: this.kind_ }));
this.hidethreshold_ += 1;
}
return _texttrackbutton.prototype.createitems.call(this, items);
};
return captionsbutton;
}(_texttrackbutton2['default']);
/**
* `kind` of texttrack to look for to associate it with this menu.
*
* @type {string}
* @private
*/
captionsbutton.prototype.kind_ = 'captions';
/**
* the text that should display over the `captionsbutton`s controls. added for localization.
*
* @type {string}
* @private
*/
captionsbutton.prototype.controltext_ = 'captions';
_component2['default'].registercomponent('captionsbutton', captionsbutton);
exports['default'] = captionsbutton;
},{"23":23,"30":30,"5":5}],25:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _texttrackbutton = _dereq_(30);
var _texttrackbutton2 = _interoprequiredefault(_texttrackbutton);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _chapterstrackmenuitem = _dereq_(26);
var _chapterstrackmenuitem2 = _interoprequiredefault(_chapterstrackmenuitem);
var _totitlecase = _dereq_(91);
var _totitlecase2 = _interoprequiredefault(_totitlecase);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file chapters-button.js
*/
/**
* the button component for toggling and selecting chapters
* chapters act much differently than other text tracks
* cues are navigation vs. other tracks of alternative languages
*
* @extends texttrackbutton
*/
var chaptersbutton = function (_texttrackbutton) {
_inherits(chaptersbutton, _texttrackbutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} [ready]
* the function to call when this function is ready.
*/
function chaptersbutton(player, options, ready) {
_classcallcheck(this, chaptersbutton);
var _this = _possibleconstructorreturn(this, _texttrackbutton.call(this, player, options, ready));
_this.el_.setattribute('aria-label', 'chapters menu');
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
chaptersbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-chapters-button ' + _texttrackbutton.prototype.buildcssclass.call(this);
};
/**
* update the menu based on the current state of its items.
*
* @param {eventtarget~event} [event]
* an event that triggered this function to run.
*
* @listens texttracklist#addtrack
* @listens texttracklist#removetrack
* @listens texttracklist#change
*/
chaptersbutton.prototype.update = function update(event) {
if (!this.track_ || event && (event.type === 'addtrack' || event.type === 'removetrack')) {
this.settrack(this.findchapterstrack());
}
_texttrackbutton.prototype.update.call(this);
};
/**
* set the currently selected track for the chapters button.
*
* @param {texttrack} track
* the new track to select. nothing will change if this is the currently selected
* track.
*/
chaptersbutton.prototype.settrack = function settrack(track) {
if (this.track_ === track) {
return;
}
if (!this.updatehandler_) {
this.updatehandler_ = this.update.bind(this);
}
// here this.track_ refers to the old track instance
if (this.track_) {
var remotetexttrackel = this.player_.remotetexttrackels().gettrackelementbytrack_(this.track_);
if (remotetexttrackel) {
remotetexttrackel.removeeventlistener('load', this.updatehandler_);
}
this.track_ = null;
}
this.track_ = track;
// here this.track_ refers to the new track instance
if (this.track_) {
this.track_.mode = 'hidden';
var _remotetexttrackel = this.player_.remotetexttrackels().gettrackelementbytrack_(this.track_);
if (_remotetexttrackel) {
_remotetexttrackel.addeventlistener('load', this.updatehandler_);
}
}
};
/**
* find the track object that is currently in use by this chaptersbutton
*
* @return {texttrack|undefined}
* the current track or undefined if none was found.
*/
chaptersbutton.prototype.findchapterstrack = function findchapterstrack() {
var tracks = this.player_.texttracks() || [];
for (var i = tracks.length - 1; i >= 0; i--) {
// we will always choose the last track as our chapterstrack
var track = tracks[i];
if (track.kind === this.kind_) {
return track;
}
}
};
/**
* get the caption for the chaptersbutton based on the track label. this will also
* use the current tracks localized kind as a fallback if a label does not exist.
*
* @return {string}
* the tracks current label or the localized track kind.
*/
chaptersbutton.prototype.getmenucaption = function getmenucaption() {
if (this.track_ && this.track_.label) {
return this.track_.label;
}
return this.localize((0, _totitlecase2['default'])(this.kind_));
};
/**
* create menu from chapter track
*
* @return {menu}
* new menu for the chapter buttons
*/
chaptersbutton.prototype.createmenu = function createmenu() {
this.options_.title = this.getmenucaption();
return _texttrackbutton.prototype.createmenu.call(this);
};
/**
* create a menu item for each text track
*
* @return {texttrackmenuitem[]}
* array of menu items
*/
chaptersbutton.prototype.createitems = function createitems() {
var items = [];
if (!this.track_) {
return items;
}
var cues = this.track_.cues;
if (!cues) {
return items;
}
for (var i = 0, l = cues.length; i < l; i++) {
var cue = cues[i];
var mi = new _chapterstrackmenuitem2['default'](this.player_, { track: this.track_, cue: cue });
items.push(mi);
}
return items;
};
return chaptersbutton;
}(_texttrackbutton2['default']);
/**
* `kind` of texttrack to look for to associate it with this menu.
*
* @type {string}
* @private
*/
chaptersbutton.prototype.kind_ = 'chapters';
/**
* the text that should display over the `chaptersbutton`s controls. added for localization.
*
* @type {string}
* @private
*/
chaptersbutton.prototype.controltext_ = 'chapters';
_component2['default'].registercomponent('chaptersbutton', chaptersbutton);
exports['default'] = chaptersbutton;
},{"26":26,"30":30,"5":5,"91":91}],26:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _menuitem = _dereq_(48);
var _menuitem2 = _interoprequiredefault(_menuitem);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file chapters-track-menu-item.js
*/
/**
* the chapter track menu item
*
* @extends menuitem
*/
var chapterstrackmenuitem = function (_menuitem) {
_inherits(chapterstrackmenuitem, _menuitem);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function chapterstrackmenuitem(player, options) {
_classcallcheck(this, chapterstrackmenuitem);
var track = options.track;
var cue = options.cue;
var currenttime = player.currenttime();
// modify options for parent menuitem class's init.
options.selectable = true;
options.label = cue.text;
options.selected = cue.starttime <= currenttime && currenttime < cue.endtime;
var _this = _possibleconstructorreturn(this, _menuitem.call(this, player, options));
_this.track = track;
_this.cue = cue;
track.addeventlistener('cuechange', fn.bind(_this, _this.update));
return _this;
}
/**
* this gets called when an `chapterstrackmenuitem` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
chapterstrackmenuitem.prototype.handleclick = function handleclick(event) {
_menuitem.prototype.handleclick.call(this);
this.player_.currenttime(this.cue.starttime);
this.update(this.cue.starttime);
};
/**
* update chapter menu item
*
* @param {eventtarget~event} [event]
* the `cuechange` event that caused this function to run.
*
* @listens texttrack#cuechange
*/
chapterstrackmenuitem.prototype.update = function update(event) {
var cue = this.cue;
var currenttime = this.player_.currenttime();
// vjs.log(currenttime, cue.starttime);
this.selected(cue.starttime <= currenttime && currenttime < cue.endtime);
};
return chapterstrackmenuitem;
}(_menuitem2['default']);
_component2['default'].registercomponent('chapterstrackmenuitem', chapterstrackmenuitem);
exports['default'] = chapterstrackmenuitem;
},{"48":48,"5":5,"83":83}],27:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _texttrackbutton = _dereq_(30);
var _texttrackbutton2 = _interoprequiredefault(_texttrackbutton);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file descriptions-button.js
*/
/**
* the button component for toggling and selecting descriptions
*
* @extends texttrackbutton
*/
var descriptionsbutton = function (_texttrackbutton) {
_inherits(descriptionsbutton, _texttrackbutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} [ready]
* the function to call when this component is ready.
*/
function descriptionsbutton(player, options, ready) {
_classcallcheck(this, descriptionsbutton);
var _this = _possibleconstructorreturn(this, _texttrackbutton.call(this, player, options, ready));
_this.el_.setattribute('aria-label', 'descriptions menu');
var tracks = player.texttracks();
if (tracks) {
var changehandler = fn.bind(_this, _this.handletrackschange);
tracks.addeventlistener('change', changehandler);
_this.on('dispose', function () {
tracks.removeeventlistener('change', changehandler);
});
}
return _this;
}
/**
* handle text track change
*
* @param {eventtarget~event} event
* the event that caused this function to run
*
* @listens texttracklist#change
*/
descriptionsbutton.prototype.handletrackschange = function handletrackschange(event) {
var tracks = this.player().texttracks();
var disabled = false;
// check whether a track of a different kind is showing
for (var i = 0, l = tracks.length; i < l; i++) {
var track = tracks[i];
if (track.kind !== this.kind_ && track.mode === 'showing') {
disabled = true;
break;
}
}
// if another track is showing, disable this menu button
if (disabled) {
this.disable();
} else {
this.enable();
}
};
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
descriptionsbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-descriptions-button ' + _texttrackbutton.prototype.buildcssclass.call(this);
};
return descriptionsbutton;
}(_texttrackbutton2['default']);
/**
* `kind` of texttrack to look for to associate it with this menu.
*
* @type {string}
* @private
*/
descriptionsbutton.prototype.kind_ = 'descriptions';
/**
* the text that should display over the `descriptionsbutton`s controls. added for localization.
*
* @type {string}
* @private
*/
descriptionsbutton.prototype.controltext_ = 'descriptions';
_component2['default'].registercomponent('descriptionsbutton', descriptionsbutton);
exports['default'] = descriptionsbutton;
},{"30":30,"5":5,"83":83}],28:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _texttrackmenuitem = _dereq_(31);
var _texttrackmenuitem2 = _interoprequiredefault(_texttrackmenuitem);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file off-text-track-menu-item.js
*/
/**
* a special menu item for turning of a specific type of text track
*
* @extends texttrackmenuitem
*/
var offtexttrackmenuitem = function (_texttrackmenuitem) {
_inherits(offtexttrackmenuitem, _texttrackmenuitem);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function offtexttrackmenuitem(player, options) {
_classcallcheck(this, offtexttrackmenuitem);
// create pseudo track info
// requires options['kind']
options.track = {
player: player,
kind: options.kind,
label: options.kind + ' off',
'default': false,
mode: 'disabled'
};
// menuitem is selectable
options.selectable = true;
var _this = _possibleconstructorreturn(this, _texttrackmenuitem.call(this, player, options));
_this.selected(true);
return _this;
}
/**
* handle text track change
*
* @param {eventtarget~event} event
* the event that caused this function to run
*/
offtexttrackmenuitem.prototype.handletrackschange = function handletrackschange(event) {
var tracks = this.player().texttracks();
var selected = true;
for (var i = 0, l = tracks.length; i < l; i++) {
var track = tracks[i];
if (track.kind === this.track.kind && track.mode === 'showing') {
selected = false;
break;
}
}
this.selected(selected);
};
return offtexttrackmenuitem;
}(_texttrackmenuitem2['default']);
_component2['default'].registercomponent('offtexttrackmenuitem', offtexttrackmenuitem);
exports['default'] = offtexttrackmenuitem;
},{"31":31,"5":5}],29:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _texttrackbutton = _dereq_(30);
var _texttrackbutton2 = _interoprequiredefault(_texttrackbutton);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file subtitles-button.js
*/
/**
* the button component for toggling and selecting subtitles
*
* @extends texttrackbutton
*/
var subtitlesbutton = function (_texttrackbutton) {
_inherits(subtitlesbutton, _texttrackbutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} [ready]
* the function to call when this component is ready.
*/
function subtitlesbutton(player, options, ready) {
_classcallcheck(this, subtitlesbutton);
var _this = _possibleconstructorreturn(this, _texttrackbutton.call(this, player, options, ready));
_this.el_.setattribute('aria-label', 'subtitles menu');
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
subtitlesbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-subtitles-button ' + _texttrackbutton.prototype.buildcssclass.call(this);
};
return subtitlesbutton;
}(_texttrackbutton2['default']);
/**
* `kind` of texttrack to look for to associate it with this menu.
*
* @type {string}
* @private
*/
subtitlesbutton.prototype.kind_ = 'subtitles';
/**
* the text that should display over the `subtitlesbutton`s controls. added for localization.
*
* @type {string}
* @private
*/
subtitlesbutton.prototype.controltext_ = 'subtitles';
_component2['default'].registercomponent('subtitlesbutton', subtitlesbutton);
exports['default'] = subtitlesbutton;
},{"30":30,"5":5}],30:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _trackbutton = _dereq_(36);
var _trackbutton2 = _interoprequiredefault(_trackbutton);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _texttrackmenuitem = _dereq_(31);
var _texttrackmenuitem2 = _interoprequiredefault(_texttrackmenuitem);
var _offtexttrackmenuitem = _dereq_(28);
var _offtexttrackmenuitem2 = _interoprequiredefault(_offtexttrackmenuitem);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file text-track-button.js
*/
/**
* the base class for buttons that toggle specific text track types (e.g. subtitles)
*
* @extends menubutton
*/
var texttrackbutton = function (_trackbutton) {
_inherits(texttrackbutton, _trackbutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options={}]
* the key/value store of player options.
*/
function texttrackbutton(player) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classcallcheck(this, texttrackbutton);
options.tracks = player.texttracks();
return _possibleconstructorreturn(this, _trackbutton.call(this, player, options));
}
/**
* create a menu item for each text track
*
* @param {texttrackmenuitem[]} [items=[]]
* existing array of items to use during creation
*
* @return {texttrackmenuitem[]}
* array of menu items that were created
*/
texttrackbutton.prototype.createitems = function createitems() {
var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
// add an off menu item to turn all tracks off
items.push(new _offtexttrackmenuitem2['default'](this.player_, { kind: this.kind_ }));
this.hidethreshold_ += 1;
var tracks = this.player_.texttracks();
if (!tracks) {
return items;
}
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
// only add tracks that are of the appropriate kind and have a label
if (track.kind === this.kind_) {
items.push(new _texttrackmenuitem2['default'](this.player_, {
track: track,
// menuitem is selectable
selectable: true
}));
}
}
return items;
};
return texttrackbutton;
}(_trackbutton2['default']);
_component2['default'].registercomponent('texttrackbutton', texttrackbutton);
exports['default'] = texttrackbutton;
},{"28":28,"31":31,"36":36,"5":5}],31:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
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; };
var _menuitem = _dereq_(48);
var _menuitem2 = _interoprequiredefault(_menuitem);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file text-track-menu-item.js
*/
/**
* the specific menu item type for selecting a language within a text track kind
*
* @extends menuitem
*/
var texttrackmenuitem = function (_menuitem) {
_inherits(texttrackmenuitem, _menuitem);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function texttrackmenuitem(player, options) {
_classcallcheck(this, texttrackmenuitem);
var track = options.track;
var tracks = player.texttracks();
// modify options for parent menuitem class's init.
options.label = track.label || track.language || 'unknown';
options.selected = track['default'] || track.mode === 'showing';
var _this = _possibleconstructorreturn(this, _menuitem.call(this, player, options));
_this.track = track;
if (tracks) {
var changehandler = fn.bind(_this, _this.handletrackschange);
player.on(['loadstart', 'texttrackchange'], changehandler);
tracks.addeventlistener('change', changehandler);
_this.on('dispose', function () {
tracks.removeeventlistener('change', changehandler);
});
}
// ios7 doesn't dispatch change events to texttracklists when an
// associated track's mode changes. without something like
// object.observe() (also not present on ios7), it's not
// possible to detect changes to the mode attribute and polyfill
// the change event. as a poor substitute, we manually dispatch
// change events whenever the controls modify the mode.
if (tracks && tracks.onchange === undefined) {
var event = void 0;
_this.on(['tap', 'click'], function () {
if (_typeof(_window2['default'].event) !== 'object') {
// android 2.3 throws an illegal constructor error for window.event
try {
event = new _window2['default'].event('change');
} catch (err) {
// continue regardless of error
}
}
if (!event) {
event = _document2['default'].createevent('event');
event.initevent('change', true, true);
}
tracks.dispatchevent(event);
});
}
return _this;
}
/**
* this gets called when an `texttrackmenuitem` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} event
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
texttrackmenuitem.prototype.handleclick = function handleclick(event) {
var kind = this.track.kind;
var tracks = this.player_.texttracks();
_menuitem.prototype.handleclick.call(this, event);
if (!tracks) {
return;
}
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
if (track.kind !== kind) {
continue;
}
if (track === this.track) {
track.mode = 'showing';
} else {
track.mode = 'disabled';
}
}
};
/**
* handle text track list change
*
* @param {eventtarget~event} event
* the `change` event that caused this function to be called.
*
* @listens texttracklist#change
*/
texttrackmenuitem.prototype.handletrackschange = function handletrackschange(event) {
this.selected(this.track.mode === 'showing');
};
return texttrackmenuitem;
}(_menuitem2['default']);
_component2['default'].registercomponent('texttrackmenuitem', texttrackmenuitem);
exports['default'] = texttrackmenuitem;
},{"48":48,"5":5,"83":83,"94":94,"95":95}],32:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _formattime = _dereq_(84);
var _formattime2 = _interoprequiredefault(_formattime);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file current-time-display.js
*/
/**
* displays the current time
*
* @extends component
*/
var currenttimedisplay = function (_component) {
_inherits(currenttimedisplay, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function currenttimedisplay(player, options) {
_classcallcheck(this, currenttimedisplay);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.on(player, 'timeupdate', _this.updatecontent);
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
currenttimedisplay.prototype.createel = function createel() {
var el = _component.prototype.createel.call(this, 'div', {
classname: 'vjs-current-time vjs-time-control vjs-control'
});
this.contentel_ = dom.createel('div', {
classname: 'vjs-current-time-display',
// label the current time for screen reader users
innerhtml: 'current time ' + '0:00'
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
});
el.appendchild(this.contentel_);
return el;
};
/**
* update current time display
*
* @param {eventtarget~event} [event]
* the `timeupdate` event that caused this function to run.
*
* @listens player#timeupdate
*/
currenttimedisplay.prototype.updatecontent = function updatecontent(event) {
// allows for smooth scrubbing, when player can't keep up.
var time = this.player_.scrubbing() ? this.player_.getcache().currenttime : this.player_.currenttime();
var localizedtext = this.localize('current time');
var formattedtime = (0, _formattime2['default'])(time, this.player_.duration());
if (formattedtime !== this.formattedtime_) {
this.formattedtime_ = formattedtime;
this.contentel_.innerhtml = '' + localizedtext + ' ' + formattedtime;
}
};
return currenttimedisplay;
}(_component2['default']);
_component2['default'].registercomponent('currenttimedisplay', currenttimedisplay);
exports['default'] = currenttimedisplay;
},{"5":5,"81":81,"84":84}],33:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _formattime = _dereq_(84);
var _formattime2 = _interoprequiredefault(_formattime);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file duration-display.js
*/
/**
* displays the duration
*
* @extends component
*/
var durationdisplay = function (_component) {
_inherits(durationdisplay, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function durationdisplay(player, options) {
_classcallcheck(this, durationdisplay);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.on(player, 'durationchange', _this.updatecontent);
// also listen for timeupdate and loadedmetadata because removing those
// listeners could have broken dependent applications/libraries. these
// can likely be removed for 6.0.
_this.on(player, 'timeupdate', _this.updatecontent);
_this.on(player, 'loadedmetadata', _this.updatecontent);
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
durationdisplay.prototype.createel = function createel() {
var el = _component.prototype.createel.call(this, 'div', {
classname: 'vjs-duration vjs-time-control vjs-control'
});
this.contentel_ = dom.createel('div', {
classname: 'vjs-duration-display',
// label the duration time for screen reader users
innerhtml: '' + this.localize('duration time') + ' 0:00'
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
});
el.appendchild(this.contentel_);
return el;
};
/**
* update duration time display.
*
* @param {eventtarget~event} [event]
* the `durationchange`, `timeupdate`, or `loadedmetadata` event that caused
* this function to be called.
*
* @listens player#durationchange
* @listens player#timeupdate
* @listens player#loadedmetadata
*/
durationdisplay.prototype.updatecontent = function updatecontent(event) {
var duration = this.player_.duration();
if (duration && this.duration_ !== duration) {
this.duration_ = duration;
var localizedtext = this.localize('duration time');
var formattedtime = (0, _formattime2['default'])(duration);
// label the duration time for screen reader users
this.contentel_.innerhtml = '' + localizedtext + ' ' + formattedtime;
}
};
return durationdisplay;
}(_component2['default']);
_component2['default'].registercomponent('durationdisplay', durationdisplay);
exports['default'] = durationdisplay;
},{"5":5,"81":81,"84":84}],34:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _formattime = _dereq_(84);
var _formattime2 = _interoprequiredefault(_formattime);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file remaining-time-display.js
*/
/**
* displays the time left in the video
*
* @extends component
*/
var remainingtimedisplay = function (_component) {
_inherits(remainingtimedisplay, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function remainingtimedisplay(player, options) {
_classcallcheck(this, remainingtimedisplay);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.on(player, 'timeupdate', _this.updatecontent);
_this.on(player, 'durationchange', _this.updatecontent);
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
remainingtimedisplay.prototype.createel = function createel() {
var el = _component.prototype.createel.call(this, 'div', {
classname: 'vjs-remaining-time vjs-time-control vjs-control'
});
this.contentel_ = dom.createel('div', {
classname: 'vjs-remaining-time-display',
// label the remaining time for screen reader users
innerhtml: '' + this.localize('remaining time') + ' -0:00'
}, {
// tell screen readers not to automatically read the time as it changes
'aria-live': 'off'
});
el.appendchild(this.contentel_);
return el;
};
/**
* update remaining time display.
*
* @param {eventtarget~event} [event]
* the `timeupdate` or `durationchange` event that caused this to run.
*
* @listens player#timeupdate
* @listens player#durationchange
*/
remainingtimedisplay.prototype.updatecontent = function updatecontent(event) {
if (this.player_.duration()) {
var localizedtext = this.localize('remaining time');
var formattedtime = (0, _formattime2['default'])(this.player_.remainingtime());
if (formattedtime !== this.formattedtime_) {
this.formattedtime_ = formattedtime;
this.contentel_.innerhtml = '' + localizedtext + ' -' + formattedtime;
}
}
// allows for smooth scrubbing, when player can't keep up.
// var time = (this.player_.scrubbing()) ? this.player_.getcache().currenttime : this.player_.currenttime();
// this.contentel_.innerhtml = vjs.formattime(time, this.player_.duration());
};
return remainingtimedisplay;
}(_component2['default']);
_component2['default'].registercomponent('remainingtimedisplay', remainingtimedisplay);
exports['default'] = remainingtimedisplay;
},{"5":5,"81":81,"84":84}],35:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file time-divider.js
*/
/**
* the separator between the current time and duration.
* can be hidden if it's not needed in the design.
*
* @extends component
*/
var timedivider = function (_component) {
_inherits(timedivider, _component);
function timedivider() {
_classcallcheck(this, timedivider);
return _possibleconstructorreturn(this, _component.apply(this, arguments));
}
/**
* create the component's dom element
*
* @return {element}
* the element that was created.
*/
timedivider.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-time-control vjs-time-divider',
innerhtml: '
/
'
});
};
return timedivider;
}(_component2['default']);
_component2['default'].registercomponent('timedivider', timedivider);
exports['default'] = timedivider;
},{"5":5}],36:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _menubutton = _dereq_(47);
var _menubutton2 = _interoprequiredefault(_menubutton);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file track-button.js
*/
/**
* the base class for buttons that toggle specific track types (e.g. subtitles).
*
* @extends menubutton
*/
var trackbutton = function (_menubutton) {
_inherits(trackbutton, _menubutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function trackbutton(player, options) {
_classcallcheck(this, trackbutton);
var tracks = options.tracks;
var _this = _possibleconstructorreturn(this, _menubutton.call(this, player, options));
if (_this.items.length <= 1) {
_this.hide();
}
if (!tracks) {
return _possibleconstructorreturn(_this);
}
var updatehandler = fn.bind(_this, _this.update);
tracks.addeventlistener('removetrack', updatehandler);
tracks.addeventlistener('addtrack', updatehandler);
_this.player_.on('dispose', function () {
tracks.removeeventlistener('removetrack', updatehandler);
tracks.removeeventlistener('addtrack', updatehandler);
});
return _this;
}
return trackbutton;
}(_menubutton2['default']);
_component2['default'].registercomponent('trackbutton', trackbutton);
exports['default'] = trackbutton;
},{"47":47,"5":5,"83":83}],37:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _slider = _dereq_(57);
var _slider2 = _interoprequiredefault(_slider);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
_dereq_(39);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file volume-bar.js
*/
// required children
/**
* the bar that contains the volume level and can be clicked on to adjust the level
*
* @extends slider
*/
var volumebar = function (_slider) {
_inherits(volumebar, _slider);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function volumebar(player, options) {
_classcallcheck(this, volumebar);
var _this = _possibleconstructorreturn(this, _slider.call(this, player, options));
_this.on(player, 'volumechange', _this.updateariaattributes);
player.ready(fn.bind(_this, _this.updateariaattributes));
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
volumebar.prototype.createel = function createel() {
return _slider.prototype.createel.call(this, 'div', {
classname: 'vjs-volume-bar vjs-slider-bar'
}, {
'aria-label': 'volume level'
});
};
/**
* handle movement events on the {@link volumemenubutton}.
*
* @param {eventtarget~event} event
* the event that caused this function to run.
*
* @listens mousemove
*/
volumebar.prototype.handlemousemove = function handlemousemove(event) {
this.checkmuted();
this.player_.volume(this.calculatedistance(event));
};
/**
* if the player is muted unmute it.
*/
volumebar.prototype.checkmuted = function checkmuted() {
if (this.player_.muted()) {
this.player_.muted(false);
}
};
/**
* get percent of volume level
*
* @return {number}
* volume level percent as a decimal number.
*/
volumebar.prototype.getpercent = function getpercent() {
if (this.player_.muted()) {
return 0;
}
return this.player_.volume();
};
/**
* increase volume level for keyboard users
*/
volumebar.prototype.stepforward = function stepforward() {
this.checkmuted();
this.player_.volume(this.player_.volume() + 0.1);
};
/**
* decrease volume level for keyboard users
*/
volumebar.prototype.stepback = function stepback() {
this.checkmuted();
this.player_.volume(this.player_.volume() - 0.1);
};
/**
* update aria accessibility attributes
*
* @param {eventtarget~event} [event]
* the `volumechange` event that caused this function to run.
*
* @listens player#volumechange
*/
volumebar.prototype.updateariaattributes = function updateariaattributes(event) {
// current value of volume bar as a percentage
var volume = (this.player_.volume() * 100).tofixed(2);
this.el_.setattribute('aria-valuenow', volume);
this.el_.setattribute('aria-valuetext', volume + '%');
};
return volumebar;
}(_slider2['default']);
/**
* default options for the `volumebar`
*
* @type {object}
* @private
*/
volumebar.prototype.options_ = {
children: ['volumelevel'],
barname: 'volumelevel'
};
/**
* call the update event for this slider when this event happens on the player.
*
* @type {string}
*/
volumebar.prototype.playerevent = 'volumechange';
_component2['default'].registercomponent('volumebar', volumebar);
exports['default'] = volumebar;
},{"39":39,"5":5,"57":57,"83":83}],38:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
_dereq_(37);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file volume-control.js
*/
// required children
/**
* the component for controlling the volume level
*
* @extends component
*/
var volumecontrol = function (_component) {
_inherits(volumecontrol, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options={}]
* the key/value store of player options.
*/
function volumecontrol(player, options) {
_classcallcheck(this, volumecontrol);
// hide volume controls when they're not supported by the current tech
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
if (player.tech_ && player.tech_.featuresvolumecontrol === false) {
_this.addclass('vjs-hidden');
}
_this.on(player, 'loadstart', function () {
if (player.tech_.featuresvolumecontrol === false) {
this.addclass('vjs-hidden');
} else {
this.removeclass('vjs-hidden');
}
});
return _this;
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
volumecontrol.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-volume-control vjs-control'
});
};
return volumecontrol;
}(_component2['default']);
/**
* default options for the `volumecontrol`
*
* @type {object}
* @private
*/
volumecontrol.prototype.options_ = {
children: ['volumebar']
};
_component2['default'].registercomponent('volumecontrol', volumecontrol);
exports['default'] = volumecontrol;
},{"37":37,"5":5}],39:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file volume-level.js
*/
/**
* shows volume level
*
* @extends component
*/
var volumelevel = function (_component) {
_inherits(volumelevel, _component);
function volumelevel() {
_classcallcheck(this, volumelevel);
return _possibleconstructorreturn(this, _component.apply(this, arguments));
}
/**
* create the `component`'s dom element
*
* @return {element}
* the element that was created.
*/
volumelevel.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-volume-level',
innerhtml: ''
});
};
return volumelevel;
}(_component2['default']);
_component2['default'].registercomponent('volumelevel', volumelevel);
exports['default'] = volumelevel;
},{"5":5}],40:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _popup = _dereq_(54);
var _popup2 = _interoprequiredefault(_popup);
var _popupbutton = _dereq_(53);
var _popupbutton2 = _interoprequiredefault(_popupbutton);
var _mutetoggle = _dereq_(11);
var _mutetoggle2 = _interoprequiredefault(_mutetoggle);
var _volumebar = _dereq_(37);
var _volumebar2 = _interoprequiredefault(_volumebar);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
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; } }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file volume-menu-button.js
*/
/**
* button for volume popup
*
* @extends popupbutton
*/
var volumemenubutton = function (_popupbutton) {
_inherits(volumemenubutton, _popupbutton);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options={}]
* the key/value store of player options.
*/
function volumemenubutton(player) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classcallcheck(this, volumemenubutton);
// default to inline
if (options.inline === undefined) {
options.inline = true;
}
// if the vertical option isn't passed at all, default to true.
if (options.vertical === undefined) {
// if an inline volumemenubutton is used, we should default to using
// a horizontal slider for obvious reasons.
if (options.inline) {
options.vertical = false;
} else {
options.vertical = true;
}
}
// the vertical option needs to be set on the volumebar as well,
// since that will need to be passed along to the volumebar constructor
options.volumebar = options.volumebar || {};
options.volumebar.vertical = !!options.vertical;
// same listeners as mutetoggle
var _this = _possibleconstructorreturn(this, _popupbutton.call(this, player, options));
_this.on(player, 'volumechange', _this.volumeupdate);
_this.on(player, 'loadstart', _this.volumeupdate);
// hide mute toggle if the current tech doesn't support volume control
function updatevisibility() {
if (player.tech_ && player.tech_.featuresvolumecontrol === false) {
this.addclass('vjs-hidden');
} else {
this.removeclass('vjs-hidden');
}
}
updatevisibility.call(_this);
_this.on(player, 'loadstart', updatevisibility);
_this.on(_this.volumebar, ['slideractive', 'focus'], function () {
this.addclass('vjs-slider-active');
});
_this.on(_this.volumebar, ['sliderinactive', 'blur'], function () {
this.removeclass('vjs-slider-active');
});
_this.on(_this.volumebar, ['focus'], function () {
this.addclass('vjs-lock-showing');
});
_this.on(_this.volumebar, ['blur'], function () {
this.removeclass('vjs-lock-showing');
});
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
volumemenubutton.prototype.buildcssclass = function buildcssclass() {
var orientationclass = '';
if (this.options_.vertical) {
orientationclass = 'vjs-volume-menu-button-vertical';
} else {
orientationclass = 'vjs-volume-menu-button-horizontal';
}
return 'vjs-volume-menu-button ' + _popupbutton.prototype.buildcssclass.call(this) + ' ' + orientationclass;
};
/**
* create the volumemenubutton popup
*
* @return {popup}
* the popup that was created
*/
volumemenubutton.prototype.createpopup = function createpopup() {
var popup = new _popup2['default'](this.player_, {
contenteltype: 'div'
});
var vb = new _volumebar2['default'](this.player_, this.options_.volumebar);
popup.addchild(vb);
this.menucontent = popup;
this.volumebar = vb;
this.attachvolumebarevents();
return popup;
};
/**
* this gets called when an `volumemenubutton` is "clicked". see
* {@link clickablecomponent} for more detailed information on what a click can be.
*
* @param {eventtarget~event} [event]
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
volumemenubutton.prototype.handleclick = function handleclick(event) {
_mutetoggle2['default'].prototype.handleclick.call(this);
_popupbutton.prototype.handleclick.call(this);
};
/**
* add events listeners to the created `volumebar`.
*/
volumemenubutton.prototype.attachvolumebarevents = function attachvolumebarevents() {
this.menucontent.on(['mousedown', 'touchdown'], fn.bind(this, this.handlemousedown));
};
/**
* handle the `mousedown` and `touchdown` events on the `volumebar`
*
* @param {eventtarget~event} [event]
* the `mousedown` or `touchdown` event that caused this to run.
*
* @listens mousedown
* @listens touchdown
*/
volumemenubutton.prototype.handlemousedown = function handlemousedown(event) {
this.on(['mousemove', 'touchmove'], fn.bind(this.volumebar, this.volumebar.handlemousemove));
this.on(this.el_.ownerdocument, ['mouseup', 'touchend'], this.handlemouseup);
};
/**
* handle the `mouseup` and `touchend` events on the `volumebar`
*
* @param {eventtarget~event} [event]
* the `mouseup` or `touchend` event that caused this to run.
*
* @listens mouseup
* @listens touchend
*/
volumemenubutton.prototype.handlemouseup = function handlemouseup(event) {
this.off(['mousemove', 'touchmove'], fn.bind(this.volumebar, this.volumebar.handlemousemove));
};
return volumemenubutton;
}(_popupbutton2['default']);
/**
* @borrows mutetoggle#update as volumemenubutton#volumeupdate
*/
volumemenubutton.prototype.volumeupdate = _mutetoggle2['default'].prototype.update;
/**
* the text that should display over the `volumemenubutton`s controls. added for localization.
*
* @type {string}
* @private
*/
volumemenubutton.prototype.controltext_ = 'mute';
_component2['default'].registercomponent('volumemenubutton', volumemenubutton);
exports['default'] = volumemenubutton;
},{"11":11,"37":37,"5":5,"53":53,"54":54,"83":83}],41:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _modaldialog = _dereq_(50);
var _modaldialog2 = _interoprequiredefault(_modaldialog);
var _mergeoptions = _dereq_(87);
var _mergeoptions2 = _interoprequiredefault(_mergeoptions);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file error-display.js
*/
/**
* a display that indicates an error has occurred. this means that the video
* is unplayable.
*
* @extends modaldialog
*/
var errordisplay = function (_modaldialog) {
_inherits(errordisplay, _modaldialog);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function errordisplay(player, options) {
_classcallcheck(this, errordisplay);
var _this = _possibleconstructorreturn(this, _modaldialog.call(this, player, options));
_this.on(player, 'error', _this.open);
return _this;
}
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*
* @deprecated since version 5.
*/
errordisplay.prototype.buildcssclass = function buildcssclass() {
return 'vjs-error-display ' + _modaldialog.prototype.buildcssclass.call(this);
};
/**
* gets the localized error message based on the `player`s error.
*
* @return {string}
* the `player`s error message localized or an empty string.
*/
errordisplay.prototype.content = function content() {
var error = this.player().error();
return error ? this.localize(error.message) : '';
};
return errordisplay;
}(_modaldialog2['default']);
/**
* the default options for an `errordisplay`.
*
* @private
*/
errordisplay.prototype.options_ = (0, _mergeoptions2['default'])(_modaldialog2['default'].prototype.options_, {
pauseonopen: false,
fillalways: true,
temporary: false,
uncloseable: true
});
_component2['default'].registercomponent('errordisplay', errordisplay);
exports['default'] = errordisplay;
},{"5":5,"50":50,"87":87}],42:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _events = _dereq_(82);
var events = _interoprequirewildcard(_events);
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; } }
/**
* `eventtarget` is a class that can have the same api as the dom `eventtarget`. it
* adds shorthand functions that wrap around lengthy functions. for example:
* the `on` function is a wrapper around `addeventlistener`.
*
* @see [eventtarget spec]{@link https://www.w3.org/tr/dom-level-2-events/events.html#events-eventtarget}
* @class eventtarget
*/
var eventtarget = function eventtarget() {};
/**
* a custom dom event.
*
* @typedef {object} eventtarget~event
* @see [properties]{@link https://developer.mozilla.org/en-us/docs/web/api/customevent}
*/
/**
* all event listeners should follow the following format.
*
* @callback eventtarget~eventlistener
* @this {eventtarget}
*
* @param {eventtarget~event} event
* the event that triggered this function
*
* @param {object} [hash]
* hash of data sent during the event
*/
/**
* an object containing event names as keys and booleans as values.
*
* > note: if an event name is set to a true value here {@link eventtarget#trigger}
* will have extra functionality. see that function for more information.
*
* @property eventtarget.prototype.allowedevents_
* @private
*/
/**
* @file src/js/event-target.js
*/
eventtarget.prototype.allowedevents_ = {};
/**
* adds an `event listener` to an instance of an `eventtarget`. an `event listener` is a
* function that will get called when an event with a certain name gets triggered.
*
* @param {string|string[]} type
* an event name or an array of event names.
*
* @param {eventtarget~eventlistener} fn
* the function to call with `eventtarget`s
*/
eventtarget.prototype.on = function (type, fn) {
// remove the addeventlistener alias before calling events.on
// so we don't get into an infinite type loop
var ael = this.addeventlistener;
this.addeventlistener = function () {};
events.on(this, type, fn);
this.addeventlistener = ael;
};
/**
* an alias of {@link eventtarget#on}. allows `eventtarget` to mimic
* the standard dom api.
*
* @function
* @see {@link eventtarget#on}
*/
eventtarget.prototype.addeventlistener = eventtarget.prototype.on;
/**
* removes an `event listener` for a specific event from an instance of `eventtarget`.
* this makes it so that the `event listener` will no longer get called when the
* named event happens.
*
* @param {string|string[]} type
* an event name or an array of event names.
*
* @param {eventtarget~eventlistener} fn
* the function to remove.
*/
eventtarget.prototype.off = function (type, fn) {
events.off(this, type, fn);
};
/**
* an alias of {@link eventtarget#off}. allows `eventtarget` to mimic
* the standard dom api.
*
* @function
* @see {@link eventtarget#off}
*/
eventtarget.prototype.removeeventlistener = eventtarget.prototype.off;
/**
* this function will add an `event listener` that gets triggered only once. after the
* first trigger it will get removed. this is like adding an `event listener`
* with {@link eventtarget#on} that calls {@link eventtarget#off} on itself.
*
* @param {string|string[]} type
* an event name or an array of event names.
*
* @param {eventtarget~eventlistener} fn
* the function to be called once for each event name.
*/
eventtarget.prototype.one = function (type, fn) {
// remove the addeventlistener alialing events.on
// so we don't get into an infinite type loop
var ael = this.addeventlistener;
this.addeventlistener = function () {};
events.one(this, type, fn);
this.addeventlistener = ael;
};
/**
* this function causes an event to happen. this will then cause any `event listeners`
* that are waiting for that event, to get called. if there are no `event listeners`
* for an event then nothing will happen.
*
* if the name of the `event` that is being triggered is in `eventtarget.allowedevents_`.
* trigger will also call the `on` + `uppercaseeventname` function.
*
* example:
* 'click' is in `eventtarget.allowedevents_`, so, trigger will attempt to call
* `onclick` if it exists.
*
* @param {string|eventtarget~event|object} event
* the name of the event, an `event`, or an object with a key of type set to
* an event name.
*/
eventtarget.prototype.trigger = function (event) {
var type = event.type || event;
if (typeof event === 'string') {
event = { type: type };
}
event = events.fixevent(event);
if (this.allowedevents_[type] && this['on' + type]) {
this['on' + type](event);
}
events.trigger(this, event);
};
/**
* an alias of {@link eventtarget#trigger}. allows `eventtarget` to mimic
* the standard dom api.
*
* @function
* @see {@link eventtarget#trigger}
*/
eventtarget.prototype.dispatchevent = eventtarget.prototype.trigger;
exports['default'] = eventtarget;
},{"82":82}],43:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
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; };
var _log = _dereq_(86);
var _log2 = _interoprequiredefault(_log);
var _obj = _dereq_(88);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
/**
* @file extend.js
* @module extend
*/
/**
* a combination of node inherits and babel's inherits (after transpile).
* both work the same but node adds `super_` to the subclass
* and bable adds the superclass as __proto__. both seem useful.
*
* @param {object} subclass
* the class to inherit to
*
* @param {object} superclass
* the class to inherit from
*
* @private
*/
var _inherits = 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 === 'undefined' ? 'undefined' : _typeof(superclass)));
}
subclass.prototype = object.create(superclass && superclass.prototype, {
constructor: {
value: subclass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superclass) {
// node
subclass.super_ = superclass;
}
};
/**
* function for subclassing using the same inheritance that
* videojs uses internally
*
* @param {object} superclass
* the class to inherit from
*
* @param {object} [subclassmethods={}]
* the class to inherit to
*
* @return {object}
* the new object with subclassmethods that inherited superclass.
*/
var extendfn = function extendfn(superclass) {
var subclassmethods = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var subclass = function subclass() {
superclass.apply(this, arguments);
};
var methods = {};
if ((0, _obj.isobject)(subclassmethods)) {
if (typeof subclassmethods.init === 'function') {
_log2['default'].warn('constructor logic via init() is deprecated; please use constructor() instead.');
subclassmethods.constructor = subclassmethods.init;
}
if (subclassmethods.constructor !== object.prototype.constructor) {
subclass = subclassmethods.constructor;
}
methods = subclassmethods;
} else if (typeof subclassmethods === 'function') {
subclass = subclassmethods;
}
_inherits(subclass, superclass);
// extend subobj's prototype with functions and other properties from props
for (var name in methods) {
if (methods.hasownproperty(name)) {
subclass.prototype[name] = methods[name];
}
}
return subclass;
};
exports['default'] = extendfn;
},{"86":86,"88":88}],44:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
/**
* store the browser-specific methods for the fullscreen api.
*
* @type {object}
* @see [specification]{@link https://fullscreen.spec.whatwg.org}
* @see [map approach from screenfull.js]{@link https://github.com/sindresorhus/screenfull.js}
*/
var fullscreenapi = {};
// browser api methods
/**
* @file fullscreen-api.js
* @module fullscreen-api
* @private
*/
var apimap = [['requestfullscreen', 'exitfullscreen', 'fullscreenelement', 'fullscreenenabled', 'fullscreenchange', 'fullscreenerror'],
// webkit
['webkitrequestfullscreen', 'webkitexitfullscreen', 'webkitfullscreenelement', 'webkitfullscreenenabled', 'webkitfullscreenchange', 'webkitfullscreenerror'],
// old webkit (safari 5.1)
['webkitrequestfullscreen', 'webkitcancelfullscreen', 'webkitcurrentfullscreenelement', 'webkitcancelfullscreen', 'webkitfullscreenchange', 'webkitfullscreenerror'],
// mozilla
['mozrequestfullscreen', 'mozcancelfullscreen', 'mozfullscreenelement', 'mozfullscreenenabled', 'mozfullscreenchange', 'mozfullscreenerror'],
// microsoft
['msrequestfullscreen', 'msexitfullscreen', 'msfullscreenelement', 'msfullscreenenabled', 'msfullscreenchange', 'msfullscreenerror']];
var specapi = apimap[0];
var browserapi = void 0;
// determine the supported set of functions
for (var i = 0; i < apimap.length; i++) {
// check for exitfullscreen function
if (apimap[i][1] in _document2['default']) {
browserapi = apimap[i];
break;
}
}
// map the browser api names to the spec api names
if (browserapi) {
for (var _i = 0; _i < browserapi.length; _i++) {
fullscreenapi[specapi[_i]] = browserapi[_i];
}
}
exports['default'] = fullscreenapi;
},{"94":94}],45:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file loading-spinner.js
*/
/**
* a loading spinner for use during waiting/loading events.
*
* @extends component
*/
var loadingspinner = function (_component) {
_inherits(loadingspinner, _component);
function loadingspinner() {
_classcallcheck(this, loadingspinner);
return _possibleconstructorreturn(this, _component.apply(this, arguments));
}
/**
* create the `loadingspinner`s dom element.
*
* @return {element}
* the dom element that gets created.
*/
loadingspinner.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-loading-spinner',
dir: 'ltr'
});
};
return loadingspinner;
}(_component2['default']);
_component2['default'].registercomponent('loadingspinner', loadingspinner);
exports['default'] = loadingspinner;
},{"5":5}],46:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _obj = _dereq_(88);
/**
* a custom `mediaerror` class which mimics the standard html5 `mediaerror` class.
*
* @param {number|string|object|mediaerror} value
* this can be of multiple types:
* - number: should be a standard error code
* - string: an error message (the code will be 0)
* - object: arbitrary properties
* - `mediaerror` (native): used to populate a video.js `mediaerror` object
* - `mediaerror` (video.js): will return itself if it's already a
* video.js `mediaerror` object.
*
* @see [mediaerror spec]{@link https://dev.w3.org/html5/spec-author-view/video.html#mediaerror}
* @see [encrypted mediaerror spec]{@link https://www.w3.org/tr/2013/wd-encrypted-media-20130510/#error-codes}
*
* @class mediaerror
*/
function mediaerror(value) {
// allow redundant calls to this constructor to avoid having `instanceof`
// checks peppered around the code.
if (value instanceof mediaerror) {
return value;
}
if (typeof value === 'number') {
this.code = value;
} else if (typeof value === 'string') {
// default code is zero, so this is a custom error
this.message = value;
} else if ((0, _obj.isobject)(value)) {
// we assign the `code` property manually because native `mediaerror` objects
// do not expose it as an own/enumerable property of the object.
if (typeof value.code === 'number') {
this.code = value.code;
}
(0, _obj.assign)(this, value);
}
if (!this.message) {
this.message = mediaerror.defaultmessages[this.code] || '';
}
}
/**
* the error code that refers two one of the defined `mediaerror` types
*
* @type {number}
*/
/**
* @file media-error.js
*/
mediaerror.prototype.code = 0;
/**
* an optional message that to show with the error. message is not part of the html5
* video spec but allows for more informative custom errors.
*
* @type {string}
*/
mediaerror.prototype.message = '';
/**
* an optional status code that can be set by plugins to allow even more detail about
* the error. for example a plugin might provide a specific http status code and an
* error message for that code. then when the plugin gets that error this class will
* know how to display an error message for it. this allows a custom message to show
* up on the `player` error overlay.
*
* @type {array}
*/
mediaerror.prototype.status = null;
/**
* errors indexed by the w3c standard. the order **cannot change**! see the
* specification listed under {@link mediaerror} for more information.
*
* @enum {array}
* @readonly
* @property {string} 0 - media_err_custom
* @property {string} 1 - media_err_custom
* @property {string} 2 - media_err_aborted
* @property {string} 3 - media_err_network
* @property {string} 4 - media_err_src_not_supported
* @property {string} 5 - media_err_encrypted
*/
mediaerror.errortypes = ['media_err_custom', 'media_err_aborted', 'media_err_network', 'media_err_decode', 'media_err_src_not_supported', 'media_err_encrypted'];
/**
* the default `mediaerror` messages based on the {@link mediaerror.errortypes}.
*
* @type {array}
* @constant
*/
mediaerror.defaultmessages = {
1: 'you aborted the media playback',
2: 'a network error caused the media download to fail part-way.',
3: 'the media playback was aborted due to a corruption problem or because the media used features your browser did not support.',
4: 'the media could not be loaded, either because the server or network failed or because the format is not supported.',
5: 'the media is encrypted and we do not have the keys to decrypt it.'
};
// add types as properties on mediaerror
// e.g. mediaerror.media_err_src_not_supported = 4;
for (var errnum = 0; errnum < mediaerror.errortypes.length; errnum++) {
mediaerror[mediaerror.errortypes[errnum]] = errnum;
// values should be accessible on both the class and instance
mediaerror.prototype[mediaerror.errortypes[errnum]] = errnum;
}
// jsdocs for instance/static members added above
// instance methods use `#` and static methods use `.`
/**
* w3c error code for any custom error.
*
* @member mediaerror#media_err_custom
* @constant {number}
* @default 0
*/
/**
* w3c error code for any custom error.
*
* @member mediaerror.media_err_custom
* @constant {number}
* @default 0
*/
/**
* w3c error code for media error aborted.
*
* @member mediaerror#media_err_aborted
* @constant {number}
* @default 1
*/
/**
* w3c error code for media error aborted.
*
* @member mediaerror.media_err_aborted
* @constant {number}
* @default 1
*/
/**
* w3c error code for any network error.
*
* @member mediaerror#media_err_network
* @constant {number}
* @default 2
*/
/**
* w3c error code for any network error.
*
* @member mediaerror.media_err_network
* @constant {number}
* @default 2
*/
/**
* w3c error code for any decoding error.
*
* @member mediaerror#media_err_decode
* @constant {number}
* @default 3
*/
/**
* w3c error code for any decoding error.
*
* @member mediaerror.media_err_decode
* @constant {number}
* @default 3
*/
/**
* w3c error code for any time that a source is not supported.
*
* @member mediaerror#media_err_src_not_supported
* @constant {number}
* @default 4
*/
/**
* w3c error code for any time that a source is not supported.
*
* @member mediaerror.media_err_src_not_supported
* @constant {number}
* @default 4
*/
/**
* w3c error code for any time that a source is encrypted.
*
* @member mediaerror#media_err_encrypted
* @constant {number}
* @default 5
*/
/**
* w3c error code for any time that a source is encrypted.
*
* @member mediaerror.media_err_encrypted
* @constant {number}
* @default 5
*/
exports['default'] = mediaerror;
},{"88":88}],47:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _clickablecomponent = _dereq_(3);
var _clickablecomponent2 = _interoprequiredefault(_clickablecomponent);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _menu = _dereq_(49);
var _menu2 = _interoprequiredefault(_menu);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _totitlecase = _dereq_(91);
var _totitlecase2 = _interoprequiredefault(_totitlecase);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file menu-button.js
*/
/**
* a `menubutton` class for any popup {@link menu}.
*
* @extends clickablecomponent
*/
var menubutton = function (_clickablecomponent) {
_inherits(menubutton, _clickablecomponent);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options={}]
* the key/value store of player options.
*/
function menubutton(player) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classcallcheck(this, menubutton);
var _this = _possibleconstructorreturn(this, _clickablecomponent.call(this, player, options));
_this.update();
_this.enabled_ = true;
_this.el_.setattribute('aria-haspopup', 'true');
_this.el_.setattribute('role', 'menuitem');
_this.on('keydown', _this.handlesubmenukeypress);
return _this;
}
/**
* update the menu based on the current state of its items.
*/
menubutton.prototype.update = function update() {
var menu = this.createmenu();
if (this.menu) {
this.removechild(this.menu);
}
this.menu = menu;
this.addchild(menu);
/**
* track the state of the menu button
*
* @type {boolean}
* @private
*/
this.buttonpressed_ = false;
this.el_.setattribute('aria-expanded', 'false');
if (this.items && this.items.length <= this.hidethreshold_) {
this.hide();
} else {
this.show();
}
};
/**
* create the menu and add all items to it.
*
* @return {menu}
* the constructed menu
*/
menubutton.prototype.createmenu = function createmenu() {
var menu = new _menu2['default'](this.player_);
/**
* hide the menu if the number of items is less than or equal to this threshold. this defaults
* to 0 and whenever we add items which can be hidden to the menu we'll increment it. we list
* it here because every time we run `createmenu` we need to reset the value.
*
* @protected
* @type {number}
*/
this.hidethreshold_ = 0;
// add a title list item to the top
if (this.options_.title) {
var title = dom.createel('li', {
classname: 'vjs-menu-title',
innerhtml: (0, _totitlecase2['default'])(this.options_.title),
tabindex: -1
});
this.hidethreshold_ += 1;
menu.children_.unshift(title);
dom.insertelfirst(title, menu.contentel());
}
this.items = this.createitems();
if (this.items) {
// add menu items to the menu
for (var i = 0; i < this.items.length; i++) {
menu.additem(this.items[i]);
}
}
return menu;
};
/**
* create the list of menu items. specific to each subclass.
*
* @abstract
*/
menubutton.prototype.createitems = function createitems() {};
/**
* create the `menubuttons`s dom element.
*
* @return {element}
* the element that gets created.
*/
menubutton.prototype.createel = function createel() {
return _clickablecomponent.prototype.createel.call(this, 'div', {
classname: this.buildcssclass()
});
};
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
menubutton.prototype.buildcssclass = function buildcssclass() {
var menubuttonclass = 'vjs-menu-button';
// if the inline option is passed, we want to use different styles altogether.
if (this.options_.inline === true) {
menubuttonclass += '-inline';
} else {
menubuttonclass += '-popup';
}
return 'vjs-menu-button ' + menubuttonclass + ' ' + _clickablecomponent.prototype.buildcssclass.call(this);
};
/**
* handle a click on a `menubutton`.
* see {@link clickablecomponent#handleclick} for instances where this is called.
*
* @param {eventtarget~event} event
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
menubutton.prototype.handleclick = function handleclick(event) {
// when you click the button it adds focus, which will show the menu.
// so we'll remove focus when the mouse leaves the button. focus is needed
// for tab navigation.
this.one(this.menu.contentel(), 'mouseleave', fn.bind(this, function (e) {
this.unpressbutton();
this.el_.blur();
}));
if (this.buttonpressed_) {
this.unpressbutton();
} else {
this.pressbutton();
}
};
/**
* handle tab, escape, down arrow, and up arrow keys for `menubutton`. see
* {@link clickablecomponent#handlekeypress} for instances where this is called.
*
* @param {eventtarget~event} event
* the `keydown` event that caused this function to be called.
*
* @listens keydown
*/
menubutton.prototype.handlekeypress = function handlekeypress(event) {
// escape (27) key or tab (9) key unpress the 'button'
if (event.which === 27 || event.which === 9) {
if (this.buttonpressed_) {
this.unpressbutton();
}
// don't preventdefault for tab key - we still want to lose focus
if (event.which !== 9) {
event.preventdefault();
}
// up (38) key or down (40) key press the 'button'
} else if (event.which === 38 || event.which === 40) {
if (!this.buttonpressed_) {
this.pressbutton();
event.preventdefault();
}
} else {
_clickablecomponent.prototype.handlekeypress.call(this, event);
}
};
/**
* handle a `keydown` event on a sub-menu. the listener for this is added in
* the constructor.
*
* @param {eventtarget~event} event
* key press event
*
* @listens keydown
*/
menubutton.prototype.handlesubmenukeypress = function handlesubmenukeypress(event) {
// escape (27) key or tab (9) key unpress the 'button'
if (event.which === 27 || event.which === 9) {
if (this.buttonpressed_) {
this.unpressbutton();
}
// don't preventdefault for tab key - we still want to lose focus
if (event.which !== 9) {
event.preventdefault();
}
}
};
/**
* put the current `menubutton` into a pressed state.
*/
menubutton.prototype.pressbutton = function pressbutton() {
if (this.enabled_) {
this.buttonpressed_ = true;
this.menu.lockshowing();
this.el_.setattribute('aria-expanded', 'true');
// set the focus into the submenu
this.menu.focus();
}
};
/**
* take the current `menubutton` out of a pressed state.
*/
menubutton.prototype.unpressbutton = function unpressbutton() {
if (this.enabled_) {
this.buttonpressed_ = false;
this.menu.unlockshowing();
this.el_.setattribute('aria-expanded', 'false');
// set focus back to this menu button
this.el_.focus();
}
};
/**
* disable the `menubutton`. don't allow it to be clicked.
*
* @return {menubutton}
* returns itself; method can be chained.
*/
menubutton.prototype.disable = function disable() {
// unpress, but don't force focus on this button
this.buttonpressed_ = false;
this.menu.unlockshowing();
this.el_.setattribute('aria-expanded', 'false');
this.enabled_ = false;
return _clickablecomponent.prototype.disable.call(this);
};
/**
* enable the `menubutton`. allow it to be clicked.
*
* @return {menubutton}
* returns itself; method can be chained.
*/
menubutton.prototype.enable = function enable() {
this.enabled_ = true;
return _clickablecomponent.prototype.enable.call(this);
};
return menubutton;
}(_clickablecomponent2['default']);
_component2['default'].registercomponent('menubutton', menubutton);
exports['default'] = menubutton;
},{"3":3,"49":49,"5":5,"81":81,"83":83,"91":91}],48:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _clickablecomponent = _dereq_(3);
var _clickablecomponent2 = _interoprequiredefault(_clickablecomponent);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _obj = _dereq_(88);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file menu-item.js
*/
/**
* the component for a menu item. `
`
*
* @extends clickablecomponent
*/
var menuitem = function (_clickablecomponent) {
_inherits(menuitem, _clickablecomponent);
/**
* creates an instance of the this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options={}]
* the key/value store of player options.
*
*/
function menuitem(player, options) {
_classcallcheck(this, menuitem);
var _this = _possibleconstructorreturn(this, _clickablecomponent.call(this, player, options));
_this.selectable = options.selectable;
_this.selected(options.selected);
if (_this.selectable) {
// todo: may need to be either menuitemcheckbox or menuitemradio,
// and may need logical grouping of menu items.
_this.el_.setattribute('role', 'menuitemcheckbox');
} else {
_this.el_.setattribute('role', 'menuitem');
}
return _this;
}
/**
* create the `menuitem's dom element
*
* @param {string} [type=li]
* element's node type, not actually used, always set to `li`.
*
* @param {object} [props={}]
* an object of properties that should be set on the element
*
* @param {object} [attrs={}]
* an object of attributes that should be set on the element
*
* @return {element}
* the element that gets created.
*/
menuitem.prototype.createel = function createel(type, props, attrs) {
// the control is textual, not just an icon
this.noniconcontrol = true;
return _clickablecomponent.prototype.createel.call(this, 'li', (0, _obj.assign)({
classname: 'vjs-menu-item',
innerhtml: this.localize(this.options_.label),
tabindex: -1
}, props), attrs);
};
/**
* any click on a `menuitem` puts int into the selected state.
* see {@link clickablecomponent#handleclick} for instances where this is called.
*
* @param {eventtarget~event} event
* the `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
menuitem.prototype.handleclick = function handleclick(event) {
this.selected(true);
};
/**
* set the state for this menu item as selected or not.
*
* @param {boolean} selected
* if the menu item is selected or not
*/
menuitem.prototype.selected = function selected(_selected) {
if (this.selectable) {
if (_selected) {
this.addclass('vjs-selected');
this.el_.setattribute('aria-checked', 'true');
// aria-checked isn't fully supported by browsers/screen readers,
// so indicate selected state to screen reader in the control text.
this.controltext(', selected');
} else {
this.removeclass('vjs-selected');
this.el_.setattribute('aria-checked', 'false');
// indicate un-selected state to screen reader
// note that a space clears out the selected state text
this.controltext(' ');
}
}
};
return menuitem;
}(_clickablecomponent2['default']);
_component2['default'].registercomponent('menuitem', menuitem);
exports['default'] = menuitem;
},{"3":3,"5":5,"88":88}],49:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _events = _dereq_(82);
var events = _interoprequirewildcard(_events);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file menu.js
*/
/**
* the menu component is used to build popup menus, including subtitle and
* captions selection menus.
*
* @extends component
*/
var menu = function (_component) {
_inherits(menu, _component);
/**
* create an instance of this class.
*
* @param {player} player
* the player that this component should attach to
*
* @param {object} [options]
* object of option names and values
*
*/
function menu(player, options) {
_classcallcheck(this, menu);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.focusedchild_ = -1;
_this.on('keydown', _this.handlekeypress);
return _this;
}
/**
* add a {@link menuitem} to the menu.
*
* @param {object|string} component
* the name or instance of the `menuitem` to add.
*
*/
menu.prototype.additem = function additem(component) {
this.addchild(component);
component.on('click', fn.bind(this, function (event) {
this.unlockshowing();
// todo: need to set keyboard focus back to the menubutton
}));
};
/**
* create the `menu`s dom element.
*
* @return {element}
* the element that was created
*/
menu.prototype.createel = function createel() {
var contenteltype = this.options_.contenteltype || 'ul';
this.contentel_ = dom.createel(contenteltype, {
classname: 'vjs-menu-content'
});
this.contentel_.setattribute('role', 'menu');
var el = _component.prototype.createel.call(this, 'div', {
append: this.contentel_,
classname: 'vjs-menu'
});
el.setattribute('role', 'presentation');
el.appendchild(this.contentel_);
// prevent clicks from bubbling up. needed for menu buttons,
// where a click on the parent is significant
events.on(el, 'click', function (event) {
event.preventdefault();
event.stopimmediatepropagation();
});
return el;
};
/**
* handle a `keydown` event on this menu. this listener is added in the constructor.
*
* @param {eventtarget~event} event
* a `keydown` event that happened on the menu.
*
* @listens keydown
*/
menu.prototype.handlekeypress = function handlekeypress(event) {
// left and down arrows
if (event.which === 37 || event.which === 40) {
event.preventdefault();
this.stepforward();
// up and right arrows
} else if (event.which === 38 || event.which === 39) {
event.preventdefault();
this.stepback();
}
};
/**
* move to next (lower) menu item for keyboard users.
*/
menu.prototype.stepforward = function stepforward() {
var stepchild = 0;
if (this.focusedchild_ !== undefined) {
stepchild = this.focusedchild_ + 1;
}
this.focus(stepchild);
};
/**
* move to previous (higher) menu item for keyboard users.
*/
menu.prototype.stepback = function stepback() {
var stepchild = 0;
if (this.focusedchild_ !== undefined) {
stepchild = this.focusedchild_ - 1;
}
this.focus(stepchild);
};
/**
* set focus on a {@link menuitem} in the `menu`.
*
* @param {object|string} [item=0]
* index of child item set focus on.
*/
menu.prototype.focus = function focus() {
var item = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var children = this.children().slice();
var havetitle = children.length && children[0].classname && /vjs-menu-title/.test(children[0].classname);
if (havetitle) {
children.shift();
}
if (children.length > 0) {
if (item < 0) {
item = 0;
} else if (item >= children.length) {
item = children.length - 1;
}
this.focusedchild_ = item;
children[item].el_.focus();
}
};
return menu;
}(_component2['default']);
_component2['default'].registercomponent('menu', menu);
exports['default'] = menu;
},{"5":5,"81":81,"82":82,"83":83}],50:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
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; } }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file modal-dialog.js
*/
var modal_class_name = 'vjs-modal-dialog';
var esc = 27;
/**
* the `modaldialog` displays over the video and its controls, which blocks
* interaction with the player until it is closed.
*
* modal dialogs include a "close" button and will close when that button
* is activated - or when esc is pressed anywhere.
*
* @extends component
*/
var modaldialog = function (_component) {
_inherits(modaldialog, _component);
/**
* create an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {mixed} [options.content=undefined]
* provide customized content for this modal.
*
* @param {string} [options.description]
* a text description for the modal, primarily for accessibility.
*
* @param {boolean} [options.fillalways=false]
* normally, modals are automatically filled only the first time
* they open. this tells the modal to refresh its content
* every time it opens.
*
* @param {string} [options.label]
* a text label for the modal, primarily for accessibility.
*
* @param {boolean} [options.temporary=true]
* if `true`, the modal can only be opened once; it will be
* disposed as soon as it's closed.
*
* @param {boolean} [options.uncloseable=false]
* if `true`, the user will not be able to close the modal
* through the ui in the normal ways. programmatic closing is
* still possible.
*/
function modaldialog(player, options) {
_classcallcheck(this, modaldialog);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.opened_ = _this.hasbeenopened_ = _this.hasbeenfilled_ = false;
_this.closeable(!_this.options_.uncloseable);
_this.content(_this.options_.content);
// make sure the contentel is defined after any children are initialized
// because we only want the contents of the modal in the contentel
// (not the ui elements like the close button).
_this.contentel_ = dom.createel('div', {
classname: modal_class_name + '-content'
}, {
role: 'document'
});
_this.descel_ = dom.createel('p', {
classname: modal_class_name + '-description vjs-offscreen',
id: _this.el().getattribute('aria-describedby')
});
dom.textcontent(_this.descel_, _this.description());
_this.el_.appendchild(_this.descel_);
_this.el_.appendchild(_this.contentel_);
return _this;
}
/**
* create the `modaldialog`'s dom element
*
* @return {element}
* the dom element that gets created.
*/
modaldialog.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: this.buildcssclass(),
tabindex: -1
}, {
'aria-describedby': this.id() + '_description',
'aria-hidden': 'true',
'aria-label': this.label(),
'role': 'dialog'
});
};
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
modaldialog.prototype.buildcssclass = function buildcssclass() {
return modal_class_name + ' vjs-hidden ' + _component.prototype.buildcssclass.call(this);
};
/**
* handles `keydown` events on the document, looking for esc, which closes
* the modal.
*
* @param {eventtarget~event} e
* the keypress that triggered this event.
*
* @listens keydown
*/
modaldialog.prototype.handlekeypress = function handlekeypress(e) {
if (e.which === esc && this.closeable()) {
this.close();
}
};
/**
* returns the label string for this modal. primarily used for accessibility.
*
* @return {string}
* the localized or raw label of this modal.
*/
modaldialog.prototype.label = function label() {
return this.options_.label || this.localize('modal window');
};
/**
* returns the description string for this modal. primarily used for
* accessibility.
*
* @return {string}
* the localized or raw description of this modal.
*/
modaldialog.prototype.description = function description() {
var desc = this.options_.description || this.localize('this is a modal window.');
// append a universal closeability message if the modal is closeable.
if (this.closeable()) {
desc += ' ' + this.localize('this modal can be closed by pressing the escape key or activating the close button.');
}
return desc;
};
/**
* opens the modal.
*
* @fires modaldialog#beforemodalopen
* @fires modaldialog#modalopen
*
* @return {modaldialog}
* returns itself; method can be chained.
*/
modaldialog.prototype.open = function open() {
if (!this.opened_) {
var player = this.player();
/**
* fired just before a `modaldialog` is opened.
*
* @event modaldialog#beforemodalopen
* @type {eventtarget~event}
*/
this.trigger('beforemodalopen');
this.opened_ = true;
// fill content if the modal has never opened before and
// never been filled.
if (this.options_.fillalways || !this.hasbeenopened_ && !this.hasbeenfilled_) {
this.fill();
}
// if the player was playing, pause it and take note of its previously
// playing state.
this.wasplaying_ = !player.paused();
if (this.options_.pauseonopen && this.wasplaying_) {
player.pause();
}
if (this.closeable()) {
this.on(this.el_.ownerdocument, 'keydown', fn.bind(this, this.handlekeypress));
}
player.controls(false);
this.show();
this.el().setattribute('aria-hidden', 'false');
/**
* fired just after a `modaldialog` is opened.
*
* @event modaldialog#modalopen
* @type {eventtarget~event}
*/
this.trigger('modalopen');
this.hasbeenopened_ = true;
}
return this;
};
/**
* if the `modaldialog` is currently open or closed.
*
* @param {boolean} [value]
* if given, it will open (`true`) or close (`false`) the modal.
*
* @return {boolean}
* the current open state of the modaldialog
*/
modaldialog.prototype.opened = function opened(value) {
if (typeof value === 'boolean') {
this[value ? 'open' : 'close']();
}
return this.opened_;
};
/**
* closes the modal, does nothing if the `modaldialog` is
* not open.
*
* @fires modaldialog#beforemodalclose
* @fires modaldialog#modalclose
*
* @return {modaldialog}
* returns itself; method can be chained.
*/
modaldialog.prototype.close = function close() {
if (this.opened_) {
var player = this.player();
/**
* fired just before a `modaldialog` is closed.
*
* @event modaldialog#beforemodalclose
* @type {eventtarget~event}
*/
this.trigger('beforemodalclose');
this.opened_ = false;
if (this.wasplaying_ && this.options_.pauseonopen) {
player.play();
}
if (this.closeable()) {
this.off(this.el_.ownerdocument, 'keydown', fn.bind(this, this.handlekeypress));
}
player.controls(true);
this.hide();
this.el().setattribute('aria-hidden', 'true');
/**
* fired just after a `modaldialog` is closed.
*
* @event modaldialog#modalclose
* @type {eventtarget~event}
*/
this.trigger('modalclose');
if (this.options_.temporary) {
this.dispose();
}
}
return this;
};
/**
* check to see if the `modaldialog` is closeable via the ui.
*
* @param {boolean} [value]
* if given as a boolean, it will set the `closeable` option.
*
* @return {boolean}
* returns the final value of the closable option.
*/
modaldialog.prototype.closeable = function closeable(value) {
if (typeof value === 'boolean') {
var closeable = this.closeable_ = !!value;
var close = this.getchild('closebutton');
// if this is being made closeable and has no close button, add one.
if (closeable && !close) {
// the close button should be a child of the modal - not its
// content element, so temporarily change the content element.
var temp = this.contentel_;
this.contentel_ = this.el_;
close = this.addchild('closebutton', { controltext: 'close modal dialog' });
this.contentel_ = temp;
this.on(close, 'close', this.close);
}
// if this is being made uncloseable and has a close button, remove it.
if (!closeable && close) {
this.off(close, 'close', this.close);
this.removechild(close);
close.dispose();
}
}
return this.closeable_;
};
/**
* fill the modal's content element with the modal's "content" option.
* the content element will be emptied before this change takes place.
*
* @return {modaldialog}
* returns itself; method can be chained.
*/
modaldialog.prototype.fill = function fill() {
return this.fillwith(this.content());
};
/**
* fill the modal's content element with arbitrary content.
* the content element will be emptied before this change takes place.
*
* @fires modaldialog#beforemodalfill
* @fires modaldialog#modalfill
*
* @param {mixed} [content]
* the same rules apply to this as apply to the `content` option.
*
* @return {modaldialog}
* returns itself; method can be chained.
*/
modaldialog.prototype.fillwith = function fillwith(content) {
var contentel = this.contentel();
var parentel = contentel.parentnode;
var nextsiblingel = contentel.nextsibling;
/**
* fired just before a `modaldialog` is filled with content.
*
* @event modaldialog#beforemodalfill
* @type {eventtarget~event}
*/
this.trigger('beforemodalfill');
this.hasbeenfilled_ = true;
// detach the content element from the dom before performing
// manipulation to avoid modifying the live dom multiple times.
parentel.removechild(contentel);
this.empty();
dom.insertcontent(contentel, content);
/**
* fired just after a `modaldialog` is filled with content.
*
* @event modaldialog#modalfill
* @type {eventtarget~event}
*/
this.trigger('modalfill');
// re-inject the re-filled content element.
if (nextsiblingel) {
parentel.insertbefore(contentel, nextsiblingel);
} else {
parentel.appendchild(contentel);
}
return this;
};
/**
* empties the content element. this happens anytime the modal is filled.
*
* @fires modaldialog#beforemodalempty
* @fires modaldialog#modalempty
*
* @return {modaldialog}
* returns itself; method can be chained.
*/
modaldialog.prototype.empty = function empty() {
/**
* fired just before a `modaldialog` is emptied.
*
* @event modaldialog#beforemodalempty
* @type {eventtarget~event}
*/
this.trigger('beforemodalempty');
dom.emptyel(this.contentel());
/**
* fired just after a `modaldialog` is emptied.
*
* @event modaldialog#modalempty
* @type {eventtarget~event}
*/
this.trigger('modalempty');
return this;
};
/**
* gets or sets the modal content, which gets normalized before being
* rendered into the dom.
*
* this does not update the dom or fill the modal, but it is called during
* that process.
*
* @param {mixed} [value]
* if defined, sets the internal content value to be used on the
* next call(s) to `fill`. this value is normalized before being
* inserted. to "clear" the internal content value, pass `null`.
*
* @return {mixed}
* the current content of the modal dialog
*/
modaldialog.prototype.content = function content(value) {
if (typeof value !== 'undefined') {
this.content_ = value;
}
return this.content_;
};
return modaldialog;
}(_component2['default']);
/**
* default options for `modaldialog` default options.
*
* @type {object}
* @private
*/
modaldialog.prototype.options_ = {
pauseonopen: true,
temporary: true
};
_component2['default'].registercomponent('modaldialog', modaldialog);
exports['default'] = modaldialog;
},{"5":5,"81":81,"83":83}],51:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
var _events = _dereq_(82);
var events = _interoprequirewildcard(_events);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _guid = _dereq_(85);
var guid = _interoprequirewildcard(_guid);
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
var _log = _dereq_(86);
var _log2 = _interoprequiredefault(_log);
var _totitlecase = _dereq_(91);
var _totitlecase2 = _interoprequiredefault(_totitlecase);
var _timeranges = _dereq_(90);
var _buffer = _dereq_(79);
var _stylesheet = _dereq_(89);
var stylesheet = _interoprequirewildcard(_stylesheet);
var _fullscreenapi = _dereq_(44);
var _fullscreenapi2 = _interoprequiredefault(_fullscreenapi);
var _mediaerror = _dereq_(46);
var _mediaerror2 = _interoprequiredefault(_mediaerror);
var _tuple = _dereq_(97);
var _tuple2 = _interoprequiredefault(_tuple);
var _obj = _dereq_(88);
var _mergeoptions = _dereq_(87);
var _mergeoptions2 = _interoprequiredefault(_mergeoptions);
var _texttracklistconverter = _dereq_(69);
var _texttracklistconverter2 = _interoprequiredefault(_texttracklistconverter);
var _modaldialog = _dereq_(50);
var _modaldialog2 = _interoprequiredefault(_modaldialog);
var _tech = _dereq_(62);
var _tech2 = _interoprequiredefault(_tech);
var _audiotracklist = _dereq_(63);
var _audiotracklist2 = _interoprequiredefault(_audiotracklist);
var _videotracklist = _dereq_(76);
var _videotracklist2 = _interoprequiredefault(_videotracklist);
_dereq_(61);
_dereq_(59);
_dereq_(55);
_dereq_(68);
_dereq_(45);
_dereq_(1);
_dereq_(4);
_dereq_(8);
_dereq_(41);
_dereq_(71);
_dereq_(60);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file player.js
*/
// subclasses component
// the following imports are used only to ensure that the corresponding modules
// are always included in the video.js package. importing the modules will
// execute them and they will register themselves with video.js.
// import html5 tech, at least for disposing the original video tag.
// the following tech events are simply re-triggered
// on the player when they happen
var tech_events_retrigger = [
/**
* fired while the user agent is downloading media data.
*
* @event player#progress
* @type {eventtarget~event}
*/
/**
* retrigger the `progress` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechprogress_
* @fires player#progress
* @listens tech#progress
*/
'progress',
/**
* fires when the loading of an audio/video is aborted.
*
* @event player#abort
* @type {eventtarget~event}
*/
/**
* retrigger the `abort` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechabort_
* @fires player#abort
* @listens tech#abort
*/
'abort',
/**
* fires when the browser is intentionally not getting media data.
*
* @event player#suspend
* @type {eventtarget~event}
*/
/**
* retrigger the `suspend` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechsuspend_
* @fires player#suspend
* @listens tech#suspend
*/
'suspend',
/**
* fires when the current playlist is empty.
*
* @event player#emptied
* @type {eventtarget~event}
*/
/**
* retrigger the `emptied` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechemptied_
* @fires player#emptied
* @listens tech#emptied
*/
'emptied',
/**
* fires when the browser is trying to get media data, but data is not available.
*
* @event player#stalled
* @type {eventtarget~event}
*/
/**
* retrigger the `stalled` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechstalled_
* @fires player#stalled
* @listens tech#stalled
*/
'stalled',
/**
* fires when the browser has loaded meta data for the audio/video.
*
* @event player#loadedmetadata
* @type {eventtarget~event}
*/
/**
* retrigger the `stalled` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechloadedmetadata_
* @fires player#loadedmetadata
* @listens tech#loadedmetadata
*/
'loadedmetadata',
/**
* fires when the browser has loaded the current frame of the audio/video.
*
* @event player#loadeddata
* @type {event}
*/
/**
* retrigger the `loadeddata` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechloaddeddata_
* @fires player#loadeddata
* @listens tech#loadeddata
*/
'loadeddata',
/**
* fires when the current playback position has changed.
*
* @event player#timeupdate
* @type {event}
*/
/**
* retrigger the `timeupdate` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechtimeupdate_
* @fires player#timeupdate
* @listens tech#timeupdate
*/
'timeupdate',
/**
* fires when the playing speed of the audio/video is changed
*
* @event player#ratechange
* @type {event}
*/
/**
* retrigger the `ratechange` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechratechange_
* @fires player#ratechange
* @listens tech#ratechange
*/
'ratechange',
/**
* fires when the volume has been changed
*
* @event player#volumechange
* @type {event}
*/
/**
* retrigger the `volumechange` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechvolumechange_
* @fires player#volumechange
* @listens tech#volumechange
*/
'volumechange',
/**
* fires when the text track has been changed
*
* @event player#texttrackchange
* @type {event}
*/
/**
* retrigger the `texttrackchange` event that was triggered by the {@link tech}.
*
* @private
* @method player#handletechtexttrackchange_
* @fires player#texttrackchange
* @listens tech#texttrackchange
*/
'texttrackchange'];
/**
* an instance of the `player` class is created when any of the video.js setup methods
* are used to initialize a video.
*
* after an instance has been created it can be accessed globally in two ways:
* 1. by calling `videojs('example_video_1');`
* 2. by using it directly via `videojs.players.example_video_1;`
*
* @extends component
*/
var player = function (_component) {
_inherits(player, _component);
/**
* create an instance of this class.
*
* @param {element} tag
* the original video dom element used for configuring options.
*
* @param {object} [options]
* object of option names and values.
*
* @param {component~readycallback} [ready]
* ready callback function.
*/
function player(tag, options, ready) {
_classcallcheck(this, player);
// make sure tag id exists
tag.id = tag.id || 'vjs_video_' + guid.newguid();
// set options
// the options argument overrides options set in the video tag
// which overrides globally set options.
// this latter part coincides with the load order
// (tag must exist before player)
options = (0, _obj.assign)(player.gettagsettings(tag), options);
// delay the initialization of children because we need to set up
// player properties first, and can't use `this` before `super()`
options.initchildren = false;
// same with creating the element
options.createel = false;
// we don't want the player to report touch activity on itself
// see enabletouchactivity in component
options.reporttouchactivity = false;
// if language is not set, get the closest lang attribute
if (!options.language) {
if (typeof tag.closest === 'function') {
var closest = tag.closest('[lang]');
if (closest) {
options.language = closest.getattribute('lang');
}
} else {
var element = tag;
while (element && element.nodetype === 1) {
if (dom.getelattributes(element).hasownproperty('lang')) {
options.language = element.getattribute('lang');
break;
}
element = element.parentnode;
}
}
}
// run base component initializing with new options
// if the global option object was accidentally blown away by
// someone, bail early with an informative error
var _this = _possibleconstructorreturn(this, _component.call(this, null, options, ready));
if (!_this.options_ || !_this.options_.techorder || !_this.options_.techorder.length) {
throw new error('no techorder specified. did you overwrite ' + 'videojs.options instead of just changing the ' + 'properties you want to override?');
}
// store the original tag used to set options
_this.tag = tag;
// store the tag attributes used to restore html5 element
_this.tagattributes = tag && dom.getelattributes(tag);
// update current language
_this.language(_this.options_.language);
// update supported languages
if (options.languages) {
// normalise player option languages to lowercase
var languagestolower = {};
object.getownpropertynames(options.languages).foreach(function (name) {
languagestolower[name.tolowercase()] = options.languages[name];
});
_this.languages_ = languagestolower;
} else {
_this.languages_ = player.prototype.options_.languages;
}
// cache for video property values.
_this.cache_ = {};
// set poster
_this.poster_ = options.poster || '';
// set controls
_this.controls_ = !!options.controls;
// original tag settings stored in options
// now remove immediately so native controls don't flash.
// may be turned back on by html5 tech if nativecontrolsfortouch is true
tag.controls = false;
/*
* store the internal state of scrubbing
*
* @private
* @return {boolean} true if the user is scrubbing
*/
_this.scrubbing_ = false;
_this.el_ = _this.createel();
// we also want to pass the original player options to each component and plugin
// as well so they don't need to reach back into the player for options later.
// we also need to do another copy of this.options_ so we don't end up with
// an infinite loop.
var playeroptionscopy = (0, _mergeoptions2['default'])(_this.options_);
// load plugins
if (options.plugins) {
var plugins = options.plugins;
object.getownpropertynames(plugins).foreach(function (name) {
if (typeof this[name] === 'function') {
this[name](plugins[name]);
} else {
_log2['default'].error('unable to find plugin:', name);
}
}, _this);
}
_this.options_.playeroptions = playeroptionscopy;
_this.initchildren();
// set isaudio based on whether or not an audio tag was used
_this.isaudio(tag.nodename.tolowercase() === 'audio');
// update controls classname. can't do this when the controls are initially
// set because the element doesn't exist yet.
if (_this.controls()) {
_this.addclass('vjs-controls-enabled');
} else {
_this.addclass('vjs-controls-disabled');
}
// set aria label and region role depending on player type
_this.el_.setattribute('role', 'region');
if (_this.isaudio()) {
_this.el_.setattribute('aria-label', 'audio player');
} else {
_this.el_.setattribute('aria-label', 'video player');
}
if (_this.isaudio()) {
_this.addclass('vjs-audio');
}
if (_this.flexnotsupported_()) {
_this.addclass('vjs-no-flex');
}
// todo: make this smarter. toggle user state between touching/mousing
// using events, since devices can have both touch and mouse events.
// if (browser.touch_enabled) {
// this.addclass('vjs-touch-enabled');
// }
// ios safari has broken hover handling
if (!browser.is_ios) {
_this.addclass('vjs-workinghover');
}
// make player easily findable by id
player.players[_this.id_] = _this;
// when the player is first initialized, trigger activity so components
// like the control bar show themselves if needed
_this.useractive(true);
_this.reportuseractivity();
_this.listenforuseractivity_();
_this.on('fullscreenchange', _this.handlefullscreenchange_);
_this.on('stageclick', _this.handlestageclick_);
return _this;
}
/**
* destroys the video player and does any necessary cleanup.
*
* this is especially helpful if you are dynamically adding and removing videos
* to/from the dom.
*
* @fires player#dispose
*/
player.prototype.dispose = function dispose() {
/**
* called when the player is being disposed of.
*
* @event player#dispose
* @type {eventtarget~event}
*/
this.trigger('dispose');
// prevent dispose from being called twice
this.off('dispose');
if (this.styleel_ && this.styleel_.parentnode) {
this.styleel_.parentnode.removechild(this.styleel_);
}
// kill reference to this player
player.players[this.id_] = null;
if (this.tag && this.tag.player) {
this.tag.player = null;
}
if (this.el_ && this.el_.player) {
this.el_.player = null;
}
if (this.tech_) {
this.tech_.dispose();
}
_component.prototype.dispose.call(this);
};
/**
* create the `player`'s dom element.
*
* @return {element}
* the dom element that gets created.
*/
player.prototype.createel = function createel() {
var tag = this.tag;
var el = void 0;
var playerelingest = this.playerelingest_ = tag.parentnode && tag.parentnode.hasattribute && tag.parentnode.hasattribute('data-vjs-player');
if (playerelingest) {
el = this.el_ = tag.parentnode;
} else {
el = this.el_ = _component.prototype.createel.call(this, 'div');
}
// set tabindex to -1 so we could focus on the player element
tag.setattribute('tabindex', '-1');
// remove width/height attrs from tag so css can make it 100% width/height
tag.removeattribute('width');
tag.removeattribute('height');
// copy over all the attributes from the tag, including id and class
// id will now reference player box, not the video tag
var attrs = dom.getelattributes(tag);
object.getownpropertynames(attrs).foreach(function (attr) {
// workaround so we don't totally break ie7
// http://stackoverflow.com/questions/3653444/css-styles-not-applied-on-dynamic-elements-in-internet-explorer-7
if (attr === 'class') {
el.classname += ' ' + attrs[attr];
} else {
el.setattribute(attr, attrs[attr]);
}
});
// update tag id/class for use as html5 playback tech
// might think we should do this after embedding in container so .vjs-tech class
// doesn't flash 100% width/height, but class only applies with .video-js parent
tag.playerid = tag.id;
tag.id += '_html5_api';
tag.classname = 'vjs-tech';
// make player findable on elements
tag.player = el.player = this;
// default state of video is paused
this.addclass('vjs-paused');
// add a style element in the player that we'll use to set the width/height
// of the player in a way that's still overrideable by css, just like the
// video element
if (_window2['default'].videojs_no_dynamic_style !== true) {
this.styleel_ = stylesheet.createstyleelement('vjs-styles-dimensions');
var defaultsstyleel = dom.$('.vjs-styles-defaults');
var head = dom.$('head');
head.insertbefore(this.styleel_, defaultsstyleel ? defaultsstyleel.nextsibling : head.firstchild);
}
// pass in the width/height/aspectratio options which will update the style el
this.width(this.options_.width);
this.height(this.options_.height);
this.fluid(this.options_.fluid);
this.aspectratio(this.options_.aspectratio);
// hide any links within the video/audio tag, because ie doesn't hide them completely.
var links = tag.getelementsbytagname('a');
for (var i = 0; i < links.length; i++) {
var linkel = links.item(i);
dom.addelclass(linkel, 'vjs-hidden');
linkel.setattribute('hidden', 'hidden');
}
// insertelfirst seems to cause the networkstate to flicker from 3 to 2, so
// keep track of the original for later so we can know if the source originally failed
tag.initnetworkstate_ = tag.networkstate;
// wrap video tag in div (el/box) container
if (tag.parentnode && !playerelingest) {
tag.parentnode.insertbefore(el, tag);
}
// insert the tag as the first child of the player element
// then manually add it to the children array so that this.addchild
// will work properly for other components
//
// breaks iphone, fixed in html5 setup.
dom.insertelfirst(tag, el);
this.children_.unshift(tag);
this.el_ = el;
return el;
};
/**
* a getter/setter for the `player`'s width.
*
* @param {number} [value]
* the value to set the `player's width to.
*
* @return {number}
* the current width of the `player`.
*/
player.prototype.width = function width(value) {
return this.dimension('width', value);
};
/**
* a getter/setter for the `player`'s height.
*
* @param {number} [value]
* the value to set the `player's heigth to.
*
* @return {number}
* the current heigth of the `player`.
*/
player.prototype.height = function height(value) {
return this.dimension('height', value);
};
/**
* a getter/setter for the `player`'s width & height.
*
* @param {string} dimension
* this string can be:
* - 'width'
* - 'height'
*
* @param {number} [value]
* value for dimension specified in the first argument.
*
* @return {player|number}
* - returns itself when setting; method can be chained.
* - the dimension arguments value when getting (width/height).
*/
player.prototype.dimension = function dimension(_dimension, value) {
var privdimension = _dimension + '_';
if (value === undefined) {
return this[privdimension] || 0;
}
if (value === '') {
// if an empty string is given, reset the dimension to be automatic
this[privdimension] = undefined;
} else {
var parsedval = parsefloat(value);
if (isnan(parsedval)) {
_log2['default'].error('improper value "' + value + '" supplied for for ' + _dimension);
return this;
}
this[privdimension] = parsedval;
}
this.updatestyleel_();
return this;
};
/**
* a getter/setter/toggler for the vjs-fluid `classname` on the `player`.
*
* @param {boolean} [bool]
* - a value of true adds the class.
* - a value of false removes the class.
* - no value will toggle the fluid class.
*
* @return {boolean|undefined}
* - the value of fluid when getting.
* - `undefined` when setting.
*/
player.prototype.fluid = function fluid(bool) {
if (bool === undefined) {
return !!this.fluid_;
}
this.fluid_ = !!bool;
if (bool) {
this.addclass('vjs-fluid');
} else {
this.removeclass('vjs-fluid');
}
this.updatestyleel_();
};
/**
* get/set the aspect ratio
*
* @param {string} [ratio]
* aspect ratio for player
*
* @return {string|undefined}
* returns the current aspect ratio when getting
*/
/**
* a getter/setter for the `player`'s aspect ratio.
*
* @param {string} [ratio]
* the value to set the `player's aspect ratio to.
*
* @return {string|undefined}
* - the current aspect ratio of the `player` when getting.
* - undefined when setting
*/
player.prototype.aspectratio = function aspectratio(ratio) {
if (ratio === undefined) {
return this.aspectratio_;
}
// check for width:height format
if (!/^\d+\:\d+$/.test(ratio)) {
throw new error('improper value supplied for aspect ratio. the format should be width:height, for example 16:9.');
}
this.aspectratio_ = ratio;
// we're assuming if you set an aspect ratio you want fluid mode,
// because in fixed mode you could calculate width and height yourself.
this.fluid(true);
this.updatestyleel_();
};
/**
* update styles of the `player` element (height, width and aspect ratio).
*
* @private
* @listens tech#loadedmetadata
*/
player.prototype.updatestyleel_ = function updatestyleel_() {
if (_window2['default'].videojs_no_dynamic_style === true) {
var _width = typeof this.width_ === 'number' ? this.width_ : this.options_.width;
var _height = typeof this.height_ === 'number' ? this.height_ : this.options_.height;
var techel = this.tech_ && this.tech_.el();
if (techel) {
if (_width >= 0) {
techel.width = _width;
}
if (_height >= 0) {
techel.height = _height;
}
}
return;
}
var width = void 0;
var height = void 0;
var aspectratio = void 0;
var idclass = void 0;
// the aspect ratio is either used directly or to calculate width and height.
if (this.aspectratio_ !== undefined && this.aspectratio_ !== 'auto') {
// use any aspectratio that's been specifically set
aspectratio = this.aspectratio_;
} else if (this.videowidth() > 0) {
// otherwise try to get the aspect ratio from the video metadata
aspectratio = this.videowidth() + ':' + this.videoheight();
} else {
// or use a default. the video element's is 2:1, but 16:9 is more common.
aspectratio = '16:9';
}
// get the ratio as a decimal we can use to calculate dimensions
var ratioparts = aspectratio.split(':');
var ratiomultiplier = ratioparts[1] / ratioparts[0];
if (this.width_ !== undefined) {
// use any width that's been specifically set
width = this.width_;
} else if (this.height_ !== undefined) {
// or calulate the width from the aspect ratio if a height has been set
width = this.height_ / ratiomultiplier;
} else {
// or use the video's metadata, or use the video el's default of 300
width = this.videowidth() || 300;
}
if (this.height_ !== undefined) {
// use any height that's been specifically set
height = this.height_;
} else {
// otherwise calculate the height from the ratio and the width
height = width * ratiomultiplier;
}
// ensure the css class is valid by starting with an alpha character
if (/^[^a-za-z]/.test(this.id())) {
idclass = 'dimensions-' + this.id();
} else {
idclass = this.id() + '-dimensions';
}
// ensure the right class is still on the player for the style element
this.addclass(idclass);
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 ');
};
/**
* load/create an instance of playback {@link tech} including element
* and api methods. then append the `tech` element in `player` as a child.
*
* @param {string} techname
* name of the playback technology
*
* @param {string} source
* video source
*
* @private
*/
player.prototype.loadtech_ = function loadtech_(techname, source) {
var _this2 = this;
// pause and remove current playback technology
if (this.tech_) {
this.unloadtech_();
}
// get rid of the html5 video tag as soon as we are using another tech
if (techname !== 'html5' && this.tag) {
_tech2['default'].gettech('html5').disposemediaelement(this.tag);
this.tag.player = null;
this.tag = null;
}
this.techname_ = techname;
// turn off api access because we're loading a new tech that might load asynchronously
this.isready_ = false;
// grab tech-specific options from player options and add source and parent element to use.
var techoptions = (0, _obj.assign)({
source: source,
'nativecontrolsfortouch': this.options_.nativecontrolsfortouch,
'playerid': this.id(),
'techid': this.id() + '_' + techname + '_api',
'videotracks': this.videotracks_,
'texttracks': this.texttracks_,
'audiotracks': this.audiotracks_,
'autoplay': this.options_.autoplay,
'preload': this.options_.preload,
'loop': this.options_.loop,
'muted': this.options_.muted,
'poster': this.poster(),
'language': this.language(),
'playerelingest': this.playerelingest_ || false,
'vtt.js': this.options_['vtt.js']
}, this.options_[techname.tolowercase()]);
if (this.tag) {
techoptions.tag = this.tag;
}
if (source) {
this.currenttype_ = source.type;
if (source.src === this.cache_.src && this.cache_.currenttime > 0) {
techoptions.starttime = this.cache_.currenttime;
}
this.cache_.sources = null;
this.cache_.source = source;
this.cache_.src = source.src;
}
// initialize tech instance
var techcomponent = _tech2['default'].gettech(techname);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!techcomponent) {
techcomponent = _component2['default'].getcomponent(techname);
}
this.tech_ = new techcomponent(techoptions);
// player.triggerready is always async, so don't need this to be async
this.tech_.ready(fn.bind(this, this.handletechready_), true);
_texttracklistconverter2['default'].jsontotexttracks(this.texttracksjson_ || [], this.tech_);
// listen to all html5-defined events and trigger them on the player
tech_events_retrigger.foreach(function (event) {
_this2.on(_this2.tech_, event, _this2['handletech' + (0, _totitlecase2['default'])(event) + '_']);
});
this.on(this.tech_, 'loadstart', this.handletechloadstart_);
this.on(this.tech_, 'waiting', this.handletechwaiting_);
this.on(this.tech_, 'canplay', this.handletechcanplay_);
this.on(this.tech_, 'canplaythrough', this.handletechcanplaythrough_);
this.on(this.tech_, 'playing', this.handletechplaying_);
this.on(this.tech_, 'ended', this.handletechended_);
this.on(this.tech_, 'seeking', this.handletechseeking_);
this.on(this.tech_, 'seeked', this.handletechseeked_);
this.on(this.tech_, 'play', this.handletechplay_);
this.on(this.tech_, 'firstplay', this.handletechfirstplay_);
this.on(this.tech_, 'pause', this.handletechpause_);
this.on(this.tech_, 'durationchange', this.handletechdurationchange_);
this.on(this.tech_, 'fullscreenchange', this.handletechfullscreenchange_);
this.on(this.tech_, 'error', this.handletecherror_);
this.on(this.tech_, 'loadedmetadata', this.updatestyleel_);
this.on(this.tech_, 'posterchange', this.handletechposterchange_);
this.on(this.tech_, 'textdata', this.handletechtextdata_);
this.usingnativecontrols(this.techget_('controls'));
if (this.controls() && !this.usingnativecontrols()) {
this.addtechcontrolslisteners_();
}
// add the tech element in the dom if it was not already there
// make sure to not insert the original video element if using html5
if (this.tech_.el().parentnode !== this.el() && (techname !== 'html5' || !this.tag)) {
dom.insertelfirst(this.tech_.el(), this.el());
}
// get rid of the original video tag reference after the first tech is loaded
if (this.tag) {
this.tag.player = null;
this.tag = null;
}
};
/**
* unload and dispose of the current playback {@link tech}.
*
* @private
*/
player.prototype.unloadtech_ = function unloadtech_() {
// save the current text tracks so that we can reuse the same text tracks with the next tech
this.videotracks_ = this.videotracks();
this.texttracks_ = this.texttracks();
this.audiotracks_ = this.audiotracks();
this.texttracksjson_ = _texttracklistconverter2['default'].texttrackstojson(this.tech_);
this.isready_ = false;
this.tech_.dispose();
this.tech_ = false;
};
/**
* return a reference to the current {@link tech}, but only if given an object with the
* `iwillnotusethisinplugins` property having a true value. this is try and prevent misuse
* of techs by plugins.
*
* @param {object} safety
* an object that must contain `{iwillnotusethisinplugins: true}`
*
* @param {boolean} safety.iwillnotusethisinplugins
* must be set to true or else this function will throw an error.
*
* @return {tech}
* the tech
*/
player.prototype.tech = function tech(safety) {
if (safety && safety.iwillnotusethisinplugins) {
return this.tech_;
}
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 ';
_window2['default'].alert(errortext);
throw new error(errortext);
};
/**
* set up click and touch listeners for the playback element
*
* - on desktops: a click on the video itself will toggle playback
* - on mobile devices: a click on the video toggles controls
* which is done by toggling the user state between active and
* inactive
* - a tap can signal that a user has become active or has become inactive
* e.g. a quick tap on an iphone movie should reveal the controls. another
* quick tap should hide them again (signaling the user is in an inactive
* viewing state)
* - in addition to this, we still want the user to be considered inactive after
* a few seconds of inactivity.
*
* > note: the only part of ios interaction we can't mimic with this setup
* is a touch and hold on the video element counting as activity in order to
* keep the controls showing, but that shouldn't be an issue. a touch and hold
* on any controls will still keep the user active
*
* @private
*/
player.prototype.addtechcontrolslisteners_ = function addtechcontrolslisteners_() {
// make sure to remove all the previous listeners in case we are called multiple times.
this.removetechcontrolslisteners_();
// some browsers (chrome & ie) don't trigger a click on a flash swf, but do
// trigger mousedown/up.
// http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object
// any touch events are set to block the mousedown event from happening
this.on(this.tech_, 'mousedown', this.handletechclick_);
// if the controls were hidden we don't want that to change without a tap event
// so we'll check if the controls were already showing before reporting user
// activity
this.on(this.tech_, 'touchstart', this.handletechtouchstart_);
this.on(this.tech_, 'touchmove', this.handletechtouchmove_);
this.on(this.tech_, 'touchend', this.handletechtouchend_);
// the tap listener needs to come after the touchend listener because the tap
// listener cancels out any reporteduseractivity when setting useractive(false)
this.on(this.tech_, 'tap', this.handletechtap_);
};
/**
* remove the listeners used for click and tap controls. this is needed for
* toggling to controls disabled, where a tap/touch should do nothing.
*
* @private
*/
player.prototype.removetechcontrolslisteners_ = function removetechcontrolslisteners_() {
// we don't want to just use `this.off()` because there might be other needed
// listeners added by techs that extend this.
this.off(this.tech_, 'tap', this.handletechtap_);
this.off(this.tech_, 'touchstart', this.handletechtouchstart_);
this.off(this.tech_, 'touchmove', this.handletechtouchmove_);
this.off(this.tech_, 'touchend', this.handletechtouchend_);
this.off(this.tech_, 'mousedown', this.handletechclick_);
};
/**
* player waits for the tech to be ready
*
* @private
*/
player.prototype.handletechready_ = function handletechready_() {
this.triggerready();
// keep the same volume as before
if (this.cache_.volume) {
this.techcall_('setvolume', this.cache_.volume);
}
// look if the tech found a higher resolution poster while loading
this.handletechposterchange_();
// update the duration if available
this.handletechdurationchange_();
// chrome and safari both have issues with autoplay.
// in safari (5.1.1), when we move the video element into the container div, autoplay doesn't work.
// in chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays)
// this fixes both issues. need to wait for api, so it updates displays correctly
if ((this.src() || this.currentsrc()) && this.tag && this.options_.autoplay && this.paused()) {
try {
// chrome fix. fixed in chrome v16.
delete this.tag.poster;
} catch (e) {
(0, _log2['default'])('deleting tag.poster throws in some browsers', e);
}
this.play();
}
};
/**
* retrigger the `loadstart` event that was triggered by the {@link tech}. this
* function will also trigger {@link player#firstplay} if it is the first loadstart
* for a video.
*
* @fires player#loadstart
* @fires player#firstplay
* @listens tech#loadstart
* @private
*/
player.prototype.handletechloadstart_ = function handletechloadstart_() {
// todo: update to use `emptied` event instead. see #1277.
this.removeclass('vjs-ended');
this.removeclass('vjs-seeking');
// reset the error state
this.error(null);
// if it's already playing we want to trigger a firstplay event now.
// the firstplay event relies on both the play and loadstart events
// which can happen in any order for a new source
if (!this.paused()) {
/**
* fired when the user agent begins looking for media data
*
* @event player#loadstart
* @type {eventtarget~event}
*/
this.trigger('loadstart');
this.trigger('firstplay');
} else {
// reset the hasstarted state
this.hasstarted(false);
this.trigger('loadstart');
}
};
/**
* add/remove the vjs-has-started class
*
* @fires player#firstplay
*
* @param {boolean} hasstarted
* - true: adds the class
* - false: remove the class
*
* @return {boolean}
* the boolean value of hasstarted
*/
player.prototype.hasstarted = function hasstarted(_hasstarted) {
if (_hasstarted !== undefined) {
// only update if this is a new value
if (this.hasstarted_ !== _hasstarted) {
this.hasstarted_ = _hasstarted;
if (_hasstarted) {
this.addclass('vjs-has-started');
// trigger the firstplay event if this newly has played
this.trigger('firstplay');
} else {
this.removeclass('vjs-has-started');
}
}
return this;
}
return !!this.hasstarted_;
};
/**
* fired whenever the media begins or resumes playback
*
* @see [spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play}
* @fires player#play
* @listens tech#play
* @private
*/
player.prototype.handletechplay_ = function handletechplay_() {
this.removeclass('vjs-ended');
this.removeclass('vjs-paused');
this.addclass('vjs-playing');
// hide the poster when the user hits play
this.hasstarted(true);
/**
* triggered whenever an {@link tech#play} event happens. indicates that
* playback has started or resumed.
*
* @event player#play
* @type {eventtarget~event}
*/
this.trigger('play');
};
/**
* retrigger the `waiting` event that was triggered by the {@link tech}.
*
* @fires player#waiting
* @listens tech#waiting
* @private
*/
player.prototype.handletechwaiting_ = function handletechwaiting_() {
var _this3 = this;
this.addclass('vjs-waiting');
/**
* a readystate change on the dom element has caused playback to stop.
*
* @event player#waiting
* @type {eventtarget~event}
*/
this.trigger('waiting');
this.one('timeupdate', function () {
return _this3.removeclass('vjs-waiting');
});
};
/**
* retrigger the `canplay` event that was triggered by the {@link tech}.
* > note: this is not consistent between browsers. see #1351
*
* @fires player#canplay
* @listens tech#canplay
* @private
*/
player.prototype.handletechcanplay_ = function handletechcanplay_() {
this.removeclass('vjs-waiting');
/**
* the media has a readystate of have_future_data or greater.
*
* @event player#canplay
* @type {eventtarget~event}
*/
this.trigger('canplay');
};
/**
* retrigger the `canplaythrough` event that was triggered by the {@link tech}.
*
* @fires player#canplaythrough
* @listens tech#canplaythrough
* @private
*/
player.prototype.handletechcanplaythrough_ = function handletechcanplaythrough_() {
this.removeclass('vjs-waiting');
/**
* the media has a readystate of have_enough_data or greater. this means that the
* entire media file can be played without buffering.
*
* @event player#canplaythrough
* @type {eventtarget~event}
*/
this.trigger('canplaythrough');
};
/**
* retrigger the `playing` event that was triggered by the {@link tech}.
*
* @fires player#playing
* @listens tech#playing
* @private
*/
player.prototype.handletechplaying_ = function handletechplaying_() {
this.removeclass('vjs-waiting');
/**
* the media is no longer blocked from playback, and has started playing.
*
* @event player#playing
* @type {eventtarget~event}
*/
this.trigger('playing');
};
/**
* retrigger the `seeking` event that was triggered by the {@link tech}.
*
* @fires player#seeking
* @listens tech#seeking
* @private
*/
player.prototype.handletechseeking_ = function handletechseeking_() {
this.addclass('vjs-seeking');
/**
* fired whenever the player is jumping to a new time
*
* @event player#seeking
* @type {eventtarget~event}
*/
this.trigger('seeking');
};
/**
* retrigger the `seeked` event that was triggered by the {@link tech}.
*
* @fires player#seeked
* @listens tech#seeked
* @private
*/
player.prototype.handletechseeked_ = function handletechseeked_() {
this.removeclass('vjs-seeking');
/**
* fired when the player has finished jumping to a new time
*
* @event player#seeked
* @type {eventtarget~event}
*/
this.trigger('seeked');
};
/**
* retrigger the `firstplay` event that was triggered by the {@link tech}.
*
* @fires player#firstplay
* @listens tech#firstplay
* @deprecated as of 6.0 passing the `starttime` option to the player will be deprecated
* @private
*/
player.prototype.handletechfirstplay_ = function handletechfirstplay_() {
// if the first starttime attribute is specified
// then we will start at the given offset in seconds
if (this.options_.starttime) {
_log2['default'].warn('passing the `starttime` option to the player will be deprecated in 6.0');
this.currenttime(this.options_.starttime);
}
this.addclass('vjs-has-started');
/**
* fired the first time a video is played. not part of the hls spec, and this is
* probably not the best implementation yet, so use sparingly. if you don't have a
* reason to prevent playback, use `myplayer.one('play');` instead.
*
* @event player#firstplay
* @type {eventtarget~event}
*/
this.trigger('firstplay');
};
/**
* retrigger the `pause` event that was triggered by the {@link tech}.
*
* @fires player#pause
* @listens tech#pause
* @private
*/
player.prototype.handletechpause_ = function handletechpause_() {
this.removeclass('vjs-playing');
this.addclass('vjs-paused');
/**
* fired whenever the media has been paused
*
* @event player#pause
* @type {eventtarget~event}
*/
this.trigger('pause');
};
/**
* retrigger the `ended` event that was triggered by the {@link tech}.
*
* @fires player#ended
* @listens tech#ended
* @private
*/
player.prototype.handletechended_ = function handletechended_() {
this.addclass('vjs-ended');
if (this.options_.loop) {
this.currenttime(0);
this.play();
} else if (!this.paused()) {
this.pause();
}
/**
* fired when the end of the media resource is reached (currenttime == duration)
*
* @event player#ended
* @type {eventtarget~event}
*/
this.trigger('ended');
};
/**
* fired when the duration of the media resource is first known or changed
*
* @listens tech#durationchange
* @private
*/
player.prototype.handletechdurationchange_ = function handletechdurationchange_() {
this.duration(this.techget_('duration'));
};
/**
* handle a click on the media element to play/pause
*
* @param {eventtarget~event} event
* the event that caused this function to trigger
*
* @listens tech#mousedown
* @private
*/
player.prototype.handletechclick_ = function handletechclick_(event) {
// we're using mousedown to detect clicks thanks to flash, but mousedown
// will also be triggered with right-clicks, so we need to prevent that
if (event.button !== 0) {
return;
}
// when controls are disabled a click should not toggle playback because
// the click is considered a control
if (this.controls()) {
if (this.paused()) {
this.play();
} else {
this.pause();
}
}
};
/**
* handle a tap on the media element. it will toggle the user
* activity state, which hides and shows the controls.
*
* @listens tech#tap
* @private
*/
player.prototype.handletechtap_ = function handletechtap_() {
this.useractive(!this.useractive());
};
/**
* handle touch to start
*
* @listens tech#touchstart
* @private
*/
player.prototype.handletechtouchstart_ = function handletechtouchstart_() {
this.userwasactive = this.useractive();
};
/**
* handle touch to move
*
* @listens tech#touchmove
* @private
*/
player.prototype.handletechtouchmove_ = function handletechtouchmove_() {
if (this.userwasactive) {
this.reportuseractivity();
}
};
/**
* handle touch to end
*
* @param {eventtarget~event} event
* the touchend event that triggered
* this function
*
* @listens tech#touchend
* @private
*/
player.prototype.handletechtouchend_ = function handletechtouchend_(event) {
// stop the mouse events from also happening
event.preventdefault();
};
/**
* fired when the player switches in or out of fullscreen mode
*
* @private
* @listens player#fullscreenchange
*/
player.prototype.handlefullscreenchange_ = function handlefullscreenchange_() {
if (this.isfullscreen()) {
this.addclass('vjs-fullscreen');
} else {
this.removeclass('vjs-fullscreen');
}
};
/**
* native click events on the swf aren't triggered on ie11, win8.1rt
* use stageclick events triggered from inside the swf instead
*
* @private
* @listens stageclick
*/
player.prototype.handlestageclick_ = function handlestageclick_() {
this.reportuseractivity();
};
/**
* handle tech fullscreen change
*
* @param {eventtarget~event} event
* the fullscreenchange event that triggered this function
*
* @param {object} data
* the data that was sent with the event
*
* @private
* @listens tech#fullscreenchange
* @fires player#fullscreenchange
*/
player.prototype.handletechfullscreenchange_ = function handletechfullscreenchange_(event, data) {
if (data) {
this.isfullscreen(data.isfullscreen);
}
/**
* fired when going in and out of fullscreen.
*
* @event player#fullscreenchange
* @type {eventtarget~event}
*/
this.trigger('fullscreenchange');
};
/**
* fires when an error occurred during the loading of an audio/video.
*
* @private
* @listens tech#error
*/
player.prototype.handletecherror_ = function handletecherror_() {
var error = this.tech_.error();
this.error(error);
};
/**
* retrigger the `textdata` event that was triggered by the {@link tech}.
*
* @fires player#textdata
* @listens tech#textdata
* @private
*/
player.prototype.handletechtextdata_ = function handletechtextdata_() {
var data = null;
if (arguments.length > 1) {
data = arguments[1];
}
/**
* fires when we get a textdata event from tech
*
* @event player#textdata
* @type {eventtarget~event}
*/
this.trigger('textdata', data);
};
/**
* get object for cached values.
*
* @return {object}
* get the current object cache
*/
player.prototype.getcache = function getcache() {
return this.cache_;
};
/**
* pass values to the playback tech
*
* @param {string} [method]
* the method to call
*
* @param {object} arg
* the argument to pass
*
* @private
*/
player.prototype.techcall_ = function techcall_(method, arg) {
// if it's not ready yet, call method when it is
if (this.tech_ && !this.tech_.isready_) {
this.tech_.ready(function () {
this[method](arg);
}, true);
// otherwise call method now
} else {
try {
if (this.tech_) {
this.tech_[method](arg);
}
} catch (e) {
(0, _log2['default'])(e);
throw e;
}
}
};
/**
* get calls can't wait for the tech, and sometimes don't need to.
*
* @param {string} method
* tech method
*
* @return {function|undefined}
* the method or undefined
*
* @private
*/
player.prototype.techget_ = function techget_(method) {
if (this.tech_ && this.tech_.isready_) {
// flash likes to die and reload when you hide or reposition it.
// in these cases the object methods go away and we get errors.
// when that happens we'll catch the errors and inform tech that it's not ready any more.
try {
return this.tech_[method]();
} catch (e) {
// when building additional tech libs, an expected method may not be defined yet
if (this.tech_[method] === undefined) {
(0, _log2['default'])('video.js: ' + method + ' method not defined for ' + this.techname_ + ' playback technology.', e);
// when a method isn't available on the object it throws a typeerror
} else if (e.name === 'typeerror') {
(0, _log2['default'])('video.js: ' + method + ' unavailable on ' + this.techname_ + ' playback technology element.', e);
this.tech_.isready_ = false;
} else {
(0, _log2['default'])(e);
}
throw e;
}
}
return;
};
/**
* start media playback
*
* @return {player}
* a reference to the player object this function was called on
*/
player.prototype.play = function play() {
// only calls the tech's play if we already have a src loaded
if (this.src() || this.currentsrc()) {
this.techcall_('play');
} else {
this.tech_.one('loadstart', function () {
this.play();
});
}
return this;
};
/**
* pause the video playback
*
* @return {player}
* a reference to the player object this function was called on
*/
player.prototype.pause = function pause() {
this.techcall_('pause');
return this;
};
/**
* check if the player is paused or has yet to play
*
* @return {boolean}
* - false: if the media is currently playing
* - true: if media is not currently playing
*/
player.prototype.paused = function paused() {
// the initial state of paused should be true (in safari it's actually false)
return this.techget_('paused') === false ? false : true;
};
/**
* returns whether or not the user is "scrubbing". scrubbing is
* when the user has clicked the progress bar handle and is
* dragging it along the progress bar.
*
* @param {boolean} [isscrubbing]
* wether the user is or is not scrubbing
*
* @return {boolean|player}
* a instance of the player that called this function when setting,
* and the value of scrubbing when getting
*/
player.prototype.scrubbing = function scrubbing(isscrubbing) {
if (isscrubbing !== undefined) {
this.scrubbing_ = !!isscrubbing;
if (isscrubbing) {
this.addclass('vjs-scrubbing');
} else {
this.removeclass('vjs-scrubbing');
}
return this;
}
return this.scrubbing_;
};
/**
* get or set the current time (in seconds)
*
* @param {number|string} [seconds]
* the time to seek to in seconds
*
* @return {player|number}
* - the current time in seconds when getting
* - a reference to the current player object when setting
*/
player.prototype.currenttime = function currenttime(seconds) {
if (seconds !== undefined) {
this.techcall_('setcurrenttime', seconds);
return this;
}
// cache last currenttime and return. default to 0 seconds
//
// caching the currenttime is meant to prevent a massive amount of reads on the tech's
// currenttime when scrubbing, but may not provide much performance benefit afterall.
// should be tested. also something has to read the actual current time or the cache will
// never get updated.
this.cache_.currenttime = this.techget_('currenttime') || 0;
return this.cache_.currenttime;
};
/**
* normally gets the length in time of the video in seconds;
* in all but the rarest use cases an argument will not be passed to the method
*
* > **note**: the video must have started loading before the duration can be
* known, and in the case of flash, may not be known until the video starts
* playing.
*
* @fires player#durationchange
*
* @param {number} [seconds]
* the duration of the video to set in seconds
*
* @return {number|player}
* - the duration of the video in seconds when getting
* - a reference to the player that called this function
* when setting
*/
player.prototype.duration = function duration(seconds) {
if (seconds === undefined) {
return this.cache_.duration || 0;
}
seconds = parsefloat(seconds) || 0;
// standardize on inifity for signaling video is live
if (seconds < 0) {
seconds = infinity;
}
if (seconds !== this.cache_.duration) {
// cache the last set value for optimized scrubbing (esp. flash)
this.cache_.duration = seconds;
if (seconds === infinity) {
this.addclass('vjs-live');
} else {
this.removeclass('vjs-live');
}
/**
* @event player#durationchange
* @type {eventtarget~event}
*/
this.trigger('durationchange');
}
return this;
};
/**
* calculates how much time is left in the video. not part
* of the native video api.
*
* @return {number}
* the time remaining in seconds
*/
player.prototype.remainingtime = function remainingtime() {
return this.duration() - this.currenttime();
};
//
// kind of like an array of portions of the video that have been downloaded.
/**
* get a timerange object with an array of the times of the video
* that have been downloaded. if you just want the percent of the
* video that's been downloaded, use bufferedpercent.
*
* @see [buffered spec]{@link http://dev.w3.org/html5/spec/video.html#dom-media-buffered}
*
* @return {timerange}
* a mock timerange object (following html spec)
*/
player.prototype.buffered = function buffered() {
var buffered = this.techget_('buffered');
if (!buffered || !buffered.length) {
buffered = (0, _timeranges.createtimerange)(0, 0);
}
return buffered;
};
/**
* get the percent (as a decimal) of the video that's been downloaded.
* this method is not a part of the native html video api.
*
* @return {number}
* a decimal between 0 and 1 representing the percent
* that is bufferred 0 being 0% and 1 being 100%
*/
player.prototype.bufferedpercent = function bufferedpercent() {
return (0, _buffer.bufferedpercent)(this.buffered(), this.duration());
};
/**
* get the ending time of the last buffered time range
* this is used in the progress bar to encapsulate all time ranges.
*
* @return {number}
* the end of the last buffered time range
*/
player.prototype.bufferedend = function bufferedend() {
var buffered = this.buffered();
var duration = this.duration();
var end = buffered.end(buffered.length - 1);
if (end > duration) {
end = duration;
}
return end;
};
/**
* get or set the current volume of the media
*
* @param {number} [percentasdecimal]
* the new volume as a decimal percent:
* - 0 is muted/0%/off
* - 1.0 is 100%/full
* - 0.5 is half volume or 50%
*
* @return {player|number}
* a reference to the calling player when setting and the
* current volume as a percent when getting
*/
player.prototype.volume = function volume(percentasdecimal) {
var vol = void 0;
if (percentasdecimal !== undefined) {
// force value to between 0 and 1
vol = math.max(0, math.min(1, parsefloat(percentasdecimal)));
this.cache_.volume = vol;
this.techcall_('setvolume', vol);
return this;
}
// default to 1 when returning current volume.
vol = parsefloat(this.techget_('volume'));
return isnan(vol) ? 1 : vol;
};
/**
* get the current muted state, or turn mute on or off
*
* @param {boolean} [muted]
* - true to mute
* - false to unmute
*
* @return {boolean|player}
* - true if mute is on and getting
* - false if mute is off and getting
* - a reference to the current player when setting
*/
player.prototype.muted = function muted(_muted) {
if (_muted !== undefined) {
this.techcall_('setmuted', _muted);
return this;
}
return this.techget_('muted') || false;
};
/**
* check if current tech can support native fullscreen
* (e.g. with built in controls like ios, so not our flash swf)
*
* @return {boolean}
* if native fullscreen is supported
*/
player.prototype.supportsfullscreen = function supportsfullscreen() {
return this.techget_('supportsfullscreen') || false;
};
/**
* check if the player is in fullscreen mode or tell the player that it
* is or is not in fullscreen mode.
*
* > note: as of the latest html5 spec, isfullscreen is no longer an official
* property and instead document.fullscreenelement is used. but isfullscreen is
* still a valuable property for internal player workings.
*
* @param {boolean} [isfs]
* set the players current fullscreen state
*
* @return {boolean|player}
* - true if fullscreen is on and getting
* - false if fullscreen is off and getting
* - a reference to the current player when setting
*/
player.prototype.isfullscreen = function isfullscreen(isfs) {
if (isfs !== undefined) {
this.isfullscreen_ = !!isfs;
return this;
}
return !!this.isfullscreen_;
};
/**
* increase the size of the video to full screen
* in some browsers, full screen is not supported natively, so it enters
* "full window mode", where the video fills the browser window.
* in browsers and devices that support native full screen, sometimes the
* browser's default controls will be shown, and not the video.js custom skin.
* this includes most mobile devices (ios, android) and older versions of
* safari.
*
* @fires player#fullscreenchange
* @return {player}
* a reference to the current player
*/
player.prototype.requestfullscreen = function requestfullscreen() {
var fsapi = _fullscreenapi2['default'];
this.isfullscreen(true);
if (fsapi.requestfullscreen) {
// the browser supports going fullscreen at the element level so we can
// take the controls fullscreen as well as the video
// trigger fullscreenchange event after change
// we have to specifically add this each time, and remove
// when canceling fullscreen. otherwise if there's multiple
// players on a page, they would all be reacting to the same fullscreen
// events
events.on(_document2['default'], fsapi.fullscreenchange, fn.bind(this, function documentfullscreenchange(e) {
this.isfullscreen(_document2['default'][fsapi.fullscreenelement]);
// if cancelling fullscreen, remove event listener.
if (this.isfullscreen() === false) {
events.off(_document2['default'], fsapi.fullscreenchange, documentfullscreenchange);
}
/**
* @event player#fullscreenchange
* @type {eventtarget~event}
*/
this.trigger('fullscreenchange');
}));
this.el_[fsapi.requestfullscreen]();
} else if (this.tech_.supportsfullscreen()) {
// we can't take the video.js controls fullscreen but we can go fullscreen
// with native controls
this.techcall_('enterfullscreen');
} else {
// fullscreen isn't supported so we'll just stretch the video element to
// fill the viewport
this.enterfullwindow();
/**
* @event player#fullscreenchange
* @type {eventtarget~event}
*/
this.trigger('fullscreenchange');
}
return this;
};
/**
* return the video to its normal size after having been in full screen mode
*
* @fires player#fullscreenchange
*
* @return {player}
* a reference to the current player
*/
player.prototype.exitfullscreen = function exitfullscreen() {
var fsapi = _fullscreenapi2['default'];
this.isfullscreen(false);
// check for browser element fullscreen support
if (fsapi.requestfullscreen) {
_document2['default'][fsapi.exitfullscreen]();
} else if (this.tech_.supportsfullscreen()) {
this.techcall_('exitfullscreen');
} else {
this.exitfullwindow();
/**
* @event player#fullscreenchange
* @type {eventtarget~event}
*/
this.trigger('fullscreenchange');
}
return this;
};
/**
* when fullscreen isn't supported we can stretch the
* video container to as wide as the browser will let us.
*
* @fires player#enterfullwindow
*/
player.prototype.enterfullwindow = function enterfullwindow() {
this.isfullwindow = true;
// storing original doc overflow value to return to when fullscreen is off
this.docorigoverflow = _document2['default'].documentelement.style.overflow;
// add listener for esc key to exit fullscreen
events.on(_document2['default'], 'keydown', fn.bind(this, this.fullwindowonesckey));
// hide any scroll bars
_document2['default'].documentelement.style.overflow = 'hidden';
// apply fullscreen styles
dom.addelclass(_document2['default'].body, 'vjs-full-window');
/**
* @event player#enterfullwindow
* @type {eventtarget~event}
*/
this.trigger('enterfullwindow');
};
/**
* check for call to either exit full window or
* full screen on esc key
*
* @param {string} event
* event to check for key press
*/
player.prototype.fullwindowonesckey = function fullwindowonesckey(event) {
if (event.keycode === 27) {
if (this.isfullscreen() === true) {
this.exitfullscreen();
} else {
this.exitfullwindow();
}
}
};
/**
* exit full window
*
* @fires player#exitfullwindow
*/
player.prototype.exitfullwindow = function exitfullwindow() {
this.isfullwindow = false;
events.off(_document2['default'], 'keydown', this.fullwindowonesckey);
// unhide scroll bars.
_document2['default'].documentelement.style.overflow = this.docorigoverflow;
// remove fullscreen styles
dom.removeelclass(_document2['default'].body, 'vjs-full-window');
// resize the box, controller, and poster to original sizes
// this.positionall();
/**
* @event player#exitfullwindow
* @type {eventtarget~event}
*/
this.trigger('exitfullwindow');
};
/**
* check whether the player can play a given mimetype
*
* @see https://www.w3.org/tr/2011/wd-html5-20110113/video.html#dom-navigator-canplaytype
*
* @param {string} type
* the mimetype to check
*
* @return {string}
* 'probably', 'maybe', or '' (empty string)
*/
player.prototype.canplaytype = function canplaytype(type) {
var can = void 0;
// loop through each playback technology in the options order
for (var i = 0, j = this.options_.techorder; i < j.length; i++) {
var techname = (0, _totitlecase2['default'])(j[i]);
var tech = _tech2['default'].gettech(techname);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!tech) {
tech = _component2['default'].getcomponent(techname);
}
// check if the current tech is defined before continuing
if (!tech) {
_log2['default'].error('the "' + techname + '" tech is undefined. skipped browser support check for that tech.');
continue;
}
// check if the browser supports this technology
if (tech.issupported()) {
can = tech.canplaytype(type);
if (can) {
return can;
}
}
}
return '';
};
/**
* select source based on tech-order or source-order
* uses source-order selection if `options.sourceorder` is truthy. otherwise,
* defaults to tech-order selection
*
* @param {array} sources
* the sources for a media asset
*
* @return {object|boolean}
* object of source and tech order or false
*/
player.prototype.selectsource = function selectsource(sources) {
var _this4 = this;
// get only the techs specified in `techorder` that exist and are supported by the
// current platform
var techs = this.options_.techorder.map(_totitlecase2['default']).map(function (techname) {
// `component.getcomponent(...)` is for support of old behavior of techs
// being registered as components.
// remove once that deprecated behavior is removed.
return [techname, _tech2['default'].gettech(techname) || _component2['default'].getcomponent(techname)];
}).filter(function (_ref) {
var techname = _ref[0],
tech = _ref[1];
// check if the current tech is defined before continuing
if (tech) {
// check if the browser supports this technology
return tech.issupported();
}
_log2['default'].error('the "' + techname + '" tech is undefined. skipped browser support check for that tech.');
return false;
});
// iterate over each `innerarray` element once per `outerarray` element and execute
// `tester` with both. if `tester` returns a non-falsy value, exit early and return
// that value.
var findfirstpassingtechsourcepair = function findfirstpassingtechsourcepair(outerarray, innerarray, tester) {
var found = void 0;
outerarray.some(function (outerchoice) {
return innerarray.some(function (innerchoice) {
found = tester(outerchoice, innerchoice);
if (found) {
return true;
}
});
});
return found;
};
var foundsourceandtech = void 0;
var flip = function flip(fn) {
return function (a, b) {
return fn(b, a);
};
};
var finder = function finder(_ref2, source) {
var techname = _ref2[0],
tech = _ref2[1];
if (tech.canplaysource(source, _this4.options_[techname.tolowercase()])) {
return { source: source, tech: techname };
}
};
// depending on the truthiness of `options.sourceorder`, we swap the order of techs and sources
// to select from them based on their priority.
if (this.options_.sourceorder) {
// source-first ordering
foundsourceandtech = findfirstpassingtechsourcepair(sources, techs, flip(finder));
} else {
// tech-first ordering
foundsourceandtech = findfirstpassingtechsourcepair(techs, sources, finder);
}
return foundsourceandtech || false;
};
/**
* the source function updates the video source
* there are three types of variables you can pass as the argument.
* **url string**: a url to the the video file. use this method if you are sure
* the current playback technology (html5/flash) can support the source you
* provide. currently only mp4 files can be used in both html5 and flash.
*
* @param {tech~sourceobject|tech~sourceobject[]} [source]
* one sourceobject or an array of sourceobjects
*
* @return {string|player}
* - the current video source when getting
* - the player when setting
*/
player.prototype.src = function src(source) {
if (source === undefined) {
return this.techget_('src');
}
var currenttech = _tech2['default'].gettech(this.techname_);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!currenttech) {
currenttech = _component2['default'].getcomponent(this.techname_);
}
// case: array of source objects to choose from and pick the best to play
if (array.isarray(source)) {
this.sourcelist_(source);
// case: url string (http://myvideo...)
} else if (typeof source === 'string') {
// create a source object from the string
this.src({ src: source });
// case: source object { src: '', type: '' ... }
} else if (source instanceof object) {
// check if the source has a type and the loaded tech cannot play the source
// if there's no type we'll just try the current tech
if (source.type && !currenttech.canplaysource(source, this.options_[this.techname_.tolowercase()])) {
// create a source list with the current source and send through
// the tech loop to check for a compatible technology
this.sourcelist_([source]);
} else {
this.cache_.sources = null;
this.cache_.source = source;
this.cache_.src = source.src;
this.currenttype_ = source.type || '';
// wait until the tech is ready to set the source
this.ready(function () {
// the setsource tech method was added with source handlers
// so older techs won't support it
// we need to check the direct prototype for the case where subclasses
// of the tech do not support source handlers
if (currenttech.prototype.hasownproperty('setsource')) {
this.techcall_('setsource', source);
} else {
this.techcall_('src', source.src);
}
if (this.options_.preload === 'auto') {
this.load();
}
if (this.options_.autoplay) {
this.play();
}
// set the source synchronously if possible (#2326)
}, true);
}
}
return this;
};
/**
* handle an array of source objects
*
* @param {tech~sourceobject[]} sources
* array of source objects
*
* @private
*/
player.prototype.sourcelist_ = function sourcelist_(sources) {
var sourcetech = this.selectsource(sources);
if (sourcetech) {
if (sourcetech.tech === this.techname_) {
// if this technology is already loaded, set the source
this.src(sourcetech.source);
} else {
// load this technology with the chosen source
this.loadtech_(sourcetech.tech, sourcetech.source);
}
this.cache_.sources = sources;
} else {
// we need to wrap this in a timeout to give folks a chance to add error event handlers
this.settimeout(function () {
this.error({ code: 4, message: this.localize(this.options_.notsupportedmessage) });
}, 0);
// we could not find an appropriate tech, but let's still notify the delegate that this is it
// this needs a better comment about why this is needed
this.triggerready();
}
};
/**
* begin loading the src data.
*
* @return {player}
* a reference to the player
*/
player.prototype.load = function load() {
this.techcall_('load');
return this;
};
/**
* reset the player. loads the first tech in the techorder,
* and calls `reset` on the tech`.
*
* @return {player}
* a reference to the player
*/
player.prototype.reset = function reset() {
this.loadtech_((0, _totitlecase2['default'])(this.options_.techorder[0]), null);
this.techcall_('reset');
return this;
};
/**
* returns all of the current source objects.
*
* @return {tech~sourceobject[]}
* the current source objects
*/
player.prototype.currentsources = function currentsources() {
var source = this.currentsource();
var sources = [];
// assume `{}` or `{ src }`
if (object.keys(source).length !== 0) {
sources.push(source);
}
return this.cache_.sources || sources;
};
/**
* returns the current source object.
*
* @return {tech~sourceobject}
* the current source object
*/
player.prototype.currentsource = function currentsource() {
var source = {};
var src = this.currentsrc();
if (src) {
source.src = src;
}
return this.cache_.source || source;
};
/**
* returns the fully qualified url of the current source value e.g. http://mysite.com/video.mp4
* can be used in conjuction with `currenttype` to assist in rebuilding the current source object.
*
* @return {string}
* the current source
*/
player.prototype.currentsrc = function currentsrc() {
return this.techget_('currentsrc') || this.cache_.src || '';
};
/**
* get the current source type e.g. video/mp4
* this can allow you rebuild the current source object so that you could load the same
* source and tech later
*
* @return {string}
* the source mime type
*/
player.prototype.currenttype = function currenttype() {
return this.currenttype_ || '';
};
/**
* get or set the preload attribute
*
* @param {boolean} [value]
* - true means that we should preload
* - false maens that we should not preload
*
* @return {string|player}
* - the preload attribute value when getting
* - the player when setting
*/
player.prototype.preload = function preload(value) {
if (value !== undefined) {
this.techcall_('setpreload', value);
this.options_.preload = value;
return this;
}
return this.techget_('preload');
};
/**
* get or set the autoplay attribute.
*
* @param {boolean} [value]
* - true means that we should autoplay
* - false maens that we should not autoplay
*
* @return {string|player}
* - the current value of autoplay
* - the player when setting
*/
player.prototype.autoplay = function autoplay(value) {
if (value !== undefined) {
this.techcall_('setautoplay', value);
this.options_.autoplay = value;
return this;
}
return this.techget_('autoplay', value);
};
/**
* get or set the loop attribute on the video element.
*
* @param {boolean} [value]
* - true means that we should loop the video
* - false means that we should not loop the video
*
* @return {string|player}
* - the current value of loop when getting
* - the player when setting
*/
player.prototype.loop = function loop(value) {
if (value !== undefined) {
this.techcall_('setloop', value);
this.options_.loop = value;
return this;
}
return this.techget_('loop');
};
/**
* get or set the poster image source url
*
* @fires player#posterchange
*
* @param {string} [src]
* poster image source url
*
* @return {string|player}
* - the current value of poster when getting
* - the player when setting
*/
player.prototype.poster = function poster(src) {
if (src === undefined) {
return this.poster_;
}
// the correct way to remove a poster is to set as an empty string
// other falsey values will throw errors
if (!src) {
src = '';
}
// update the internal poster variable
this.poster_ = src;
// update the tech's poster
this.techcall_('setposter', src);
// alert components that the poster has been set
/**
* this event fires when the poster image is changed on the player.
*
* @event player#posterchange
* @type {eventtarget~event}
*/
this.trigger('posterchange');
return this;
};
/**
* some techs (e.g. youtube) can provide a poster source in an
* asynchronous way. we want the poster component to use this
* poster source so that it covers up the tech's controls.
* (youtube's play button). however we only want to use this
* soruce if the player user hasn't set a poster through
* the normal apis.
*
* @fires player#posterchange
* @listens tech#posterchange
* @private
*/
player.prototype.handletechposterchange_ = function handletechposterchange_() {
if (!this.poster_ && this.tech_ && this.tech_.poster) {
this.poster_ = this.tech_.poster() || '';
// let components know the poster has changed
this.trigger('posterchange');
}
};
/**
* get or set whether or not the controls are showing.
*
* @fires player#controlsenabled
*
* @param {boolean} [bool]
* - true to turn controls on
* - false to turn controls off
*
* @return {boolean|player}
* - the current value of controls when getting
* - the player when setting
*/
player.prototype.controls = function controls(bool) {
if (bool !== undefined) {
bool = !!bool;
// don't trigger a change event unless it actually changed
if (this.controls_ !== bool) {
this.controls_ = bool;
if (this.usingnativecontrols()) {
this.techcall_('setcontrols', bool);
}
if (bool) {
this.removeclass('vjs-controls-disabled');
this.addclass('vjs-controls-enabled');
/**
* @event player#controlsenabled
* @type {eventtarget~event}
*/
this.trigger('controlsenabled');
if (!this.usingnativecontrols()) {
this.addtechcontrolslisteners_();
}
} else {
this.removeclass('vjs-controls-enabled');
this.addclass('vjs-controls-disabled');
/**
* @event player#controlsdisabled
* @type {eventtarget~event}
*/
this.trigger('controlsdisabled');
if (!this.usingnativecontrols()) {
this.removetechcontrolslisteners_();
}
}
}
return this;
}
return !!this.controls_;
};
/**
* toggle native controls on/off. native controls are the controls built into
* devices (e.g. default iphone controls), flash, or other techs
* (e.g. vimeo controls)
* **this should only be set by the current tech, because only the tech knows
* if it can support native controls**
*
* @fires player#usingnativecontrols
* @fires player#usingcustomcontrols
*
* @param {boolean} [bool]
* - true to turn native controls on
* - false to turn native controls off
*
* @return {boolean|player}
* - the current value of native controls when getting
* - the player when setting
*/
player.prototype.usingnativecontrols = function usingnativecontrols(bool) {
if (bool !== undefined) {
bool = !!bool;
// don't trigger a change event unless it actually changed
if (this.usingnativecontrols_ !== bool) {
this.usingnativecontrols_ = bool;
if (bool) {
this.addclass('vjs-using-native-controls');
/**
* player is using the native device controls
*
* @event player#usingnativecontrols
* @type {eventtarget~event}
*/
this.trigger('usingnativecontrols');
} else {
this.removeclass('vjs-using-native-controls');
/**
* player is using the custom html controls
*
* @event player#usingcustomcontrols
* @type {eventtarget~event}
*/
this.trigger('usingcustomcontrols');
}
}
return this;
}
return !!this.usingnativecontrols_;
};
/**
* set or get the current mediaerror
*
* @fires player#error
*
* @param {mediaerror|string|number} [err]
* a mediaerror or a string/number to be turned
* into a mediaerror
*
* @return {mediaerror|null|player}
* - the current mediaerror when getting (or null)
* - the player when setting
*/
player.prototype.error = function error(err) {
if (err === undefined) {
return this.error_ || null;
}
// restoring to default
if (err === null) {
this.error_ = err;
this.removeclass('vjs-error');
if (this.errordisplay) {
this.errordisplay.close();
}
return this;
}
this.error_ = new _mediaerror2['default'](err);
// add the vjs-error classname to the player
this.addclass('vjs-error');
// log the name of the error type and any message
// ie8 just logs "[object object]" if you just log the error object
_log2['default'].error('(code:' + this.error_.code + ' ' + _mediaerror2['default'].errortypes[this.error_.code] + ')', this.error_.message, this.error_);
/**
* @event player#error
* @type {eventtarget~event}
*/
this.trigger('error');
return this;
};
/**
* report user activity
*
* @param {object} event
* event object
*/
player.prototype.reportuseractivity = function reportuseractivity(event) {
this.useractivity_ = true;
};
/**
* get/set if user is active
*
* @fires player#useractive
* @fires player#userinactive
*
* @param {boolean} [bool]
* - true if the user is active
* - false if the user is inactive
* @return {boolean|player}
* - the current value of useractive when getting
* - the player when setting
*/
player.prototype.useractive = function useractive(bool) {
if (bool !== undefined) {
bool = !!bool;
if (bool !== this.useractive_) {
this.useractive_ = bool;
if (bool) {
// if the user was inactive and is now active we want to reset the
// inactivity timer
this.useractivity_ = true;
this.removeclass('vjs-user-inactive');
this.addclass('vjs-user-active');
/**
* @event player#useractive
* @type {eventtarget~event}
*/
this.trigger('useractive');
} else {
// we're switching the state to inactive manually, so erase any other
// activity
this.useractivity_ = false;
// chrome/safari/ie have bugs where when you change the cursor it can
// trigger a mousemove event. this causes an issue when you're hiding
// the cursor when the user is inactive, and a mousemove signals user
// activity. making it impossible to go into inactive mode. specifically
// this happens in fullscreen when we really need to hide the cursor.
//
// when this gets resolved in all browsers it can be removed
// https://code.google.com/p/chromium/issues/detail?id=103041
if (this.tech_) {
this.tech_.one('mousemove', function (e) {
e.stoppropagation();
e.preventdefault();
});
}
this.removeclass('vjs-user-active');
this.addclass('vjs-user-inactive');
/**
* @event player#userinactive
* @type {eventtarget~event}
*/
this.trigger('userinactive');
}
}
return this;
}
return this.useractive_;
};
/**
* listen for user activity based on timeout value
*
* @private
*/
player.prototype.listenforuseractivity_ = function listenforuseractivity_() {
var mouseinprogress = void 0;
var lastmovex = void 0;
var lastmovey = void 0;
var handleactivity = fn.bind(this, this.reportuseractivity);
var handlemousemove = function handlemousemove(e) {
// #1068 - prevent mousemove spamming
// chrome bug: https://code.google.com/p/chromium/issues/detail?id=366970
if (e.screenx !== lastmovex || e.screeny !== lastmovey) {
lastmovex = e.screenx;
lastmovey = e.screeny;
handleactivity();
}
};
var handlemousedown = function handlemousedown() {
handleactivity();
// for as long as the they are touching the device or have their mouse down,
// we consider them active even if they're not moving their finger or mouse.
// so we want to continue to update that they are active
this.clearinterval(mouseinprogress);
// setting useractivity=true now and setting the interval to the same time
// as the activitycheck interval (250) should ensure we never miss the
// next activitycheck
mouseinprogress = this.setinterval(handleactivity, 250);
};
var handlemouseup = function handlemouseup(event) {
handleactivity();
// stop the interval that maintains activity if the mouse/touch is down
this.clearinterval(mouseinprogress);
};
// any mouse movement will be considered user activity
this.on('mousedown', handlemousedown);
this.on('mousemove', handlemousemove);
this.on('mouseup', handlemouseup);
// listen for keyboard navigation
// shouldn't need to use inprogress interval because of key repeat
this.on('keydown', handleactivity);
this.on('keyup', handleactivity);
// run an interval every 250 milliseconds instead of stuffing everything into
// the mousemove/touchmove function itself, to prevent performance degradation.
// `this.reportuseractivity` simply sets this.useractivity_ to true, which
// then gets picked up by this loop
// http://ejohn.org/blog/learning-from-twitter/
var inactivitytimeout = void 0;
this.setinterval(function () {
// check to see if mouse/touch activity has happened
if (this.useractivity_) {
// reset the activity tracker
this.useractivity_ = false;
// if the user state was inactive, set the state to active
this.useractive(true);
// clear any existing inactivity timeout to start the timer over
this.cleartimeout(inactivitytimeout);
var timeout = this.options_.inactivitytimeout;
if (timeout > 0) {
// in milliseconds, if no more activity has occurred the
// user will be considered inactive
inactivitytimeout = this.settimeout(function () {
// protect against the case where the inactivitytimeout can trigger just
// before the next user activity is picked up by the activity check loop
// causing a flicker
if (!this.useractivity_) {
this.useractive(false);
}
}, timeout);
}
}
}, 250);
};
/**
* gets or sets the current playback rate. a playback rate of
* 1.0 represents normal speed and 0.5 would indicate half-speed
* playback, for instance.
*
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-playbackrate
*
* @param {number} [rate]
* new playback rate to set.
*
* @return {number|player}
* - the current playback rate when getting or 1.0
* - the player when setting
*/
player.prototype.playbackrate = function playbackrate(rate) {
if (rate !== undefined) {
this.techcall_('setplaybackrate', rate);
return this;
}
if (this.tech_ && this.tech_.featuresplaybackrate) {
return this.techget_('playbackrate');
}
return 1.0;
};
/**
* gets or sets the audio flag
*
* @param {boolean} bool
* - true signals that this is an audio player
* - false signals that this is not an audio player
*
* @return {player|boolean}
* - the current value of isaudio when getting
* - the player if setting
*/
player.prototype.isaudio = function isaudio(bool) {
if (bool !== undefined) {
this.isaudio_ = !!bool;
return this;
}
return !!this.isaudio_;
};
/**
* get the {@link videotracklist}
*
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#videotracklist
*
* @return {videotracklist}
* the current video track list
*/
player.prototype.videotracks = function videotracks() {
// if we have not yet loadtech_, we create videotracks_
// these will be passed to the tech during loading
if (!this.tech_) {
this.videotracks_ = this.videotracks_ || new _videotracklist2['default']();
return this.videotracks_;
}
return this.tech_.videotracks();
};
/**
* get the {@link audiotracklist}
*
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist
*
* @return {audiotracklist}
* the current audio track list
*/
player.prototype.audiotracks = function audiotracks() {
// if we have not yet loadtech_, we create videotracks_
// these will be passed to the tech during loading
if (!this.tech_) {
this.audiotracks_ = this.audiotracks_ || new _audiotracklist2['default']();
return this.audiotracks_;
}
return this.tech_.audiotracks();
};
/**
* get the {@link texttracklist}
*
* text tracks are tracks of timed text events.
* - captions: text displayed over the video
* for the hearing impaired
* - subtitles: text displayed over the video for
* those who don't understand language in the video
* - chapters: text displayed in a menu allowing the user to jump
* to particular points (chapters) in the video
* - descriptions: (not yet implemented) audio descriptions that are read back to
* the user by a screen reading device
*
* @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks
*
* @return {texttracklist|undefined}
* the current texttracklist or undefined if
* or undefined if we don't have a tech
*/
player.prototype.texttracks = function texttracks() {
// cannot use techget_ directly because it checks to see whether the tech is ready.
// flash is unlikely to be ready in time but texttracks should still work.
if (this.tech_) {
return this.tech_.texttracks();
}
};
/**
* get the "remote" {@link texttracklist}. remote text tracks
* are tracks that were added to the html video element and can
* be removed, whereas normal texttracks cannot be removed.
*
*
* @return {texttracklist|undefined}
* the current remote text track list or undefined
* if we don't have a tech
*/
player.prototype.remotetexttracks = function remotetexttracks() {
if (this.tech_) {
return this.tech_.remotetexttracks();
}
};
/**
* get the "remote" {@link htmltrackelementlist}.
* this gives the user all of the dom elements that match up
* with the remote {@link texttracklist}.
*
* @return {htmltrackelementlist}
* the current remote text track list elements
* or undefined if we don't have a tech
*/
player.prototype.remotetexttrackels = function remotetexttrackels() {
if (this.tech_) {
return this.tech_.remotetexttrackels();
}
};
/**
* a helper method for adding a {@link texttrack} to our
* {@link texttracklist}.
*
* in addition to the w3c settings we allow adding additional info through options.
*
* @see http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack
*
* @param {string} [kind]
* the kind of texttrack you are adding
*
* @param {string} [label]
* the label to give the texttrack label
*
* @param {string} [language]
* the language to set on the texttrack
*
* @return {texttrack|undefined}
* the texttrack that was added or undefined
* if there is no tech
*/
player.prototype.addtexttrack = function addtexttrack(kind, label, language) {
if (this.tech_) {
return this.tech_.addtexttrack(kind, label, language);
}
};
/**
* create a remote {@link texttrack} and an {@link htmltrackelement}. it will
* automatically removed from the video element whenever the source changes, unless
* manualcleanup is set to false.
*
* @param {object} options
* options to pass to {@link htmltrackelement} during creation. see
* {@link htmltrackelement} for object properties that you should use.
*
* @param {boolean} [manualcleanup=true] if set to false, the texttrack will be
*
* @return {htmltrackelement}
* the htmltrackelement that was created and added
* to the htmltrackelementlist and the remote
* texttracklist
*
* @deprecated the default value of the "manualcleanup" parameter will default
* to "false" in upcoming versions of video.js
*/
player.prototype.addremotetexttrack = function addremotetexttrack(options, manualcleanup) {
if (this.tech_) {
return this.tech_.addremotetexttrack(options, manualcleanup);
}
};
/**
* remove a remote {@link texttrack} from the respective
* {@link texttracklist} and {@link htmltrackelementlist}.
*
* @param {object} track
* remote {@link texttrack} to remove
*
* @return {undefined}
* does not return anything
*/
player.prototype.removeremotetexttrack = function removeremotetexttrack() {
var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref3$track = _ref3.track,
track = _ref3$track === undefined ? arguments[0] : _ref3$track;
// destructure the input into an object with a track argument, defaulting to arguments[0]
// default the whole argument to an empty object if nothing was passed in
if (this.tech_) {
return this.tech_.removeremotetexttrack(track);
}
};
/**
* get video width
*
* @return {number}
* current video width
*/
player.prototype.videowidth = function videowidth() {
return this.tech_ && this.tech_.videowidth && this.tech_.videowidth() || 0;
};
/**
* get video height
*
* @return {number}
* current video height
*/
player.prototype.videoheight = function videoheight() {
return this.tech_ && this.tech_.videoheight && this.tech_.videoheight() || 0;
};
// methods to add support for
// initialtime: function() { return this.techcall_('initialtime'); },
// startoffsettime: function() { return this.techcall_('startoffsettime'); },
// played: function() { return this.techcall_('played'); },
// defaultplaybackrate: function() { return this.techcall_('defaultplaybackrate'); },
// defaultmuted: function() { return this.techcall_('defaultmuted'); }
/**
* the player's language code
* note: the language should be set in the player options if you want the
* the controls to be built with a specific language. changing the lanugage
* later will not update controls text.
*
* @param {string} [code]
* the language code to set the player to
*
* @return {string|player}
* - the current language code when getting
* - a reference to the player when setting
*/
player.prototype.language = function language(code) {
if (code === undefined) {
return this.language_;
}
this.language_ = string(code).tolowercase();
return this;
};
/**
* get the player's language dictionary
* merge every time, because a newly added plugin might call videojs.addlanguage() at any time
* languages specified directly in the player options have precedence
*
* @return {array}
* an array of of supported languages
*/
player.prototype.languages = function languages() {
return (0, _mergeoptions2['default'])(player.prototype.options_.languages, this.languages_);
};
/**
* returns a javascript object reperesenting the current track
* information. **does not return it as json**
*
* @return {object}
* object representing the current of track info
*/
player.prototype.tojson = function tojson() {
var options = (0, _mergeoptions2['default'])(this.options_);
var tracks = options.tracks;
options.tracks = [];
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
// deep merge tracks and null out player so no circular references
track = (0, _mergeoptions2['default'])(track);
track.player = undefined;
options.tracks[i] = track;
}
return options;
};
/**
* creates a simple modal dialog (an instance of the {@link modaldialog}
* component) that immediately overlays the player with arbitrary
* content and removes itself when closed.
*
* @param {string|function|element|array|null} content
* same as {@link modaldialog#content}'s param of the same name.
* the most straight-forward usage is to provide a string or dom
* element.
*
* @param {object} [options]
* extra options which will be passed on to the {@link modaldialog}.
*
* @return {modaldialog}
* the {@link modaldialog} that was created
*/
player.prototype.createmodal = function createmodal(content, options) {
var _this5 = this;
options = options || {};
options.content = content || '';
var modal = new _modaldialog2['default'](this, options);
this.addchild(modal);
modal.on('dispose', function () {
_this5.removechild(modal);
});
return modal.open();
};
/**
* gets tag settings
*
* @param {element} tag
* the player tag
*
* @return {object}
* an object containing all of the settings
* for a player tag
*/
player.gettagsettings = function gettagsettings(tag) {
var baseoptions = {
sources: [],
tracks: []
};
var tagoptions = dom.getelattributes(tag);
var datasetup = tagoptions['data-setup'];
if (dom.haselclass(tag, 'vjs-fluid')) {
tagoptions.fluid = true;
}
// check if data-setup attr exists.
if (datasetup !== null) {
// parse options json
// if empty string, make it a parsable json object.
var _safeparsetuple = (0, _tuple2['default'])(datasetup || '{}'),
err = _safeparsetuple[0],
data = _safeparsetuple[1];
if (err) {
_log2['default'].error(err);
}
(0, _obj.assign)(tagoptions, data);
}
(0, _obj.assign)(baseoptions, tagoptions);
// get tag children settings
if (tag.haschildnodes()) {
var children = tag.childnodes;
for (var i = 0, j = children.length; i < j; i++) {
var child = children[i];
// change case needed: http://ejohn.org/blog/nodename-case-sensitivity/
var childname = child.nodename.tolowercase();
if (childname === 'source') {
baseoptions.sources.push(dom.getelattributes(child));
} else if (childname === 'track') {
baseoptions.tracks.push(dom.getelattributes(child));
}
}
}
return baseoptions;
};
/**
* determine wether or not flexbox is supported
*
* @return {boolean}
* - true if flexbox is supported
* - false if flexbox is not supported
*/
player.prototype.flexnotsupported_ = function flexnotsupported_() {
var elem = _document2['default'].createelement('i');
// note: we don't actually use flexbasis (or flexorder), but it's one of the more
// common flex features that we can rely on when checking for flex support.
return !('flexbasis' in elem.style || 'webkitflexbasis' in elem.style || 'mozflexbasis' in elem.style || 'msflexbasis' in elem.style ||
// ie10-specific (2012 flex spec)
'msflexorder' in elem.style);
};
return player;
}(_component2['default']);
/**
* global player list
*
* @type {object}
*/
player.players = {};
var navigator = _window2['default'].navigator;
/*
* player instance options, surfaced using options
* options = player.prototype.options_
* make changes in options, not here.
*
* @type {object}
* @private
*/
player.prototype.options_ = {
// default order of fallback technology
techorder: ['html5', 'flash'],
// techorder: ['flash','html5'],
html5: {},
flash: {},
// defaultvolume: 0.85,
defaultvolume: 0.00,
// default inactivity timeout
inactivitytimeout: 2000,
// default playback rates
playbackrates: [],
// add playback rate selection by adding rates
// 'playbackrates': [0.5, 1, 1.5, 2],
// included control sets
children: ['medialoader', 'posterimage', 'texttrackdisplay', 'loadingspinner', 'bigplaybutton', 'controlbar', 'errordisplay', 'texttracksettings'],
language: navigator && (navigator.languages && navigator.languages[0] || navigator.userlanguage || navigator.language) || 'en',
// locales and their language translations
languages: {},
// default message to show when a video cannot be played.
notsupportedmessage: 'no compatible source was found for this media.'
};
[
/**
* returns whether or not the player is in the "ended" state.
*
* @return {boolean} true if the player is in the ended state, false if not.
* @method player#ended
*/
'ended',
/**
* returns whether or not the player is in the "seeking" state.
*
* @return {boolean} true if the player is in the seeking state, false if not.
* @method player#seeking
*/
'seeking',
/**
* returns the timeranges of the media that are currently available
* for seeking to.
*
* @return {timeranges} the seekable intervals of the media timeline
* @method player#seekable
*/
'seekable',
/**
* returns the current state of network activity for the element, from
* the codes in the list below.
* - network_empty (numeric value 0)
* the element has not yet been initialised. all attributes are in
* their initial states.
* - network_idle (numeric value 1)
* the element's resource selection algorithm is active and has
* selected a resource, but it is not actually using the network at
* this time.
* - network_loading (numeric value 2)
* the user agent is actively trying to download data.
* - network_no_source (numeric value 3)
* the element's resource selection algorithm is active, but it has
* not yet found a resource to use.
*
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#network-states
* @return {number} the current network activity state
* @method player#networkstate
*/
'networkstate',
/**
* returns a value that expresses the current state of the element
* with respect to rendering the current playback position, from the
* codes in the list below.
* - have_nothing (numeric value 0)
* no information regarding the media resource is available.
* - have_metadata (numeric value 1)
* enough of the resource has been obtained that the duration of the
* resource is available.
* - have_current_data (numeric value 2)
* data for the immediate current playback position is available.
* - have_future_data (numeric value 3)
* data for the immediate current playback position is available, as
* well as enough data for the user agent to advance the current
* playback position in the direction of playback.
* - have_enough_data (numeric value 4)
* the user agent estimates that enough data is available for
* playback to proceed uninterrupted.
*
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-readystate
* @return {number} the current playback rendering state
* @method player#readystate
*/
'readystate'].foreach(function (fn) {
player.prototype[fn] = function () {
return this.techget_(fn);
};
});
tech_events_retrigger.foreach(function (event) {
player.prototype['handletech' + (0, _totitlecase2['default'])(event) + '_'] = function () {
return this.trigger(event);
};
});
/**
* fired when the player has initial duration and dimension information
*
* @event player#loadedmetadata
* @type {eventtarget~event}
*/
/**
* fired when the player has downloaded data at the current playback position
*
* @event player#loadeddata
* @type {eventtarget~event}
*/
/**
* fired when the current playback position has changed *
* during playback this is fired every 15-250 milliseconds, depending on the
* playback technology in use.
*
* @event player#timeupdate
* @type {eventtarget~event}
*/
/**
* fired when the volume changes
*
* @event player#volumechange
* @type {eventtarget~event}
*/
_component2['default'].registercomponent('player', player);
exports['default'] = player;
},{"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){
'use strict';
exports.__esmodule = true;
var _player = _dereq_(51);
var _player2 = _interoprequiredefault(_player);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
/**
* the method for registering a video.js plugin. {@link videojs:videojs.registerplugin].
*
* @param {string} name
* the name of the plugin that is being registered
*
* @param {plugins:pluginfn} init
* the function that gets run when a `player` initializes.
*/
var plugin = function plugin(name, init) {
_player2['default'].prototype[name] = init;
}; /**
* @file plugins.js
* @module plugins
*/
exports['default'] = plugin;
},{"51":51}],53:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _clickablecomponent = _dereq_(3);
var _clickablecomponent2 = _interoprequiredefault(_clickablecomponent);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file popup-button.js
*/
/**
* a button class for use with {@link popup} controls
*
* @extends clickablecomponent
*/
var popupbutton = function (_clickablecomponent) {
_inherits(popupbutton, _clickablecomponent);
/**
* create an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function popupbutton(player) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_classcallcheck(this, popupbutton);
var _this = _possibleconstructorreturn(this, _clickablecomponent.call(this, player, options));
_this.update();
return _this;
}
/**
* update the `popup` that this button is attached to.
*/
popupbutton.prototype.update = function update() {
var popup = this.createpopup();
if (this.popup) {
this.removechild(this.popup);
}
this.popup = popup;
this.addchild(popup);
if (this.items && this.items.length === 0) {
this.hide();
} else if (this.items && this.items.length > 1) {
this.show();
}
};
/**
* create a `popup`. - override with specific functionality for component
*
* @abstract
*/
popupbutton.prototype.createpopup = function createpopup() {};
/**
* create the `popupbutton`s dom element.
*
* @return {element}
* the element that gets created.
*/
popupbutton.prototype.createel = function createel() {
return _clickablecomponent.prototype.createel.call(this, 'div', {
classname: this.buildcssclass()
});
};
/**
* builds the default dom `classname`.
*
* @return {string}
* the dom `classname` for this object.
*/
popupbutton.prototype.buildcssclass = function buildcssclass() {
var menubuttonclass = 'vjs-menu-button';
// if the inline option is passed, we want to use different styles altogether.
if (this.options_.inline === true) {
menubuttonclass += '-inline';
} else {
menubuttonclass += '-popup';
}
return 'vjs-menu-button ' + menubuttonclass + ' ' + _clickablecomponent.prototype.buildcssclass.call(this);
};
return popupbutton;
}(_clickablecomponent2['default']);
_component2['default'].registercomponent('popupbutton', popupbutton);
exports['default'] = popupbutton;
},{"3":3,"5":5}],54:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _events = _dereq_(82);
var events = _interoprequirewildcard(_events);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file popup.js
*/
/**
* the popup component is used to build pop up controls.
*
* @extends component
*/
var popup = function (_component) {
_inherits(popup, _component);
function popup() {
_classcallcheck(this, popup);
return _possibleconstructorreturn(this, _component.apply(this, arguments));
}
/**
* add a popup item to the popup
*
* @param {object|string} component
* component or component type to add
*
*/
popup.prototype.additem = function additem(component) {
this.addchild(component);
component.on('click', fn.bind(this, function () {
this.unlockshowing();
}));
};
/**
* create the `popupbutton`s dom element.
*
* @return {element}
* the element that gets created.
*/
popup.prototype.createel = function createel() {
var contenteltype = this.options_.contenteltype || 'ul';
this.contentel_ = dom.createel(contenteltype, {
classname: 'vjs-menu-content'
});
var el = _component.prototype.createel.call(this, 'div', {
append: this.contentel_,
classname: 'vjs-menu'
});
el.appendchild(this.contentel_);
// prevent clicks from bubbling up. needed for popup buttons,
// where a click on the parent is significant
events.on(el, 'click', function (event) {
event.preventdefault();
event.stopimmediatepropagation();
});
return el;
};
return popup;
}(_component2['default']);
_component2['default'].registercomponent('popup', popup);
exports['default'] = popup;
},{"5":5,"81":81,"82":82,"83":83}],55:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _clickablecomponent = _dereq_(3);
var _clickablecomponent2 = _interoprequiredefault(_clickablecomponent);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file poster-image.js
*/
/**
* a `clickablecomponent` that handles showing the poster image for the player.
*
* @extends clickablecomponent
*/
var posterimage = function (_clickablecomponent) {
_inherits(posterimage, _clickablecomponent);
/**
* create an instance of this class.
*
* @param {player} player
* the `player` that this class should attach to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function posterimage(player, options) {
_classcallcheck(this, posterimage);
var _this = _possibleconstructorreturn(this, _clickablecomponent.call(this, player, options));
_this.update();
player.on('posterchange', fn.bind(_this, _this.update));
return _this;
}
/**
* clean up and dispose of the `posterimage`.
*/
posterimage.prototype.dispose = function dispose() {
this.player().off('posterchange', this.update);
_clickablecomponent.prototype.dispose.call(this);
};
/**
* create the `posterimage`s dom element.
*
* @return {element}
* the element that gets created.
*/
posterimage.prototype.createel = function createel() {
var el = dom.createel('div', {
classname: 'vjs-poster',
// don't want poster to be tabbable.
tabindex: -1
});
// to ensure the poster image resizes while maintaining its original aspect
// ratio, use a div with `background-size` when available. for browsers that
// do not support `background-size` (e.g. ie8), fall back on using a regular
// img element.
if (!browser.background_size_supported) {
this.fallbackimg_ = dom.createel('img');
el.appendchild(this.fallbackimg_);
}
return el;
};
/**
* an {@link eventtarget~eventlistener} for {@link player#posterchange} events.
*
* @listens player#posterchange
*
* @param {eventtarget~event} [event]
* the `player#posterchange` event that triggered this function.
*/
posterimage.prototype.update = function update(event) {
var url = this.player().poster();
this.setsrc(url);
// if there's no poster source we should display:none on this component
// so it's not still clickable or right-clickable
if (url) {
this.show();
} else {
this.hide();
}
};
/**
* set the source of the `posterimage` depending on the display method.
*
* @param {string} url
* the url to the source for the `posterimage`.
*/
posterimage.prototype.setsrc = function setsrc(url) {
if (this.fallbackimg_) {
this.fallbackimg_.src = url;
} else {
var backgroundimage = '';
// any falsey values should stay as an empty string, otherwise
// this will throw an extra error
if (url) {
backgroundimage = 'url("' + url + '")';
}
this.el_.style.backgroundimage = backgroundimage;
}
};
/**
* an {@link eventtarget~eventlistener} for clicks on the `posterimage`. see
* {@link clickablecomponent#handleclick} for instances where this will be triggered.
*
* @listens tap
* @listens click
* @listens keydown
*
* @param {eventtarget~event} event
+ the `click`, `tap` or `keydown` event that caused this function to be called.
*/
posterimage.prototype.handleclick = function handleclick(event) {
// we don't want a click to trigger playback when controls are disabled
if (!this.player_.controls()) {
return;
}
if (this.player_.paused()) {
this.player_.play();
} else {
this.player_.pause();
}
};
return posterimage;
}(_clickablecomponent2['default']);
_component2['default'].registercomponent('posterimage', posterimage);
exports['default'] = posterimage;
},{"3":3,"5":5,"78":78,"81":81,"83":83}],56:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
exports.hasloaded = exports.autosetuptimeout = exports.autosetup = undefined;
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _events = _dereq_(82);
var events = _interoprequirewildcard(_events);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
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; } }
/**
* @file setup.js - functions for setting up a player without
* user interaction based on the data-setup `attribute` of the video tag.
*
* @module setup
*/
var _windowloaded = false;
var videojs = void 0;
/**
* set up any tags that have a data-setup `attribute` when the player is started.
*/
var autosetup = function autosetup() {
// protect against breakage in non-browser environments.
if (!dom.isreal()) {
return;
}
// one day, when we stop supporting ie8, go back to this, but in the meantime...*hack hack hack*
// var vids = array.prototype.slice.call(document.getelementsbytagname('video'));
// var audios = array.prototype.slice.call(document.getelementsbytagname('audio'));
// var mediaels = vids.concat(audios);
// because ie8 doesn't support calling slice on a node list, we need to loop
// through each list of elements to build up a new, combined list of elements.
var vids = _document2['default'].getelementsbytagname('video');
var audios = _document2['default'].getelementsbytagname('audio');
var mediaels = [];
if (vids && vids.length > 0) {
for (var i = 0, e = vids.length; i < e; i++) {
mediaels.push(vids[i]);
}
}
if (audios && audios.length > 0) {
for (var _i = 0, _e = audios.length; _i < _e; _i++) {
mediaels.push(audios[_i]);
}
}
// check if any media elements exist
if (mediaels && mediaels.length > 0) {
for (var _i2 = 0, _e2 = mediaels.length; _i2 < _e2; _i2++) {
var mediael = mediaels[_i2];
// check if element exists, has getattribute func.
// ie seems to consider typeof el.getattribute == 'object' instead of
// 'function' like expected, at least when loading the player immediately.
if (mediael && mediael.getattribute) {
// make sure this player hasn't already been set up.
if (mediael.player === undefined) {
var options = mediael.getattribute('data-setup');
// check if data-setup attr exists.
// we only auto-setup if they've added the data-setup attr.
if (options !== null) {
// create new video.js instance.
videojs(mediael);
}
}
// if getattribute isn't defined, we need to wait for the dom.
} else {
autosetuptimeout(1);
break;
}
}
// no videos were found, so keep looping unless page is finished loading.
} else if (!_windowloaded) {
autosetuptimeout(1);
}
};
/**
* wait until the page is loaded before running autosetup. this will be called in
* autosetup if `hasloaded` returns false.
*
* @param {number} wait
* how long to wait in ms
*
* @param {videojs} [vjs]
* the videojs library function
*/
function autosetuptimeout(wait, vjs) {
if (vjs) {
videojs = vjs;
}
_window2['default'].settimeout(autosetup, wait);
}
if (dom.isreal() && _document2['default'].readystate === 'complete') {
_windowloaded = true;
} else {
/**
* listen for the load event on window, and set _windowloaded to true.
*
* @listens load
*/
events.one(_window2['default'], 'load', function () {
_windowloaded = true;
});
}
/**
* check if the document has been loaded
*/
var hasloaded = function hasloaded() {
return _windowloaded;
};
exports.autosetup = autosetup;
exports.autosetuptimeout = autosetuptimeout;
exports.hasloaded = hasloaded;
},{"81":81,"82":82,"94":94,"95":95}],57:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _obj = _dereq_(88);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file slider.js
*/
/**
* the base functionality for a slider. can be vertical or horizontal.
* for instance the volume bar or the seek bar on a video is a slider.
*
* @extends component
*/
var slider = function (_component) {
_inherits(slider, _component);
/**
* create an instance of this class
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*/
function slider(player, options) {
_classcallcheck(this, slider);
// set property names to bar to match with the child slider class is looking for
var _this = _possibleconstructorreturn(this, _component.call(this, player, options));
_this.bar = _this.getchild(_this.options_.barname);
// set a horizontal or vertical class on the slider depending on the slider type
_this.vertical(!!_this.options_.vertical);
_this.on('mousedown', _this.handlemousedown);
_this.on('touchstart', _this.handlemousedown);
_this.on('focus', _this.handlefocus);
_this.on('blur', _this.handleblur);
_this.on('click', _this.handleclick);
_this.on(player, 'controlsvisible', _this.update);
_this.on(player, _this.playerevent, _this.update);
return _this;
}
/**
* create the `button`s dom element.
*
* @param {string} type
* type of element to create.
*
* @param {object} [props={}]
* list of properties in object form.
*
* @param {object} [attributes={}]
* list of attributes in object form.
*
* @return {element}
* the element that gets created.
*/
slider.prototype.createel = function createel(type) {
var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
// add the slider element class to all sub classes
props.classname = props.classname + ' vjs-slider';
props = (0, _obj.assign)({
tabindex: 0
}, props);
attributes = (0, _obj.assign)({
'role': 'slider',
'aria-valuenow': 0,
'aria-valuemin': 0,
'aria-valuemax': 100,
'tabindex': 0
}, attributes);
return _component.prototype.createel.call(this, type, props, attributes);
};
/**
* handle `mousedown` or `touchstart` events on the `slider`.
*
* @param {eventtarget~event} event
* `mousedown` or `touchstart` event that triggered this function
*
* @listens mousedown
* @listens touchstart
* @fires slider#slideractive
*/
slider.prototype.handlemousedown = function handlemousedown(event) {
var doc = this.bar.el_.ownerdocument;
event.preventdefault();
dom.blocktextselection();
this.addclass('vjs-sliding');
/**
* triggered when the slider is in an active state
*
* @event slider#slideractive
* @type {eventtarget~event}
*/
this.trigger('slideractive');
this.on(doc, 'mousemove', this.handlemousemove);
this.on(doc, 'mouseup', this.handlemouseup);
this.on(doc, 'touchmove', this.handlemousemove);
this.on(doc, 'touchend', this.handlemouseup);
this.handlemousemove(event);
};
/**
* handle the `mousemove`, `touchmove`, and `mousedown` events on this `slider`.
* the `mousemove` and `touchmove` events will only only trigger this function during
* `mousedown` and `touchstart`. this is due to {@link slider#handlemousedown} and
* {@link slider#handlemouseup}.
*
* @param {eventtarget~event} event
* `mousedown`, `mousemove`, `touchstart`, or `touchmove` event that triggered
* this function
*
* @listens mousemove
* @listens touchmove
*/
slider.prototype.handlemousemove = function handlemousemove(event) {};
/**
* handle `mouseup` or `touchend` events on the `slider`.
*
* @param {eventtarget~event} event
* `mouseup` or `touchend` event that triggered this function.
*
* @listens touchend
* @listens mouseup
* @fires slider#sliderinactive
*/
slider.prototype.handlemouseup = function handlemouseup() {
var doc = this.bar.el_.ownerdocument;
dom.unblocktextselection();
this.removeclass('vjs-sliding');
/**
* triggered when the slider is no longer in an active state.
*
* @event slider#sliderinactive
* @type {eventtarget~event}
*/
this.trigger('sliderinactive');
this.off(doc, 'mousemove', this.handlemousemove);
this.off(doc, 'mouseup', this.handlemouseup);
this.off(doc, 'touchmove', this.handlemousemove);
this.off(doc, 'touchend', this.handlemouseup);
this.update();
};
/**
* update the progress bar of the `slider`.
*/
slider.prototype.update = function update() {
// in volumebar init we have a settimeout for update that pops and update to the end of the
// execution stack. the player is destroyed before then update will cause an error
if (!this.el_) {
return;
}
// if scrubbing, we could use a cached value to make the handle keep up with the user's mouse.
// on html5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later.
// var progress = (this.player_.scrubbing()) ? this.player_.getcache().currenttime / this.player_.duration() : this.player_.currenttime() / this.player_.duration();
var progress = this.getpercent();
var bar = this.bar;
// if there's no bar...
if (!bar) {
return;
}
// protect against no duration and other division issues
if (typeof progress !== 'number' || progress !== progress || progress < 0 || progress === infinity) {
progress = 0;
}
// convert to a percentage for setting
var percentage = (progress * 100).tofixed(2) + '%';
// set the new bar width or height
if (this.vertical()) {
bar.el().style.height = percentage;
} else {
bar.el().style.width = percentage;
}
};
/**
* calculate distance for slider
*
* @param {eventtarget~event} event
* the event that caused this function to run.
*
* @return {number}
* the current position of the slider.
* - postition.x for vertical `slider`s
* - postition.y for horizontal `slider`s
*/
slider.prototype.calculatedistance = function calculatedistance(event) {
var position = dom.getpointerposition(this.el_, event);
if (this.vertical()) {
return position.y;
}
return position.x;
};
/**
* handle a `focus` event on this `slider`.
*
* @param {eventtarget~event} event
* the `focus` event that caused this function to run.
*
* @listens focus
*/
slider.prototype.handlefocus = function handlefocus() {
this.on(this.bar.el_.ownerdocument, 'keydown', this.handlekeypress);
};
/**
* handle a `keydown` event on the `slider`. watches for left, rigth, up, and down
* arrow keys. this function will only be called when the slider has focus. see
* {@link slider#handlefocus} and {@link slider#handleblur}.
*
* @param {eventtarget~event} event
* the `keydown` event that caused this function to run.
*
* @listens keydown
*/
slider.prototype.handlekeypress = function handlekeypress(event) {
// left and down arrows
if (event.which === 37 || event.which === 40) {
event.preventdefault();
this.stepback();
// up and right arrows
} else if (event.which === 38 || event.which === 39) {
event.preventdefault();
this.stepforward();
}
};
/**
* handle a `blur` event on this `slider`.
*
* @param {eventtarget~event} event
* the `blur` event that caused this function to run.
*
* @listens blur
*/
slider.prototype.handleblur = function handleblur() {
this.off(this.bar.el_.ownerdocument, 'keydown', this.handlekeypress);
};
/**
* listener for click events on slider, used to prevent clicks
* from bubbling up to parent elements like button menus.
*
* @param {object} event
* event that caused this object to run
*/
slider.prototype.handleclick = function handleclick(event) {
event.stopimmediatepropagation();
event.preventdefault();
};
/**
* get/set if slider is horizontal for vertical
*
* @param {boolean} [bool]
* - true if slider is vertical,
* - false is horizontal
*
* @return {boolean|slider}
* - true if slider is vertical, and getting
* - false is horizontal, and getting
* - a reference to this object when setting
*/
slider.prototype.vertical = function vertical(bool) {
if (bool === undefined) {
return this.vertical_ || false;
}
this.vertical_ = !!bool;
if (this.vertical_) {
this.addclass('vjs-slider-vertical');
} else {
this.addclass('vjs-slider-horizontal');
}
return this;
};
return slider;
}(_component2['default']);
_component2['default'].registercomponent('slider', slider);
exports['default'] = slider;
},{"5":5,"81":81,"88":88}],58:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
/**
* @file flash-rtmp.js
* @module flash-rtmp
*/
/**
* add rtmp properties to the {@link flash} tech.
*
* @param {flash} flash
* the flash tech class.
*
* @mixin flashrtmpdecorator
*/
function flashrtmpdecorator(flash) {
flash.streamingformats = {
'rtmp/mp4': 'mp4',
'rtmp/flv': 'flv'
};
/**
* join connection and stream with an ampersand.
*
* @param {string} connection
* the connection string.
*
* @param {string} stream
* the stream string.
*/
flash.streamfromparts = function (connection, stream) {
return connection + '&' + stream;
};
/**
* the flash parts object that contains connection and stream info.
*
* @typedef {object} flash~partsobject
*
* @property {string} connection
* the connection string of a source, defaults to an empty string.
*
* @property {string} stream
* the stream string of the source, defaults to an empty string.
*/
/**
* convert a source url into a stream and connection parts.
*
* @param {string} src
* the source url
*
* @return {flash~partsobject}
* the parts object that contains a connection and a stream
*/
flash.streamtoparts = function (src) {
var parts = {
connection: '',
stream: ''
};
if (!src) {
return parts;
}
// look for the normal url separator we expect, '&'.
// if found, we split the url into two pieces around the
// first '&'.
var connend = src.search(/&(?!\w+=)/);
var streambegin = void 0;
if (connend !== -1) {
streambegin = connend + 1;
} else {
// if there's not a '&', we use the last '/' as the delimiter.
connend = streambegin = src.lastindexof('/') + 1;
if (connend === 0) {
// really, there's not a '/'?
connend = streambegin = src.length;
}
}
parts.connection = src.substring(0, connend);
parts.stream = src.substring(streambegin, src.length);
return parts;
};
/**
* check if the source type is a streaming type.
*
* @param {string} srctype
* the mime type to check.
*
* @return {boolean}
* - true if the source type is a streaming type.
* - false if the source type is not a streaming type.
*/
flash.isstreamingtype = function (srctype) {
return srctype in flash.streamingformats;
};
// rtmp has four variations, any string starting
// with one of these protocols should be valid
/**
* regular expression used to check if the source is an rtmp source.
*
* @property {regexp} flash.rtmp_re
*/
flash.rtmp_re = /^rtmp[set]?:\/\//i;
/**
* check if the source itself is a streaming type.
*
* @param {string} src
* the url to the source.
*
* @return {boolean}
* - true if the source url indicates that the source is streaming.
* - false if the shource url indicates that the source url is not streaming.
*/
flash.isstreamingsrc = function (src) {
return flash.rtmp_re.test(src);
};
/**
* a source handler for rtmp urls
* @type {object}
*/
flash.rtmpsourcehandler = {};
/**
* check if flash can play the given mime type.
*
* @param {string} type
* the mime type to check
*
* @return {string}
* 'maybe', or '' (empty string)
*/
flash.rtmpsourcehandler.canplaytype = function (type) {
if (flash.isstreamingtype(type)) {
return 'maybe';
}
return '';
};
/**
* check if flash can handle the source natively
*
* @param {object} source
* the source object
*
* @param {object} [options]
* the options passed to the tech
*
* @return {string}
* 'maybe', or '' (empty string)
*/
flash.rtmpsourcehandler.canhandlesource = function (source, options) {
var can = flash.rtmpsourcehandler.canplaytype(source.type);
if (can) {
return can;
}
if (flash.isstreamingsrc(source.src)) {
return 'maybe';
}
return '';
};
/**
* pass the source to the flash object.
*
* @param {object} source
* the source object
*
* @param {flash} tech
* the instance of the flash tech
*
* @param {object} [options]
* the options to pass to the source
*/
flash.rtmpsourcehandler.handlesource = function (source, tech, options) {
var srcparts = flash.streamtoparts(source.src);
tech.setrtmpconnection(srcparts.connection);
tech.setrtmpstream(srcparts.stream);
};
// register the native source handler
flash.registersourcehandler(flash.rtmpsourcehandler);
return flash;
}
exports['default'] = flashrtmpdecorator;
},{}],59:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _tech = _dereq_(62);
var _tech2 = _interoprequiredefault(_tech);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _url = _dereq_(92);
var url = _interoprequirewildcard(_url);
var _timeranges = _dereq_(90);
var _flashrtmp = _dereq_(58);
var _flashrtmp2 = _interoprequiredefault(_flashrtmp);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
var _obj = _dereq_(88);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file flash.js
* videojs-swf - custom flash player with html5-ish api
* https://github.com/zencoder/video-js-swf
* not using setuptriggers. using global onevent func to distribute events
*/
var navigator = _window2['default'].navigator;
/**
* flash media controller - wrapper for flash media api
*
* @mixes flashrtmpdecorator
* @mixes tech~soucehandleradditions
* @extends tech
*/
var flash = function (_tech) {
_inherits(flash, _tech);
/**
* create an instance of this tech.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} ready
* callback function to call when the `flash` tech is ready.
*/
function flash(options, ready) {
_classcallcheck(this, flash);
// set the source when ready
var _this = _possibleconstructorreturn(this, _tech.call(this, options, ready));
if (options.source) {
_this.ready(function () {
this.setsource(options.source);
}, true);
}
// having issues with flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers
// this allows resetting the playhead when we catch the reload
if (options.starttime) {
_this.ready(function () {
this.load();
this.play();
this.currenttime(options.starttime);
}, true);
}
// add global window functions that the swf expects
// a 4.x workflow we weren't able to solve for in 5.0
// because of the need to hard code these functions
// into the swf for security reasons
_window2['default'].videojs = _window2['default'].videojs || {};
_window2['default'].videojs.flash = _window2['default'].videojs.flash || {};
_window2['default'].videojs.flash.onready = flash.onready;
_window2['default'].videojs.flash.onevent = flash.onevent;
_window2['default'].videojs.flash.onerror = flash.onerror;
_this.on('seeked', function () {
this.lastseektarget_ = undefined;
});
return _this;
}
/**
* create the `flash` tech's dom element.
*
* @return {element}
* the element that gets created.
*/
flash.prototype.createel = function createel() {
var options = this.options_;
// if video.js is hosted locally you should also set the location
// for the hosted swf, which should be relative to the page (not video.js)
// otherwise this adds a cdn url.
// the cdn also auto-adds a swf url for that specific version.
if (!options.swf) {
var ver = '5.3.0';
options.swf = '//vjs.zencdn.net/swf/' + ver + '/video-js.swf';
}
// generate id for swf object
var objid = options.techid;
// merge default flashvars with ones passed in to init
var flashvars = (0, _obj.assign)({
// swf callback functions
readyfunction: 'videojs.flash.onready',
eventproxyfunction: 'videojs.flash.onevent',
erroreventproxyfunction: 'videojs.flash.onerror',
// player settings
autoplay: options.autoplay,
preload: options.preload,
loop: options.loop,
muted: options.muted
}, options.flashvars);
// merge default parames with ones passed in
var params = (0, _obj.assign)({
// opaque is needed to overlay controls, but can affect playback performance
wmode: 'opaque',
// using bgcolor prevents a white flash when the object is loading
bgcolor: '#000000'
}, options.params);
// merge default attributes with ones passed in
var attributes = (0, _obj.assign)({
// both id and name needed or swf to identify itself
id: objid,
name: objid,
'class': 'vjs-tech'
}, options.attributes);
this.el_ = flash.embed(options.swf, flashvars, params, attributes);
this.el_.tech = this;
return this.el_;
};
/**
* called by {@link player#play} to play using the `flash` `tech`.
*/
flash.prototype.play = function play() {
if (this.ended()) {
this.setcurrenttime(0);
}
this.el_.vjs_play();
};
/**
* called by {@link player#pause} to pause using the `flash` `tech`.
*/
flash.prototype.pause = function pause() {
this.el_.vjs_pause();
};
/**
* a getter/setter for the `flash` tech's source object.
* > note: please use {@link flash#setsource}
*
* @param {tech~sourceobject} [src]
* the source object you want to set on the `flash` techs.
*
* @return {tech~sourceobject|undefined}
* - the current source object when a source is not passed in.
* - undefined when setting
*
* @deprecated since version 5.
*/
flash.prototype.src = function src(_src) {
if (_src === undefined) {
return this.currentsrc();
}
// setting src through `src` not `setsrc` will be deprecated
return this.setsrc(_src);
};
/**
* a getter/setter for the `flash` tech's source object.
*
* @param {tech~sourceobject} [src]
* the source object you want to set on the `flash` techs.
*
* @return {tech~sourceobject|undefined}
* - the current source object when a source is not passed in.
* - undefined when setting
*/
flash.prototype.setsrc = function setsrc(src) {
var _this2 = this;
// make sure source url is absolute.
src = url.getabsoluteurl(src);
this.el_.vjs_src(src);
// currently the swf doesn't autoplay if you load a source later.
// e.g. load player w/ no source, wait 2s, set src.
if (this.autoplay()) {
this.settimeout(function () {
return _this2.play();
}, 0);
}
};
/**
* indicates whether the media is currently seeking to a new position or not.
*
* @return {boolean}
* - true if seeking to a new position
* - false otherwise
*/
flash.prototype.seeking = function seeking() {
return this.lastseektarget_ !== undefined;
};
/**
* returns the current time in seconds that the media is at in playback.
*
* @param {number} time
* current playtime of the media in seconds.
*/
flash.prototype.setcurrenttime = function setcurrenttime(time) {
var seekable = this.seekable();
if (seekable.length) {
// clamp to the current seekable range
time = time > seekable.start(0) ? time : seekable.start(0);
time = time < seekable.end(seekable.length - 1) ? time : seekable.end(seekable.length - 1);
this.lastseektarget_ = time;
this.trigger('seeking');
this.el_.vjs_setproperty('currenttime', time);
_tech.prototype.setcurrenttime.call(this);
}
};
/**
* get the current playback time in seconds
*
* @return {number}
* the current time of playback in seconds.
*/
flash.prototype.currenttime = function currenttime() {
// when seeking make the reported time keep up with the requested time
// by reading the time we're seeking to
if (this.seeking()) {
return this.lastseektarget_ || 0;
}
return this.el_.vjs_getproperty('currenttime');
};
/**
* get the current source
*
* @method currentsrc
* @return {tech~sourceobject}
* the current source
*/
flash.prototype.currentsrc = function currentsrc() {
if (this.currentsource_) {
return this.currentsource_.src;
}
return this.el_.vjs_getproperty('currentsrc');
};
/**
* get the total duration of the current media.
*
* @return {number}
8 the total duration of the current media.
*/
flash.prototype.duration = function duration() {
if (this.readystate() === 0) {
return nan;
}
var duration = this.el_.vjs_getproperty('duration');
return duration >= 0 ? duration : infinity;
};
/**
* load media into tech.
*/
flash.prototype.load = function load() {
this.el_.vjs_load();
};
/**
* get the poster image that was set on the tech.
*/
flash.prototype.poster = function poster() {
this.el_.vjs_getproperty('poster');
};
/**
* poster images are not handled by the flash tech so make this is a no-op.
*/
flash.prototype.setposter = function setposter() {};
/**
* determine the time ranges that can be seeked to in the media.
*
* @return {timerange}
* returns the time ranges that can be seeked to.
*/
flash.prototype.seekable = function seekable() {
var duration = this.duration();
if (duration === 0) {
return (0, _timeranges.createtimerange)();
}
return (0, _timeranges.createtimerange)(0, duration);
};
/**
* get and create a `timerange` object for buffering.
*
* @return {timerange}
* the time range object that was created.
*/
flash.prototype.buffered = function buffered() {
var ranges = this.el_.vjs_getproperty('buffered');
if (ranges.length === 0) {
return (0, _timeranges.createtimerange)();
}
return (0, _timeranges.createtimerange)(ranges[0][0], ranges[0][1]);
};
/**
* get fullscreen support -
*
* flash does not allow fullscreen through javascript
* so this always returns false.
*
* @return {boolean}
* the flash tech does not support fullscreen, so it will always return false.
*/
flash.prototype.supportsfullscreen = function supportsfullscreen() {
// flash does not allow fullscreen through javascript
return false;
};
/**
* flash does not allow fullscreen through javascript
* so this always returns false.
*
* @return {boolean}
* the flash tech does not support fullscreen, so it will always return false.
*/
flash.prototype.enterfullscreen = function enterfullscreen() {
return false;
};
return flash;
}(_tech2['default']);
// create setters and getters for attributes
var _api = flash.prototype;
var _readwrite = 'rtmpconnection,rtmpstream,preload,defaultplaybackrate,playbackrate,autoplay,loop,mediagroup,controller,controls,volume,muted,defaultmuted'.split(',');
var _readonly = 'networkstate,readystate,initialtime,startoffsettime,paused,ended,videowidth,videoheight'.split(',');
function _createsetter(attr) {
var attrupper = attr.charat(0).touppercase() + attr.slice(1);
_api['set' + attrupper] = function (val) {
return this.el_.vjs_setproperty(attr, val);
};
}
function _creategetter(attr) {
_api[attr] = function () {
return this.el_.vjs_getproperty(attr);
};
}
// create getter and setters for all read/write attributes
for (var i = 0; i < _readwrite.length; i++) {
_creategetter(_readwrite[i]);
_createsetter(_readwrite[i]);
}
// create getters for read-only attributes
for (var _i = 0; _i < _readonly.length; _i++) {
_creategetter(_readonly[_i]);
}
/** ------------------------------ getters ------------------------------ **/
/**
* get the value of `rtmpconnection` from the swf.
*
* @method flash#rtmpconnection
* @return {string}
* the current value of `rtmpconnection` on the swf.
*/
/**
* get the value of `rtmpstream` from the swf.
*
* @method flash#rtmpstream
* @return {string}
* the current value of `rtmpstream` on the swf.
*/
/**
* get the value of `preload` from the swf. `preload` indicates
* what should download before the media is interacted with. it can have the following
* values:
* - none: nothing should be downloaded
* - metadata: poster and the first few frames of the media may be downloaded to get
* media dimensions and other metadata
* - auto: allow the media and metadata for the media to be downloaded before
* interaction
*
* @method flash#preload
* @return {string}
* the value of `preload` from the swf. will be 'none', 'metadata',
* or 'auto'.
*/
/**
* get the value of `defaultplaybackrate` from the swf.
*
* @method flash#defaultplaybackrate
* @return {number}
* the current value of `defaultplaybackrate` on the swf.
*/
/**
* get the value of `playbackrate` from the swf. `playbackrate` indicates
* the rate at which the media is currently playing back. examples:
* - if playbackrate is set to 2, media will play twice as fast.
* - if playbackrate is set to 0.5, media will play half as fast.
*
* @method flash#playbackrate
* @return {number}
* the value of `playbackrate` from the swf. a number indicating
* the current playback speed of the media, where 1 is normal speed.
*/
/**
* get the value of `autoplay` from the swf. `autoplay` indicates
* that the media should start to play as soon as the page is ready.
*
* @method flash#autoplay
* @return {boolean}
* - the value of `autoplay` from the swf.
* - true indicates that the media ashould start as soon as the page loads.
* - false indicates that the media should not start as soon as the page loads.
*/
/**
* get the value of `loop` from the swf. `loop` indicates
* that the media should return to the start of the media and continue playing once
* it reaches the end.
*
* @method flash#loop
* @return {boolean}
* - the value of `loop` from the swf.
* - true indicates that playback should seek back to start once
* the end of a media is reached.
* - false indicates that playback should not loop back to the start when the
* end of the media is reached.
*/
/**
* get the value of `mediagroup` from the swf.
*
* @method flash#mediagroup
* @return {string}
* the current value of `mediagroup` on the swf.
*/
/**
* get the value of `controller` from the swf.
*
* @method flash#controller
* @return {string}
* the current value of `controller` on the swf.
*/
/**
* get the value of `controls` from the swf. `controls` indicates
* whether the native flash controls should be shown or hidden.
*
* @method flash#controls
* @return {boolean}
* - the value of `controls` from the swf.
* - true indicates that native controls should be showing.
* - false indicates that native controls should be hidden.
*/
/**
* get the value of the `volume` from the swf. `volume` indicates the current
* audio level as a percentage in decimal form. this means that 1 is 100%, 0.5 is 50%, and
* so on.
*
* @method flash#volume
* @return {number}
* the volume percent as a decimal. value will be between 0-1.
*/
/**
* get the value of the `muted` from the swf. `muted` indicates the current
* audio level should be silent.
*
* @method flash#muted
* @return {boolean}
* - true if the audio should be set to silent
* - false otherwise
*/
/**
* get the value of `defaultmuted` from the swf. `defaultmuted` indicates
* whether the media should start muted or not. only changes the default state of the
* media. `muted` and `defaultmuted` can have different values. `muted` indicates the
* current state.
*
* @method flash#defaultmuted
* @return {boolean}
* - the value of `defaultmuted` from the swf.
* - true indicates that the media should start muted.
* - false indicates that the media should not start muted.
*/
/**
* get the value of `networkstate` from the swf. `networkstate` indicates
* the current network state. it returns an enumeration from the following list:
* - 0: network_empty
* - 1: nework_idle
* - 2: network_loading
* - 3: network_no_source
*
* @method flash#networkstate
* @return {number}
* the value of `networkstate` from the swf. this will be a number
* from the list in the description.
*/
/**
* get the value of `readystate` from the swf. `readystate` indicates
* the current state of the media element. it returns an enumeration from the
* following list:
* - 0: have_nothing
* - 1: have_metadata
* - 2: have_current_data
* - 3: have_future_data
* - 4: have_enough_data
*
* @method flash#readystate
* @return {number}
* the value of `readystate` from the swf. this will be a number
* from the list in the description.
*/
/**
* get the value of `readystate` from the swf. `readystate` indicates
* the current state of the media element. it returns an enumeration from the
* following list:
* - 0: have_nothing
* - 1: have_metadata
* - 2: have_current_data
* - 3: have_future_data
* - 4: have_enough_data
*
* @method flash#readystate
* @return {number}
* the value of `readystate` from the swf. this will be a number
* from the list in the description.
*/
/**
* get the value of `initialtime` from the swf.
*
* @method flash#initialtime
* @return {number}
* the `initialtime` proprety on the swf.
*/
/**
* get the value of `startoffsettime` from the swf.
*
* @method flash#startoffsettime
* @return {number}
* the `startoffsettime` proprety on the swf.
*/
/**
* get the value of `paused` from the swf. `paused` indicates whether the swf
* is current paused or not.
*
* @method flash#paused
* @return {boolean}
* the value of `paused` from the swf.
*/
/**
* get the value of `ended` from the swf. `ended` indicates whether
* the media has reached the end or not.
*
* @method flash#ended
* @return {boolean}
* - true indicates that the media has ended.
* - false indicates that the media has not ended.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-ended}
*/
/**
* get the value of `videowidth` from the swf. `videowidth` indicates
* the current width of the media in css pixels.
*
* @method flash#videowidth
* @return {number}
* the value of `videowidth` from the swf. this will be a number
* in css pixels.
*/
/**
* get the value of `videoheight` from the swf. `videoheigth` indicates
* the current height of the media in css pixels.
*
* @method flassh.prototype.videoheight
* @return {number}
* the value of `videoheight` from the swf. this will be a number
* in css pixels.
*/
/** ------------------------------ setters ------------------------------ **/
/**
* set the value of `rtmpconnection` on the swf.
*
* @method flash#setrtmpconnection
* @param {string} rtmpconnection
* new value to set the `rtmpconnection` property to.
*/
/**
* set the value of `rtmpstream` on the swf.
*
* @method flash#setrtmpstream
* @param {string} rtmpstream
* new value to set the `rtmpstream` property to.
*/
/**
* set the value of `preload` on the swf. `preload` indicates
* what should download before the media is interacted with. it can have the following
* values:
* - none: nothing should be downloaded
* - metadata: poster and the first few frames of the media may be downloaded to get
* media dimensions and other metadata
* - auto: allow the media and metadata for the media to be downloaded before
* interaction
*
* @method flash#setpreload
* @param {string} preload
* the value of `preload` to set on the swf. should be 'none', 'metadata',
* or 'auto'.
*/
/**
* set the value of `defaultplaybackrate` on the swf.
*
* @method flash#setdefaultplaybackrate
* @param {number} defaultplaybackrate
* new value to set the `defaultplaybackrate` property to.
*/
/**
* set the value of `playbackrate` on the swf. `playbackrate` indicates
* the rate at which the media is currently playing back. examples:
* - if playbackrate is set to 2, media will play twice as fast.
* - if playbackrate is set to 0.5, media will play half as fast.
*
* @method flash#setplaybackrate
* @param {number} playbackrate
* new value of `playbackrate` on the swf. a number indicating
* the current playback speed of the media, where 1 is normal speed.
*/
/**
* set the value of `autoplay` on the swf. `autoplay` indicates
* that the media should start to play as soon as the page is ready.
*
* @method flash#setautoplay
* @param {boolean} autoplay
* - the value of `autoplay` from the swf.
* - true indicates that the media ashould start as soon as the page loads.
* - false indicates that the media should not start as soon as the page loads.
*/
/**
* set the value of `loop` on the swf. `loop` indicates
* that the media should return to the start of the media and continue playing once
* it reaches the end.
*
* @method flash#setloop
* @param {boolean} loop
* - true indicates that playback should seek back to start once
* the end of a media is reached.
* - false indicates that playback should not loop back to the start when the
* end of the media is reached.
*/
/**
* set the value of `mediagroup` on the swf.
*
* @method flash#setmediagroup
* @param {string} mediagroup
* new value of `mediagroup` to set on the swf.
*/
/**
* set the value of `controller` on the swf.
*
* @method flash#setcontroller
* @param {string} controller
* new value the current value of `controller` on the swf.
*/
/**
* get the value of `controls` from the swf. `controls` indicates
* whether the native flash controls should be shown or hidden.
*
* @method flash#controls
* @return {boolean}
* - the value of `controls` from the swf.
* - true indicates that native controls should be showing.
* - false indicates that native controls should be hidden.
*/
/**
* set the value of the `volume` on the swf. `volume` indicates the current
* audio level as a percentage in decimal form. this means that 1 is 100%, 0.5 is 50%, and
* so on.
*
* @method flash#setvolume
* @param {number} percentasdecimal
* the volume percent as a decimal. value will be between 0-1.
*/
/**
* set the value of the `muted` on the swf. `muted` indicates that the current
* audio level should be silent.
*
* @method flash#setmuted
* @param {boolean} muted
* - true if the audio should be set to silent
* - false otherwise
*/
/**
* set the value of `defaultmuted` on the swf. `defaultmuted` indicates
* whether the media should start muted or not. only changes the default state of the
* media. `muted` and `defaultmuted` can have different values. `muted` indicates the
* current state.
*
* @method flash#setdefaultmuted
* @param {boolean} defaultmuted
* - true indicates that the media should start muted.
* - false indicates that the media should not start muted.
*/
/* flash support testing -------------------------------------------------------- */
/**
* check if the flash tech is currently supported.
*
* @return {boolean}
* - true if the flash tech is supported.
* - false otherwise.
*/
flash.issupported = function () {
return flash.version()[0] >= 10;
// return swfobject.hasflashplayerversion('10');
};
// add source handler pattern functions to this tech
_tech2['default'].withsourcehandlers(flash);
/*
* native source handler for flash, simply passes the source to the swf element.
*
* @property {tech~sourceobject} source
* the source object
*
* @property {flash} tech
* the instance of the flash tech
*/
flash.nativesourcehandler = {};
/**
* check if the flash can play the given mime type.
*
* @param {string} type
* the mimetype to check
*
* @return {string}
* 'maybe', or '' (empty string)
*/
flash.nativesourcehandler.canplaytype = function (type) {
if (type in flash.formats) {
return 'maybe';
}
return '';
};
/**
* check if the media element can handle a source natively.
*
* @param {tech~sourceobject} source
* the source object
*
* @param {object} [options]
* options to be passed to the tech.
*
* @return {string}
* 'maybe', or '' (empty string).
*/
flash.nativesourcehandler.canhandlesource = function (source, options) {
var type = void 0;
function guessmimetype(src) {
var ext = url.getfileextension(src);
if (ext) {
return 'video/' + ext;
}
return '';
}
if (!source.type) {
type = guessmimetype(source.src);
} else {
// strip code information from the type because we don't get that specific
type = source.type.replace(/;.*/, '').tolowercase();
}
return flash.nativesourcehandler.canplaytype(type);
};
/**
* pass the source to the swf.
*
* @param {tech~sourceobject} source
* the source object
*
* @param {flash} tech
* the instance of the flash tech
*
* @param {object} [options]
* the options to pass to the source
*/
flash.nativesourcehandler.handlesource = function (source, tech, options) {
tech.setsrc(source.src);
};
/**
* noop for native source handler dispose, as cleanup will happen automatically.
*/
flash.nativesourcehandler.dispose = function () {};
// register the native source handler
flash.registersourcehandler(flash.nativesourcehandler);
/**
* flash supported mime types.
*
* @constant {object}
*/
flash.formats = {
'video/flv': 'flv',
'video/x-flv': 'flv',
'video/mp4': 'mp4',
'video/m4v': 'mp4'
};
/**
* called when the the swf is "ready", and makes sure that the swf is really
* ready using {@link flash#checkready}
*/
flash.onready = function (currswf) {
var el = dom.getel(currswf);
var tech = el && el.tech;
// if there is no el then the tech has been disposed
// and the tech element was removed from the player div
if (tech && tech.el()) {
// check that the flash object is really ready
flash.checkready(tech);
}
};
/**
* the swf isn't always ready when it says it is. sometimes the api functions still
* need to be added to the object. if it's not ready, we set a timeout to check again
* shortly.
*
* @param {flash} tech
* the instance of the flash tech to check.
*/
flash.checkready = function (tech) {
// stop worrying if the tech has been disposed
if (!tech.el()) {
return;
}
// check if api property exists
if (tech.el().vjs_getproperty) {
// tell tech it's ready
tech.triggerready();
} else {
// wait longer
this.settimeout(function () {
flash.checkready(tech);
}, 50);
}
};
/**
* trigger events from the swf on the flash tech.
*
* @param {number} swfid
* the id of the swf that had the event
*
* @param {string} eventname
* the name of the event to trigger
*/
flash.onevent = function (swfid, eventname) {
var tech = dom.getel(swfid).tech;
var args = array.prototype.slice.call(arguments, 2);
// dispatch flash events asynchronously for two reasons:
// - flash swallows any exceptions generated by javascript it
// invokes
// - flash is suspended until the javascript returns which may cause
// playback performance issues
tech.settimeout(function () {
tech.trigger(eventname, args);
}, 1);
};
/**
* log errors from the swf on the flash tech.
*
* @param {number} swfid
* the id of the swf that had an error.
*
* @param {string} the error string
* the error to set on the flash tech.
*
* @return {mediaerror|undefined}
* - returns a mediaerror when err is 'srcnotfound'
* - returns undefined otherwise.
*/
flash.onerror = function (swfid, err) {
var tech = dom.getel(swfid).tech;
// trigger media_err_src_not_supported
if (err === 'srcnotfound') {
return tech.error(4);
}
// trigger a custom error
tech.error('flash: ' + err);
};
/**
* get the current version of flash that is in use on the page.
*
* @return {array}
* an array of versions that are available.
*/
flash.version = function () {
var version = '0,0,0';
// ie
try {
version = new _window2['default'].activexobject('shockwaveflash.shockwaveflash').getvariable('$version').replace(/\d+/g, ',').match(/^,?(.+),?$/)[1];
// other browsers
} catch (e) {
try {
if (navigator.mimetypes['application/x-shockwave-flash'].enabledplugin) {
version = (navigator.plugins['shockwave flash 2.0'] || navigator.plugins['shockwave flash']).description.replace(/\d+/g, ',').match(/^,?(.+),?$/)[1];
}
} catch (err) {
// satisfy linter
}
}
return version.split(',');
};
/**
* only use for non-iframe embeds.
*
* @param {object} swf
* the videojs-swf object.
*
* @param {object} flashvars
* names and values to use as flash option variables.
*
* @param {object} params
* style parameters to set on the object.
*
* @param {object} attributes
* attributes to set on the element.
*
* @return {element}
* the embeded flash dom element.
*/
flash.embed = function (swf, flashvars, params, attributes) {
var code = flash.getembedcode(swf, flashvars, params, attributes);
// get element by embedding code and retrieving created element
var obj = dom.createel('div', { innerhtml: code }).childnodes[0];
return obj;
};
/**
* only use for non-iframe embeds.
*
* @param {object} swf
* the videojs-swf object.
*
* @param {object} flashvars
* names and values to use as flash option variables.
*
* @param {object} params
* style parameters to set on the object.
*
* @param {object} attributes
* attributes to set on the element.
*
* @return {element}
* the embeded flash dom element.
*/
flash.getembedcode = function (swf, flashvars, params, attributes) {
var objtag = '';
});
attributes = (0, _obj.assign)({
// add swf to attributes (need both for ie and others to work)
data: swf,
// default to 100% width/height
width: '100%',
height: '100%'
}, attributes);
// create attributes string
object.getownpropertynames(attributes).foreach(function (key) {
attrsstring += key + '="' + attributes[key] + '" ';
});
return '' + objtag + attrsstring + '>' + paramsstring + '';
};
// run flash through the rtmp decorator
(0, _flashrtmp2['default'])(flash);
_component2['default'].registercomponent('flash', flash);
_tech2['default'].registertech('flash', flash);
exports['default'] = flash;
},{"5":5,"58":58,"62":62,"81":81,"88":88,"90":90,"92":92,"95":95}],60:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
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.']);
var _tech = _dereq_(62);
var _tech2 = _interoprequiredefault(_tech);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var dom = _interoprequirewildcard(_dom);
var _url = _dereq_(92);
var url = _interoprequirewildcard(_url);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _log = _dereq_(86);
var _log2 = _interoprequiredefault(_log);
var _tsml = _dereq_(98);
var _tsml2 = _interoprequiredefault(_tsml);
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
var _obj = _dereq_(88);
var _mergeoptions = _dereq_(87);
var _mergeoptions2 = _interoprequiredefault(_mergeoptions);
var _totitlecase = _dereq_(91);
var _totitlecase2 = _interoprequiredefault(_totitlecase);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _taggedtemplateliteralloose(strings, raw) { strings.raw = raw; return strings; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file html5.js
*/
/**
* html5 media controller - wrapper for html5 media api
*
* @mixes tech~soucehandleradditions
* @extends tech
*/
var html5 = function (_tech) {
_inherits(html5, _tech);
/**
* create an instance of this tech.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} ready
* callback function to call when the `html5` tech is ready.
*/
function html5(options, ready) {
_classcallcheck(this, html5);
var _this = _possibleconstructorreturn(this, _tech.call(this, options, ready));
var source = options.source;
var crossorigintracks = false;
// set the source if one is provided
// 1) check if the source is new (if not, we want to keep the original so playback isn't interrupted)
// 2) check to see if the network state of the tag was failed at init, and if so, reset the source
// anyway so the error gets fired.
if (source && (_this.el_.currentsrc !== source.src || options.tag && options.tag.initnetworkstate_ === 3)) {
_this.setsource(source);
} else {
_this.handlelateinit_(_this.el_);
}
if (_this.el_.haschildnodes()) {
var nodes = _this.el_.childnodes;
var nodeslength = nodes.length;
var removenodes = [];
while (nodeslength--) {
var node = nodes[nodeslength];
var nodename = node.nodename.tolowercase();
if (nodename === 'track') {
if (!_this.featuresnativetexttracks) {
// empty video tag tracks so the built-in player doesn't use them also.
// this may not be fast enough to stop html5 browsers from reading the tags
// so we'll need to turn off any default tracks if we're manually doing
// captions and subtitles. videoelement.texttracks
removenodes.push(node);
} else {
// store htmltrackelement and texttrack to remote list
_this.remotetexttrackels().addtrackelement_(node);
_this.remotetexttracks().addtrack_(node.track);
if (!crossorigintracks && !_this.el_.hasattribute('crossorigin') && url.iscrossorigin(node.src)) {
crossorigintracks = true;
}
}
}
}
for (var i = 0; i < removenodes.length; i++) {
_this.el_.removechild(removenodes[i]);
}
}
// todo: add text tracks into this list
var tracktypes = ['audio', 'video'];
// proxynative video/audio track
tracktypes.foreach(function (type) {
var eltracks = _this.el()[type + 'tracks'];
var techtracks = _this[type + 'tracks']();
var capitaltype = (0, _totitlecase2['default'])(type);
if (!_this['featuresnative' + capitaltype + 'tracks'] || !eltracks || !eltracks.addeventlistener) {
return;
}
_this['handle' + capitaltype + 'trackchange_'] = function (e) {
techtracks.trigger({
type: 'change',
target: techtracks,
currenttarget: techtracks,
srcelement: techtracks
});
};
_this['handle' + capitaltype + 'trackadd_'] = function (e) {
return techtracks.addtrack(e.track);
};
_this['handle' + capitaltype + 'trackremove_'] = function (e) {
return techtracks.removetrack(e.track);
};
eltracks.addeventlistener('change', _this['handle' + capitaltype + 'trackchange_']);
eltracks.addeventlistener('addtrack', _this['handle' + capitaltype + 'trackadd_']);
eltracks.addeventlistener('removetrack', _this['handle' + capitaltype + 'trackremove_']);
_this['removeold' + capitaltype + 'tracks_'] = function (e) {
return _this.removeoldtracks_(techtracks, eltracks);
};
// remove (native) tracks that are not used anymore
_this.on('loadstart', _this['removeold' + capitaltype + 'tracks_']);
});
if (_this.featuresnativetexttracks) {
if (crossorigintracks) {
_log2['default'].warn((0, _tsml2['default'])(_templateobject));
}
_this.handletexttrackchange_ = fn.bind(_this, _this.handletexttrackchange);
_this.handletexttrackadd_ = fn.bind(_this, _this.handletexttrackadd);
_this.handletexttrackremove_ = fn.bind(_this, _this.handletexttrackremove);
_this.proxynativetexttracks_();
}
// determine if native controls should be used
// our goal should be to get the custom controls on mobile solid everywhere
// so we can remove this all together. right now this will block custom
// controls on touch enabled laptops like the chrome pixel
if ((browser.touch_enabled || browser.is_iphone || browser.is_native_android) && options.nativecontrolsfortouch === true) {
_this.setcontrols(true);
}
// on ios, we want to proxy `webkitbeginfullscreen` and `webkitendfullscreen`
// into a `fullscreenchange` event
_this.proxywebkitfullscreen_();
_this.triggerready();
return _this;
}
/**
* dispose of `html5` media element and remove all tracks.
*/
html5.prototype.dispose = function dispose() {
var _this2 = this;
// un-proxynativetracks
['audio', 'video', 'text'].foreach(function (type) {
var capitaltype = (0, _totitlecase2['default'])(type);
var tl = _this2.el_[type + 'tracks'];
if (tl && tl.removeeventlistener) {
tl.removeeventlistener('change', _this2['handle' + capitaltype + 'trackchange_']);
tl.removeeventlistener('addtrack', _this2['handle' + capitaltype + 'trackadd_']);
tl.removeeventlistener('removetrack', _this2['handle' + capitaltype + 'trackremove_']);
}
// stop removing old text tracks
if (tl) {
_this2.off('loadstart', _this2['removeold' + capitaltype + 'tracks_']);
}
});
html5.disposemediaelement(this.el_);
// tech will handle clearing of the emulated track list
_tech.prototype.dispose.call(this);
};
/**
* create the `html5` tech's dom element.
*
* @return {element}
* the element that gets created.
*/
html5.prototype.createel = function createel() {
var el = this.options_.tag;
// check if this browser supports moving the element into the box.
// on the iphone video will break if you move the element,
// so we have to create a brand new element.
// if we ingested the player div, we do not need to move the media element.
if (!el || !(this.options_.playerelingest || this.movingmediaelementindom)) {
// if the original tag is still there, clone and remove it.
if (el) {
var clone = el.clonenode(true);
if (el.parentnode) {
el.parentnode.insertbefore(clone, el);
}
html5.disposemediaelement(el);
el = clone;
} else {
el = _document2['default'].createelement('video');
// determine if native controls should be used
var tagattributes = this.options_.tag && dom.getelattributes(this.options_.tag);
var attributes = (0, _mergeoptions2['default'])({}, tagattributes);
if (!browser.touch_enabled || this.options_.nativecontrolsfortouch !== true) {
delete attributes.controls;
}
dom.setelattributes(el, (0, _obj.assign)(attributes, {
id: this.options_.techid,
'class': 'vjs-tech'
}));
}
el.playerid = this.options_.playerid;
}
// update specific tag settings, in case they were overridden
var settingsattrs = ['autoplay', 'preload', 'loop', 'muted'];
for (var i = settingsattrs.length - 1; i >= 0; i--) {
var attr = settingsattrs[i];
var overwriteattrs = {};
if (typeof this.options_[attr] !== 'undefined') {
overwriteattrs[attr] = this.options_[attr];
}
dom.setelattributes(el, overwriteattrs);
}
return el;
};
/**
* this will be triggered if the loadstart event has already fired, before videojs was
* ready. two known examples of when this can happen are:
* 1. if we're loading the playback object after it has started loading
* 2. the media is already playing the (often with autoplay on) then
*
* this function will fire another loadstart so that videojs can catchup.
*
* @fires tech#loadstart
*
* @return {undefined}
* returns nothing.
*/
html5.prototype.handlelateinit_ = function handlelateinit_(el) {
if (el.networkstate === 0 || el.networkstate === 3) {
// the video element hasn't started loading the source yet
// or didn't find a source
return;
}
if (el.readystate === 0) {
// networkstate is set synchronously but loadstart is fired at the
// end of the current stack, usually before setinterval(fn, 0).
// so at this point we know loadstart may have already fired or is
// about to fire, and either way the player hasn't seen it yet.
// we don't want to fire loadstart prematurely here and cause a
// double loadstart so we'll wait and see if it happens between now
// and the next loop, and fire it if not.
// however, we also want to make sure it fires before loadedmetadata
// which could also happen between now and the next loop, so we'll
// watch for that also.
var loadstartfired = false;
var setloadstartfired = function setloadstartfired() {
loadstartfired = true;
};
this.on('loadstart', setloadstartfired);
var triggerloadstart = function triggerloadstart() {
// we did miss the original loadstart. make sure the player
// sees loadstart before loadedmetadata
if (!loadstartfired) {
this.trigger('loadstart');
}
};
this.on('loadedmetadata', triggerloadstart);
this.ready(function () {
this.off('loadstart', setloadstartfired);
this.off('loadedmetadata', triggerloadstart);
if (!loadstartfired) {
// we did miss the original native loadstart. fire it now.
this.trigger('loadstart');
}
});
return;
}
// from here on we know that loadstart already fired and we missed it.
// the other readystate events aren't as much of a problem if we double
// them, so not going to go to as much trouble as loadstart to prevent
// that unless we find reason to.
var eventstotrigger = ['loadstart'];
// loadedmetadata: newly equal to have_metadata (1) or greater
eventstotrigger.push('loadedmetadata');
// loadeddata: newly increased to have_current_data (2) or greater
if (el.readystate >= 2) {
eventstotrigger.push('loadeddata');
}
// canplay: newly increased to have_future_data (3) or greater
if (el.readystate >= 3) {
eventstotrigger.push('canplay');
}
// canplaythrough: newly equal to have_enough_data (4)
if (el.readystate >= 4) {
eventstotrigger.push('canplaythrough');
}
// we still need to give the player time to add event listeners
this.ready(function () {
eventstotrigger.foreach(function (type) {
this.trigger(type);
}, this);
});
};
/**
* add event listeners to native text track events. this adds the native text tracks
* to our emulated {@link texttracklist}.
*/
html5.prototype.proxynativetexttracks_ = function proxynativetexttracks_() {
var tt = this.el().texttracks;
if (tt) {
// add tracks - if player is initialised after dom loaded, texttracks
// will not trigger addtrack
for (var i = 0; i < tt.length; i++) {
this.texttracks().addtrack_(tt[i]);
}
if (tt.addeventlistener) {
tt.addeventlistener('change', this.handletexttrackchange_);
tt.addeventlistener('addtrack', this.handletexttrackadd_);
tt.addeventlistener('removetrack', this.handletexttrackremove_);
}
// remove (native) texttracks that are not used anymore
this.on('loadstart', this.removeoldtexttracks_);
}
};
/**
* handle any {@link texttracklist} `change` event.
*
* @param {eventtarget~event} e
* the `change` event that caused this to run.
*
* @listens texttracklist#change
*/
html5.prototype.handletexttrackchange = function handletexttrackchange(e) {
var tt = this.texttracks();
this.texttracks().trigger({
type: 'change',
target: tt,
currenttarget: tt,
srcelement: tt
});
};
/**
* handle any {@link texttracklist} `addtrack` event.
*
* @param {eventtarget~event} e
* the `addtrack` event that caused this to run.
*
* @listens texttracklist#addtrack
*/
html5.prototype.handletexttrackadd = function handletexttrackadd(e) {
this.texttracks().addtrack_(e.track);
};
/**
* handle any {@link texttracklist} `removetrack` event.
*
* @param {eventtarget~event} e
* the `removetrack` event that caused this to run.
*
* @listens texttracklist#removetrack
*/
html5.prototype.handletexttrackremove = function handletexttrackremove(e) {
this.texttracks().removetrack_(e.track);
};
/**
* this function removes any {@link audiotrack}s, {@link videotrack}s, or
* {@link texttrack}s that are not in the media elements tracklist.
*
* @param {tracklist} techtracks
* html5 tech's tracklist to search through
*
* @param {tracklist} eltracks
* html5 media elements tracklist to search trough.
*
* @private
*/
html5.prototype.removeoldtracks_ = function removeoldtracks_(techtracks, eltracks) {
// this will loop over the techtracks and check if they are still used by the html5 media element
// if not, they will be removed from the emulated list
var removetracks = [];
if (!eltracks) {
return;
}
for (var i = 0; i < techtracks.length; i++) {
var techtrack = techtracks[i];
var found = false;
for (var j = 0; j < eltracks.length; j++) {
if (eltracks[j] === techtrack) {
found = true;
break;
}
}
if (!found) {
removetracks.push(techtrack);
}
}
for (var _i = 0; _i < removetracks.length; _i++) {
var track = removetracks[_i];
techtracks.removetrack_(track);
}
};
/**
* remove {@link texttrack}s that dont exist in the native track list from our
* emulated {@link texttracklist}.
*
* @listens tech#loadstart
*/
html5.prototype.removeoldtexttracks_ = function removeoldtexttracks_(e) {
var techtracks = this.texttracks();
var eltracks = this.el().texttracks;
this.removeoldtracks_(techtracks, eltracks);
};
/**
* called by {@link player#play} to play using the `html5` `tech`.
*/
html5.prototype.play = function play() {
var playpromise = this.el_.play();
// catch/silence error when a pause interrupts a play request
// on browsers which return a promise
if (playpromise !== undefined && typeof playpromise.then === 'function') {
playpromise.then(null, function (e) {});
}
};
/**
* set current time for the `html5` tech.
*
* @param {number} seconds
* set the current time of the media to this.
*/
html5.prototype.setcurrenttime = function setcurrenttime(seconds) {
try {
this.el_.currenttime = seconds;
} catch (e) {
(0, _log2['default'])(e, 'video is not ready. (video.js)');
// this.warning(videojs.warnings.videonotready);
}
};
/**
* get the current duration of the html5 media element.
*
* @return {number}
* the duration of the media or 0 if there is no duration.
*/
html5.prototype.duration = function duration() {
var _this3 = this;
// android chrome will report duration as infinity for vod hls until after
// playback has started, which triggers the live display erroneously.
// return nan if playback has not started and trigger a durationupdate once
// the duration can be reliably known.
if (this.el_.duration === infinity && browser.is_android && browser.is_chrome) {
if (this.el_.currenttime === 0) {
// wait for the first `timeupdate` with currenttime > 0 - there may be
// several with 0
var checkprogress = function checkprogress() {
if (_this3.el_.currenttime > 0) {
// trigger durationchange for genuinely live video
if (_this3.el_.duration === infinity) {
_this3.trigger('durationchange');
}
_this3.off('timeupdate', checkprogress);
}
};
this.on('timeupdate', checkprogress);
return nan;
}
}
return this.el_.duration || nan;
};
/**
* get the current width of the html5 media element.
*
* @return {number}
* the width of the html5 media element.
*/
html5.prototype.width = function width() {
return this.el_.offsetwidth;
};
/**
* get the current height of the html5 media element.
*
* @return {number}
* the heigth of the html5 media element.
*/
html5.prototype.height = function height() {
return this.el_.offsetheight;
};
/**
* proxy ios `webkitbeginfullscreen` and `webkitendfullscreen` into
* `fullscreenchange` event.
*
* @private
* @fires fullscreenchange
* @listens webkitendfullscreen
* @listens webkitbeginfullscreen
* @listens webkitbeginfullscreen
*/
html5.prototype.proxywebkitfullscreen_ = function proxywebkitfullscreen_() {
var _this4 = this;
if (!('webkitdisplayingfullscreen' in this.el_)) {
return;
}
var endfn = function endfn() {
this.trigger('fullscreenchange', { isfullscreen: false });
};
var beginfn = function beginfn() {
this.one('webkitendfullscreen', endfn);
this.trigger('fullscreenchange', { isfullscreen: true });
};
this.on('webkitbeginfullscreen', beginfn);
this.on('dispose', function () {
_this4.off('webkitbeginfullscreen', beginfn);
_this4.off('webkitendfullscreen', endfn);
});
};
/**
* check if fullscreen is supported on the current playback device.
*
* @return {boolean}
* - true if fullscreen is supported.
* - false if fullscreen is not supported.
*/
html5.prototype.supportsfullscreen = function supportsfullscreen() {
if (typeof this.el_.webkitenterfullscreen === 'function') {
var useragent = _window2['default'].navigator && _window2['default'].navigator.useragent || '';
// seems to be broken in chromium/chrome && safari in leopard
if (/android/.test(useragent) || !/chrome|mac os x 10.5/.test(useragent)) {
return true;
}
}
return false;
};
/**
* request that the `html5` tech enter fullscreen.
*/
html5.prototype.enterfullscreen = function enterfullscreen() {
var video = this.el_;
if (video.paused && video.networkstate <= video.have_metadata) {
// attempt to prime the video element for programmatic access
// this isn't necessary on the desktop but shouldn't hurt
this.el_.play();
// playing and pausing synchronously during the transition to fullscreen
// can get ios ~6.1 devices into a play/pause loop
this.settimeout(function () {
video.pause();
video.webkitenterfullscreen();
}, 0);
} else {
video.webkitenterfullscreen();
}
};
/**
* request that the `html5` tech exit fullscreen.
*/
html5.prototype.exitfullscreen = function exitfullscreen() {
this.el_.webkitexitfullscreen();
};
/**
* a getter/setter for the `html5` tech's source object.
* > note: please use {@link html5#setsource}
*
* @param {tech~sourceobject} [src]
* the source object you want to set on the `html5` techs element.
*
* @return {tech~sourceobject|undefined}
* - the current source object when a source is not passed in.
* - undefined when setting
*
* @deprecated since version 5.
*/
html5.prototype.src = function src(_src) {
if (_src === undefined) {
return this.el_.src;
}
// setting src through `src` instead of `setsrc` will be deprecated
this.setsrc(_src);
};
/**
* reset the tech by removing all sources and then calling
* {@link html5.resetmediaelement}.
*/
html5.prototype.reset = function reset() {
html5.resetmediaelement(this.el_);
};
/**
* get the current source on the `html5` tech. falls back to returning the source from
* the html5 media element.
*
* @return {tech~sourceobject}
* the current source object from the html5 tech. with a fallback to the
* elements source.
*/
html5.prototype.currentsrc = function currentsrc() {
if (this.currentsource_) {
return this.currentsource_.src;
}
return this.el_.currentsrc;
};
/**
* set controls attribute for the html5 media element.
*
* @param {string} val
* value to set the controls attribute to
*/
html5.prototype.setcontrols = function setcontrols(val) {
this.el_.controls = !!val;
};
/**
* create and returns a remote {@link texttrack} object.
*
* @param {string} kind
* `texttrack` kind (subtitles, captions, descriptions, chapters, or metadata)
*
* @param {string} [label]
* label to identify the text track
*
* @param {string} [language]
* two letter language abbreviation
*
* @return {texttrack}
* the texttrack that gets created.
*/
html5.prototype.addtexttrack = function addtexttrack(kind, label, language) {
if (!this.featuresnativetexttracks) {
return _tech.prototype.addtexttrack.call(this, kind, label, language);
}
return this.el_.addtexttrack(kind, label, language);
};
/**
* creates either native texttrack or an emulated texttrack depending
* on the value of `featuresnativetexttracks`
*
* @param {object} options
* the object should contain the options to intialize the texttrack with.
*
* @param {string} [options.kind]
* `texttrack` kind (subtitles, captions, descriptions, chapters, or metadata).
*
* @param {string} [options.label].
* label to identify the text track
*
* @param {string} [options.language]
* two letter language abbreviation.
*
* @param {boolean} [options.default]
* default this track to on.
*
* @param {string} [options.id]
* the internal id to assign this track.
*
* @param {string} [options.src]
* a source url for the track.
*
* @return {htmltrackelement}
* the track element that gets created.
*/
html5.prototype.createremotetexttrack = function createremotetexttrack(options) {
if (!this.featuresnativetexttracks) {
return _tech.prototype.createremotetexttrack.call(this, options);
}
var htmltrackelement = _document2['default'].createelement('track');
if (options.kind) {
htmltrackelement.kind = options.kind;
}
if (options.label) {
htmltrackelement.label = options.label;
}
if (options.language || options.srclang) {
htmltrackelement.srclang = options.language || options.srclang;
}
if (options['default']) {
htmltrackelement['default'] = options['default'];
}
if (options.id) {
htmltrackelement.id = options.id;
}
if (options.src) {
htmltrackelement.src = options.src;
}
return htmltrackelement;
};
/**
* creates a remote text track object and returns an html track element.
*
* @param {object} options the object should contain values for
* kind, language, label, and src (location of the webvtt file)
* @param {boolean} [manualcleanup=true] if set to false, the texttrack will be
* automatically removed from the video element whenever the source changes
* @return {htmltrackelement} an html track element.
* this can be an emulated {@link htmltrackelement} or a native one.
* @deprecated the default value of the "manualcleanup" parameter will default
* to "false" in upcoming versions of video.js
*/
html5.prototype.addremotetexttrack = function addremotetexttrack(options, manualcleanup) {
var htmltrackelement = _tech.prototype.addremotetexttrack.call(this, options, manualcleanup);
if (this.featuresnativetexttracks) {
this.el().appendchild(htmltrackelement);
}
return htmltrackelement;
};
/**
* remove remote `texttrack` from `texttracklist` object
*
* @param {texttrack} track
* `texttrack` object to remove
*/
html5.prototype.removeremotetexttrack = function removeremotetexttrack(track) {
_tech.prototype.removeremotetexttrack.call(this, track);
if (this.featuresnativetexttracks) {
var tracks = this.$$('track');
var i = tracks.length;
while (i--) {
if (track === tracks[i] || track === tracks[i].track) {
this.el().removechild(tracks[i]);
}
}
}
};
return html5;
}(_tech2['default']);
/* html5 support testing ---------------------------------------------------- */
if (dom.isreal()) {
/**
* element for testing browser html5 media capabilities
*
* @type {element}
* @constant
* @private
*/
html5.test_vid = _document2['default'].createelement('video');
var track = _document2['default'].createelement('track');
track.kind = 'captions';
track.srclang = 'en';
track.label = 'english';
html5.test_vid.appendchild(track);
}
/**
* check if html5 media is supported by this browser/device.
*
* @return {boolean}
* - true if html5 media is supported.
* - false if html5 media is not supported.
*/
html5.issupported = function () {
// ie9 with no media player is a liar! (#984)
try {
html5.test_vid.volume = 0.5;
} catch (e) {
return false;
}
return !!(html5.test_vid && html5.test_vid.canplaytype);
};
/**
* check if the volume can be changed in this browser/device.
* volume cannot be changed in a lot of mobile devices.
* specifically, it can't be changed from 1 on ios.
*
* @return {boolean}
* - true if volume can be controlled
* - false otherwise
*/
html5.cancontrolvolume = function () {
// ie will error if windows media player not installed #3315
try {
var volume = html5.test_vid.volume;
html5.test_vid.volume = volume / 2 + 0.1;
return volume !== html5.test_vid.volume;
} catch (e) {
return false;
}
};
/**
* check if the playback rate can be changed in this browser/device.
*
* @return {boolean}
* - true if playback rate can be controlled
* - false otherwise
*/
html5.cancontrolplaybackrate = function () {
// playback rate api is implemented in android chrome, but doesn't do anything
// https://github.com/videojs/video.js/issues/3180
if (browser.is_android && browser.is_chrome) {
return false;
}
// ie will error if windows media player not installed #3315
try {
var playbackrate = html5.test_vid.playbackrate;
html5.test_vid.playbackrate = playbackrate / 2 + 0.1;
return playbackrate !== html5.test_vid.playbackrate;
} catch (e) {
return false;
}
};
/**
* check to see if native `texttrack`s are supported by this browser/device.
*
* @return {boolean}
* - true if native `texttrack`s are supported.
* - false otherwise
*/
html5.supportsnativetexttracks = function () {
return browser.is_any_safari;
};
/**
* check to see if native `videotrack`s are supported by this browser/device
*
* @return {boolean}
* - true if native `videotrack`s are supported.
* - false otherwise
*/
html5.supportsnativevideotracks = function () {
return !!(html5.test_vid && html5.test_vid.videotracks);
};
/**
* check to see if native `audiotrack`s are supported by this browser/device
*
* @return {boolean}
* - true if native `audiotrack`s are supported.
* - false otherwise
*/
html5.supportsnativeaudiotracks = function () {
return !!(html5.test_vid && html5.test_vid.audiotracks);
};
/**
* an array of events available on the html5 tech.
*
* @private
* @type {array}
*/
html5.events = ['loadstart', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'seeking', 'seeked', 'ended', 'durationchange', 'timeupdate', 'progress', 'play', 'pause', 'ratechange', 'volumechange'];
/**
* boolean indicating whether the `tech` supports volume control.
*
* @type {boolean}
* @default {@link html5.cancontrolvolume}
*/
html5.prototype.featuresvolumecontrol = html5.cancontrolvolume();
/**
* boolean indicating whether the `tech` supports changing the speed at which the media
* plays. examples:
* - set player to play 2x (twice) as fast
* - set player to play 0.5x (half) as fast
*
* @type {boolean}
* @default {@link html5.cancontrolplaybackrate}
*/
html5.prototype.featuresplaybackrate = html5.cancontrolplaybackrate();
/**
* boolean indicating whether the `html5` tech currently supports the media element
* moving in the dom. ios breaks if you move the media element, so this is set this to
* false there. everywhere else this should be true.
*
* @type {boolean}
* @default
*/
html5.prototype.movingmediaelementindom = !browser.is_ios;
// todo: previous comment: no longer appears to be used. can probably be removed.
// is this true?
/**
* boolean indicating whether the `html5` tech currently supports automatic media resize
* when going into fullscreen.
*
* @type {boolean}
* @default
*/
html5.prototype.featuresfullscreenresize = true;
/**
* boolean indicating whether the `html5` tech currently supports the progress event.
* if this is false, manual `progress` events will be triggred instead.
*
* @type {boolean}
* @default
*/
html5.prototype.featuresprogressevents = true;
/**
* boolean indicating whether the `html5` tech currently supports the timeupdate event.
* if this is false, manual `timeupdate` events will be triggred instead.
*
* @default
*/
html5.prototype.featurestimeupdateevents = true;
/**
* boolean indicating whether the `html5` tech currently supports native `texttrack`s.
*
* @type {boolean}
* @default {@link html5.supportsnativetexttracks}
*/
html5.prototype.featuresnativetexttracks = html5.supportsnativetexttracks();
/**
* boolean indicating whether the `html5` tech currently supports native `videotrack`s.
*
* @type {boolean}
* @default {@link html5.supportsnativevideotracks}
*/
html5.prototype.featuresnativevideotracks = html5.supportsnativevideotracks();
/**
* boolean indicating whether the `html5` tech currently supports native `audiotrack`s.
*
* @type {boolean}
* @default {@link html5.supportsnativeaudiotracks}
*/
html5.prototype.featuresnativeaudiotracks = html5.supportsnativeaudiotracks();
// html5 feature detection and device fixes --------------------------------- //
var canplaytype = html5.test_vid && html5.test_vid.constructor.prototype.canplaytype;
var mpegurlre = /^application\/(?:x-|vnd\.apple\.)mpegurl/i;
var mp4re = /^video\/mp4/i;
html5.patchcanplaytype = function () {
// android 4.0 and above can play hls to some extent but it reports being unable to do so
if (browser.android_version >= 4.0 && !browser.is_firefox) {
html5.test_vid.constructor.prototype.canplaytype = function (type) {
if (type && mpegurlre.test(type)) {
return 'maybe';
}
return canplaytype.call(this, type);
};
// override android 2.2 and less canplaytype method which is broken
} else if (browser.is_old_android) {
html5.test_vid.constructor.prototype.canplaytype = function (type) {
if (type && mp4re.test(type)) {
return 'maybe';
}
return canplaytype.call(this, type);
};
}
};
html5.unpatchcanplaytype = function () {
var r = html5.test_vid.constructor.prototype.canplaytype;
html5.test_vid.constructor.prototype.canplaytype = canplaytype;
return r;
};
// by default, patch the media element
html5.patchcanplaytype();
html5.disposemediaelement = function (el) {
if (!el) {
return;
}
if (el.parentnode) {
el.parentnode.removechild(el);
}
// remove any child track or source nodes to prevent their loading
while (el.haschildnodes()) {
el.removechild(el.firstchild);
}
// remove any src reference. not setting `src=''` because that causes a warning
// in firefox
el.removeattribute('src');
// force the media element to update its loading state by calling load()
// however ie on windows 7n has a bug that throws an error so need a try/catch (#793)
if (typeof el.load === 'function') {
// wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
(function () {
try {
el.load();
} catch (e) {
// not supported
}
})();
}
};
html5.resetmediaelement = function (el) {
if (!el) {
return;
}
var sources = el.queryselectorall('source');
var i = sources.length;
while (i--) {
el.removechild(sources[i]);
}
// remove any src reference.
// not setting `src=''` because that throws an error
el.removeattribute('src');
if (typeof el.load === 'function') {
// wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473)
(function () {
try {
el.load();
} catch (e) {
// satisfy linter
}
})();
}
};
/* native html5 element property wrapping ----------------------------------- */
// wrap native properties with a getter
[
/**
* get the value of `paused` from the media element. `paused` indicates whether the media element
* is currently paused or not.
*
* @method html5#paused
* @return {boolean}
* the value of `paused` from the media element.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-paused}
*/
'paused',
/**
* get the value of `currenttime` from the media element. `currenttime` indicates
* the current second that the media is at in playback.
*
* @method html5#currenttime
* @return {number}
* the value of `currenttime` from the media element.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-currenttime}
*/
'currenttime',
/**
* get the value of `buffered` from the media element. `buffered` is a `timerange`
* object that represents the parts of the media that are already downloaded and
* available for playback.
*
* @method html5#buffered
* @return {timerange}
* the value of `buffered` from the media element.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-buffered}
*/
'buffered',
/**
* get the value of `volume` from the media element. `volume` indicates
* the current playback volume of audio for a media. `volume` will be a value from 0
* (silent) to 1 (loudest and default).
*
* @method html5#volume
* @return {number}
* the value of `volume` from the media element. value will be between 0-1.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-a-volume}
*/
'volume',
/**
* get the value of `muted` from the media element. `muted` indicates
* that the volume for the media should be set to silent. this does not actually change
* the `volume` attribute.
*
* @method html5#muted
* @return {boolean}
* - true if the value of `volume` should be ignored and the audio set to silent.
* - false if the value of `volume` should be used.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-muted}
*/
'muted',
/**
* get the value of `poster` from the media element. `poster` indicates
* that the url of an image file that can/will be shown when no media data is available.
*
* @method html5#poster
* @return {string}
* the value of `poster` from the media element. value will be a url to an
* image.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-video-poster}
*/
'poster',
/**
* get the value of `preload` from the media element. `preload` indicates
* what should download before the media is interacted with. it can have the following
* values:
* - none: nothing should be downloaded
* - metadata: poster and the first few frames of the media may be downloaded to get
* media dimensions and other metadata
* - auto: allow the media and metadata for the media to be downloaded before
* interaction
*
* @method html5#preload
* @return {string}
* the value of `preload` from the media element. will be 'none', 'metadata',
* or 'auto'.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-preload}
*/
'preload',
/**
* get the value of `autoplay` from the media element. `autoplay` indicates
* that the media should start to play as soon as the page is ready.
*
* @method html5#autoplay
* @return {boolean}
* - the value of `autoplay` from the media element.
* - true indicates that the media should start as soon as the page loads.
* - false indicates that the media should not start as soon as the page loads.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-autoplay}
*/
'autoplay',
/**
* get the value of `controls` from the media element. `controls` indicates
* whether the native media controls should be shown or hidden.
*
* @method html5#controls
* @return {boolean}
* - the value of `controls` from the media element.
* - true indicates that native controls should be showing.
* - false indicates that native controls should be hidden.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-controls}
*/
'controls',
/**
* get the value of `loop` from the media element. `loop` indicates
* that the media should return to the start of the media and continue playing once
* it reaches the end.
*
* @method html5#loop
* @return {boolean}
* - the value of `loop` from the media element.
* - true indicates that playback should seek back to start once
* the end of a media is reached.
* - false indicates that playback should not loop back to the start when the
* end of the media is reached.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-loop}
*/
'loop',
/**
* get the value of the `error` from the media element. `error` indicates any
* mediaerror that may have occured during playback. if error returns null there is no
* current error.
*
* @method html5#error
* @return {mediaerror|null}
* the value of `error` from the media element. will be `mediaerror` if there
* is a current error and null otherwise.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-error}
*/
'error',
/**
* get the value of `seeking` from the media element. `seeking` indicates whether the
* media is currently seeking to a new position or not.
*
* @method html5#seeking
* @return {boolean}
* - the value of `seeking` from the media element.
* - true indicates that the media is currently seeking to a new position.
* - flase indicates that the media is not seeking to a new position at this time.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-seeking}
*/
'seeking',
/**
* get the value of `seekable` from the media element. `seekable` returns a
* `timerange` object indicating ranges of time that can currently be `seeked` to.
*
* @method html5#seekable
* @return {timerange}
* the value of `seekable` from the media element. a `timerange` object
* indicating the current ranges of time that can be seeked to.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-seekable}
*/
'seekable',
/**
* get the value of `ended` from the media element. `ended` indicates whether
* the media has reached the end or not.
*
* @method html5#ended
* @return {boolean}
* - the value of `ended` from the media element.
* - true indicates that the media has ended.
* - false indicates that the media has not ended.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-ended}
*/
'ended',
/**
* get the value of `defaultmuted` from the media element. `defaultmuted` indicates
* whether the media should start muted or not. only changes the default state of the
* media. `muted` and `defaultmuted` can have different values. `muted` indicates the
* current state.
*
* @method html5#defaultmuted
* @return {boolean}
* - the value of `defaultmuted` from the media element.
* - true indicates that the media should start muted.
* - false indicates that the media should not start muted
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-defaultmuted}
*/
'defaultmuted',
/**
* get the value of `playbackrate` from the media element. `playbackrate` indicates
* the rate at which the media is currently playing back. examples:
* - if playbackrate is set to 2, media will play twice as fast.
* - if playbackrate is set to 0.5, media will play half as fast.
*
* @method html5#playbackrate
* @return {number}
* the value of `playbackrate` from the media element. a number indicating
* the current playback speed of the media, where 1 is normal speed.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-playbackrate}
*/
'playbackrate',
/**
* get the value of `played` from the media element. `played` returns a `timerange`
* object representing points in the media timeline that have been played.
*
* @method html5#played
* @return {timerange}
* the value of `played` from the media element. a `timerange` object indicating
* the ranges of time that have been played.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-played}
*/
'played',
/**
* get the value of `networkstate` from the media element. `networkstate` indicates
* the current network state. it returns an enumeration from the following list:
* - 0: network_empty
* - 1: nework_idle
* - 2: network_loading
* - 3: network_no_source
*
* @method html5#networkstate
* @return {number}
* the value of `networkstate` from the media element. this will be a number
* from the list in the description.
*
* @see [spec] {@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-networkstate}
*/
'networkstate',
/**
* get the value of `readystate` from the media element. `readystate` indicates
* the current state of the media element. it returns an enumeration from the
* following list:
* - 0: have_nothing
* - 1: have_metadata
* - 2: have_current_data
* - 3: have_future_data
* - 4: have_enough_data
*
* @method html5#readystate
* @return {number}
* the value of `readystate` from the media element. this will be a number
* from the list in the description.
*
* @see [spec] {@link https://www.w3.org/tr/html5/embedded-content-0.html#ready-states}
*/
'readystate',
/**
* get the value of `videowidth` from the video element. `videowidth` indicates
* the current width of the video in css pixels.
*
* @method html5#videowidth
* @return {number}
* the value of `videowidth` from the video element. this will be a number
* in css pixels.
*
* @see [spec] {@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-video-videowidth}
*/
'videowidth',
/**
* get the value of `videoheight` from the video element. `videoheigth` indicates
* the current height of the video in css pixels.
*
* @method html5#videoheight
* @return {number}
* the value of `videoheight` from the video element. this will be a number
* in css pixels.
*
* @see [spec] {@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-video-videowidth}
*/
'videoheight'].foreach(function (prop) {
html5.prototype[prop] = function () {
return this.el_[prop];
};
});
// wrap native properties with a setter in this format:
// set + totitlecase(name)
[
/**
* set the value of `volume` on the media element. `volume` indicates the current
* audio level as a percentage in decimal form. this means that 1 is 100%, 0.5 is 50%, and
* so on.
*
* @method html5#setvolume
* @param {number} percentasdecimal
* the volume percent as a decimal. valid range is from 0-1.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-a-volume}
*/
'volume',
/**
* set the value of `muted` on the media element. `muted` indicates the current
* audio level should be silent.
*
* @method html5#setmuted
* @param {boolean} muted
* - true if the audio should be set to silent
* - false otherwise
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-muted}
*/
'muted',
/**
* set the value of `src` on the media element. `src` indicates the current
* {@link tech~sourceobject} for the media.
*
* @method html5#setsrc
* @param {tech~sourceobject} src
* the source object to set as the current source.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-src}
*/
'src',
/**
* set the value of `poster` on the media element. `poster` is the url to
* an image file that can/will be shown when no media data is available.
*
* @method html5#setposter
* @param {string} poster
* the url to an image that should be used as the `poster` for the media
* element.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-poster}
*/
'poster',
/**
* set the value of `preload` on the media element. `preload` indicates
* what should download before the media is interacted with. it can have the following
* values:
* - none: nothing should be downloaded
* - metadata: poster and the first few frames of the media may be downloaded to get
* media dimensions and other metadata
* - auto: allow the media and metadata for the media to be downloaded before
* interaction
*
* @method html5#setpreload
* @param {string} preload
* the value of `preload` to set on the media element. must be 'none', 'metadata',
* or 'auto'.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-preload}
*/
'preload',
/**
* set the value of `autoplay` on the media element. `autoplay` indicates
* that the media should start to play as soon as the page is ready.
*
* @method html5#setautoplay
* @param {boolean} autoplay
* - true indicates that the media should start as soon as the page loads.
* - false indicates that the media should not start as soon as the page loads.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-autoplay}
*/
'autoplay',
/**
* set the value of `loop` on the media element. `loop` indicates
* that the media should return to the start of the media and continue playing once
* it reaches the end.
*
* @method html5#setloop
* @param {boolean} loop
* - true indicates that playback should seek back to start once
* the end of a media is reached.
* - false indicates that playback should not loop back to the start when the
* end of the media is reached.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#attr-media-loop}
*/
'loop',
/**
* set the value of `playbackrate` on the media element. `playbackrate` indicates
* the rate at which the media should play back. examples:
* - if playbackrate is set to 2, media will play twice as fast.
* - if playbackrate is set to 0.5, media will play half as fast.
*
* @method html5#setplaybackrate
* @return {number}
* the value of `playbackrate` from the media element. a number indicating
* the current playback speed of the media, where 1 is normal speed.
*
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-playbackrate}
*/
'playbackrate'].foreach(function (prop) {
html5.prototype['set' + (0, _totitlecase2['default'])(prop)] = function (v) {
this.el_[prop] = v;
};
});
// wrap native functions with a function
[
/**
* a wrapper around the media elements `pause` function. this will call the `html5`
* media elements `pause` function.
*
* @method html5#pause
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-pause}
*/
'pause',
/**
* a wrapper around the media elements `load` function. this will call the `html5`s
* media element `load` function.
*
* @method html5#load
* @see [spec]{@link https://www.w3.org/tr/html5/embedded-content-0.html#dom-media-load}
*/
'load'].foreach(function (prop) {
html5.prototype[prop] = function () {
return this.el_[prop]();
};
});
_tech2['default'].withsourcehandlers(html5);
/**
* native source handler for html5, simply passes the source to the media element.
*
* @proprety {tech~sourceobject} source
* the source object
*
* @proprety {html5} tech
* the instance of the html5 tech.
*/
html5.nativesourcehandler = {};
/**
* check if the media element can play the given mime type.
*
* @param {string} type
* the mimetype to check
*
* @return {string}
* 'probably', 'maybe', or '' (empty string)
*/
html5.nativesourcehandler.canplaytype = function (type) {
// ie9 on windows 7 without mediaplayer throws an error here
// https://github.com/videojs/video.js/issues/519
try {
return html5.test_vid.canplaytype(type);
} catch (e) {
return '';
}
};
/**
* check if the media element can handle a source natively.
*
* @param {tech~sourceobject} source
* the source object
*
* @param {object} [options]
* options to be passed to the tech.
*
* @return {string}
* 'probably', 'maybe', or '' (empty string).
*/
html5.nativesourcehandler.canhandlesource = function (source, options) {
// if a type was provided we should rely on that
if (source.type) {
return html5.nativesourcehandler.canplaytype(source.type);
// if no type, fall back to checking 'video/[extension]'
} else if (source.src) {
var ext = url.getfileextension(source.src);
return html5.nativesourcehandler.canplaytype('video/' + ext);
}
return '';
};
/**
* pass the source to the native media element.
*
* @param {tech~sourceobject} source
* the source object
*
* @param {html5} tech
* the instance of the html5 tech
*
* @param {object} [options]
* the options to pass to the source
*/
html5.nativesourcehandler.handlesource = function (source, tech, options) {
tech.setsrc(source.src);
};
/**
* a noop for the native dispose function, as cleanup is not needed.
*/
html5.nativesourcehandler.dispose = function () {};
// register the native source handler
html5.registersourcehandler(html5.nativesourcehandler);
_component2['default'].registercomponent('html5', html5);
_tech2['default'].registertech('html5', html5);
exports['default'] = html5;
},{"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){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _tech = _dereq_(62);
var _tech2 = _interoprequiredefault(_tech);
var _totitlecase = _dereq_(91);
var _totitlecase2 = _interoprequiredefault(_totitlecase);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file loader.js
*/
/**
* the `medialoader` is the `component` that decides which playback technology to load
* when a player is initialized.
*
* @extends component
*/
var medialoader = function (_component) {
_inherits(medialoader, _component);
/**
* create an instance of this class.
*
* @param {player} player
* the `player` that this class should attach to.
*
* @param {object} [options]
* the key/value stroe of player options.
*
* @param {component~readycallback} [ready]
* the function that is run when this component is ready.
*/
function medialoader(player, options, ready) {
_classcallcheck(this, medialoader);
// if there are no sources when the player is initialized,
// load the first supported playback technology.
var _this = _possibleconstructorreturn(this, _component.call(this, player, options, ready));
if (!options.playeroptions.sources || options.playeroptions.sources.length === 0) {
for (var i = 0, j = options.playeroptions.techorder; i < j.length; i++) {
var techname = (0, _totitlecase2['default'])(j[i]);
var tech = _tech2['default'].gettech(techname);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!techname) {
tech = _component2['default'].getcomponent(techname);
}
// check if the browser supports this technology
if (tech && tech.issupported()) {
player.loadtech_(techname);
break;
}
}
} else {
// loop through playback technologies (html5, flash) and check for support.
// then load the best source.
// a few assumptions here:
// all playback technologies respect preload false.
player.src(options.playeroptions.sources);
}
return _this;
}
return medialoader;
}(_component2['default']);
_component2['default'].registercomponent('medialoader', medialoader);
exports['default'] = medialoader;
},{"5":5,"62":62,"91":91}],62:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _htmltrackelement = _dereq_(66);
var _htmltrackelement2 = _interoprequiredefault(_htmltrackelement);
var _htmltrackelementlist = _dereq_(65);
var _htmltrackelementlist2 = _interoprequiredefault(_htmltrackelementlist);
var _mergeoptions = _dereq_(87);
var _mergeoptions2 = _interoprequiredefault(_mergeoptions);
var _texttrack = _dereq_(72);
var _texttrack2 = _interoprequiredefault(_texttrack);
var _texttracklist = _dereq_(70);
var _texttracklist2 = _interoprequiredefault(_texttracklist);
var _videotracklist = _dereq_(76);
var _videotracklist2 = _interoprequiredefault(_videotracklist);
var _audiotracklist = _dereq_(63);
var _audiotracklist2 = _interoprequiredefault(_audiotracklist);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _log = _dereq_(86);
var _log2 = _interoprequiredefault(_log);
var _timeranges = _dereq_(90);
var _buffer = _dereq_(79);
var _mediaerror = _dereq_(46);
var _mediaerror2 = _interoprequiredefault(_mediaerror);
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
var _obj = _dereq_(88);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file tech.js
*/
/**
* an object containing a structure like: `{src: 'url', type: 'mimetype'}` or string
* that just contains the src url alone.
* * `var sourceobject = {src: 'http://ex.com/video.mp4', type: 'video/mp4'};`
* `var sourcestring = 'http://example.com/some-video.mp4';`
*
* @typedef {object|string} tech~sourceobject
*
* @property {string} src
* the url to the source
*
* @property {string} type
* the mime type of the source
*/
/**
* a function used by {@link tech} to create a new {@link texttrack}.
*
* @param {tech} self
* an instance of the tech class.
*
* @param {string} kind
* `texttrack` kind (subtitles, captions, descriptions, chapters, or metadata)
*
* @param {string} [label]
* label to identify the text track
*
* @param {string} [language]
* two letter language abbreviation
*
* @param {object} [options={}]
* an object with additional text track options
*
* @return {texttrack}
* the text track that was created.
*/
function createtrackhelper(self, kind, label, language) {
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
var tracks = self.texttracks();
options.kind = kind;
if (label) {
options.label = label;
}
if (language) {
options.language = language;
}
options.tech = self;
var track = new _texttrack2['default'](options);
tracks.addtrack_(track);
return track;
}
/**
* this is the base class for media playback technology controllers, such as
* {@link flash} and {@link html5}
*
* @extends component
*/
var tech = function (_component) {
_inherits(tech, _component);
/**
* create an instance of this tech.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} ready
* callback function to call when the `html5` tech is ready.
*/
function tech() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var ready = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {};
_classcallcheck(this, tech);
// we don't want the tech to report user activity automatically.
// this is done manually in addcontrolslisteners
options.reporttouchactivity = false;
// keep track of whether the current source has played at all to
// implement a very limited played()
var _this = _possibleconstructorreturn(this, _component.call(this, null, options, ready));
_this.hasstarted_ = false;
_this.on('playing', function () {
this.hasstarted_ = true;
});
_this.on('loadstart', function () {
this.hasstarted_ = false;
});
_this.texttracks_ = options.texttracks;
_this.videotracks_ = options.videotracks;
_this.audiotracks_ = options.audiotracks;
// manually track progress in cases where the browser/flash player doesn't report it.
if (!_this.featuresprogressevents) {
_this.manualprogresson();
}
// manually track timeupdates in cases where the browser/flash player doesn't report it.
if (!_this.featurestimeupdateevents) {
_this.manualtimeupdateson();
}
['text', 'audio', 'video'].foreach(function (track) {
if (options['native' + track + 'tracks'] === false) {
_this['featuresnative' + track + 'tracks'] = false;
}
});
if (options.nativecaptions === false) {
_this.featuresnativetexttracks = false;
}
if (!_this.featuresnativetexttracks) {
_this.emulatetexttracks();
}
_this.autoremotetexttracks_ = new _texttracklist2['default']();
_this.inittexttracklisteners();
_this.inittracklisteners();
// turn on component tap events only if not using native controls
if (!options.nativecontrolsfortouch) {
_this.emittapevents();
}
if (_this.constructor) {
_this.name_ = _this.constructor.name || 'unknown tech';
}
return _this;
}
/* fallbacks for unsupported event types
================================================================================ */
/**
* polyfill the `progress` event for browsers that don't support it natively.
*
* @see {@link tech#trackprogress}
*/
tech.prototype.manualprogresson = function manualprogresson() {
this.on('durationchange', this.ondurationchange);
this.manualprogress = true;
// trigger progress watching when a source begins loading
this.one('ready', this.trackprogress);
};
/**
* turn off the polyfill for `progress` events that was created in
* {@link tech#manualprogresson}
*/
tech.prototype.manualprogressoff = function manualprogressoff() {
this.manualprogress = false;
this.stoptrackingprogress();
this.off('durationchange', this.ondurationchange);
};
/**
* this is used to trigger a `progress` event when the buffered percent changes. it
* sets an interval function that will be called every 500 milliseconds to check if the
* buffer end percent has changed.
*
* > this function is called by {@link tech#manualprogresson}
*
* @param {eventtarget~event} event
* the `ready` event that caused this to run.
*
* @listens tech#ready
* @fires tech#progress
*/
tech.prototype.trackprogress = function trackprogress(event) {
this.stoptrackingprogress();
this.progressinterval = this.setinterval(fn.bind(this, function () {
// don't trigger unless buffered amount is greater than last time
var numbufferedpercent = this.bufferedpercent();
if (this.bufferedpercent_ !== numbufferedpercent) {
/**
* see {@link player#progress}
*
* @event tech#progress
* @type {eventtarget~event}
*/
this.trigger('progress');
}
this.bufferedpercent_ = numbufferedpercent;
if (numbufferedpercent === 1) {
this.stoptrackingprogress();
}
}), 500);
};
/**
* update our internal duration on a `durationchange` event by calling
* {@link tech#duration}.
*
* @param {eventtarget~event} event
* the `durationchange` event that caused this to run.
*
* @listens tech#durationchange
*/
tech.prototype.ondurationchange = function ondurationchange(event) {
this.duration_ = this.duration();
};
/**
* get and create a `timerange` object for buffering.
*
* @return {timerange}
* the time range object that was created.
*/
tech.prototype.buffered = function buffered() {
return (0, _timeranges.createtimerange)(0, 0);
};
/**
* get the percentage of the current video that is currently buffered.
*
* @return {number}
* a number from 0 to 1 that represents the decimal percentage of the
* video that is buffered.
*
*/
tech.prototype.bufferedpercent = function bufferedpercent() {
return (0, _buffer.bufferedpercent)(this.buffered(), this.duration_);
};
/**
* turn off the polyfill for `progress` events that was created in
* {@link tech#manualprogresson}
* stop manually tracking progress events by clearing the interval that was set in
* {@link tech#trackprogress}.
*/
tech.prototype.stoptrackingprogress = function stoptrackingprogress() {
this.clearinterval(this.progressinterval);
};
/**
* polyfill the `timeupdate` event for browsers that don't support it.
*
* @see {@link tech#trackcurrenttime}
*/
tech.prototype.manualtimeupdateson = function manualtimeupdateson() {
this.manualtimeupdates = true;
this.on('play', this.trackcurrenttime);
this.on('pause', this.stoptrackingcurrenttime);
};
/**
* turn off the polyfill for `timeupdate` events that was created in
* {@link tech#manualtimeupdateson}
*/
tech.prototype.manualtimeupdatesoff = function manualtimeupdatesoff() {
this.manualtimeupdates = false;
this.stoptrackingcurrenttime();
this.off('play', this.trackcurrenttime);
this.off('pause', this.stoptrackingcurrenttime);
};
/**
* sets up an interval function to track current time and trigger `timeupdate` every
* 250 milliseconds.
*
* @listens tech#play
* @triggers tech#timeupdate
*/
tech.prototype.trackcurrenttime = function trackcurrenttime() {
if (this.currenttimeinterval) {
this.stoptrackingcurrenttime();
}
this.currenttimeinterval = this.setinterval(function () {
/**
* triggered at an interval of 250ms to indicated that time is passing in the video.
*
* @event tech#timeupdate
* @type {eventtarget~event}
*/
this.trigger({ type: 'timeupdate', target: this, manuallytriggered: true });
// 42 = 24 fps // 250 is what webkit uses // ff uses 15
}, 250);
};
/**
* stop the interval function created in {@link tech#trackcurrenttime} so that the
* `timeupdate` event is no longer triggered.
*
* @listens {tech#pause}
*/
tech.prototype.stoptrackingcurrenttime = function stoptrackingcurrenttime() {
this.clearinterval(this.currenttimeinterval);
// #1002 - if the video ends right before the next timeupdate would happen,
// the progress bar won't make it all the way to the end
this.trigger({ type: 'timeupdate', target: this, manuallytriggered: true });
};
/**
* turn off all event polyfills, clear the `tech`s {@link audiotracklist},
* {@link videotracklist}, and {@link texttracklist}, and dispose of this tech.
*
* @fires component#dispose
*/
tech.prototype.dispose = function dispose() {
// clear out all tracks because we can't reuse them between techs
this.cleartracks(['audio', 'video', 'text']);
// turn off any manual progress or timeupdate tracking
if (this.manualprogress) {
this.manualprogressoff();
}
if (this.manualtimeupdates) {
this.manualtimeupdatesoff();
}
_component.prototype.dispose.call(this);
};
/**
* clear out a single `tracklist` or an array of `tracklists` given their names.
*
* > note: techs without source handlers should call this between sources for `video`
* & `audio` tracks. you don't want to use them between tracks!
*
* @param {string[]|string} types
* tracklist names to clear, valid names are `video`, `audio`, and
* `text`.
*/
tech.prototype.cleartracks = function cleartracks(types) {
var _this2 = this;
types = [].concat(types);
// clear out all tracks because we can't reuse them between techs
types.foreach(function (type) {
var list = _this2[type + 'tracks']() || [];
var i = list.length;
while (i--) {
var track = list[i];
if (type === 'text') {
_this2.removeremotetexttrack(track);
}
list.removetrack_(track);
}
});
};
/**
* remove any texttracks added via addremotetexttrack that are
* flagged for automatic garbage collection
*/
tech.prototype.cleanupautotexttracks = function cleanupautotexttracks() {
var list = this.autoremotetexttracks_ || [];
var i = list.length;
while (i--) {
var track = list[i];
this.removeremotetexttrack(track);
}
};
/**
* reset the tech, which will removes all sources and reset the internal readystate.
*
* @abstract
*/
tech.prototype.reset = function reset() {};
/**
* get or set an error on the tech.
*
* @param {mediaerror} [err]
* error to set on the tech
*
* @return {mediaerror|null}
* the current error object on the tech, or null if there isn't one.
*/
tech.prototype.error = function error(err) {
if (err !== undefined) {
this.error_ = new _mediaerror2['default'](err);
this.trigger('error');
}
return this.error_;
};
/**
* returns the `timerange`s that have been played through for the current source.
*
* > note: this implementation is incomplete. it does not track the played `timerange`.
* it only checks wether the source has played at all or not.
*
* @return {timerange}
* - a single time range if this video has played
* - an empty set of ranges if not.
*/
tech.prototype.played = function played() {
if (this.hasstarted_) {
return (0, _timeranges.createtimerange)(0, 0);
}
return (0, _timeranges.createtimerange)();
};
/**
* causes a manual time update to occur if {@link tech#manualtimeupdateson} was
* previously called.
*
* @fires tech#timeupdate
*/
tech.prototype.setcurrenttime = function setcurrenttime() {
// improve the accuracy of manual timeupdates
if (this.manualtimeupdates) {
/**
* a manual `timeupdate` event.
*
* @event tech#timeupdate
* @type {eventtarget~event}
*/
this.trigger({ type: 'timeupdate', target: this, manuallytriggered: true });
}
};
/**
* turn on listeners for {@link texttracklist} events. this adds
* {@link eventtarget~eventlisteners} for `texttrackchange`, `addtrack` and
* `removetrack`.
*
* @fires tech#texttrackchange
*/
tech.prototype.inittexttracklisteners = function inittexttracklisteners() {
var texttracklistchanges = fn.bind(this, function () {
/**
* triggered when tracks are added or removed on the tech {@link texttracklist}
*
* @event tech#texttrackchange
* @type {eventtarget~event}
*/
this.trigger('texttrackchange');
});
var tracks = this.texttracks();
if (!tracks) {
return;
}
tracks.addeventlistener('removetrack', texttracklistchanges);
tracks.addeventlistener('addtrack', texttracklistchanges);
this.on('dispose', fn.bind(this, function () {
tracks.removeeventlistener('removetrack', texttracklistchanges);
tracks.removeeventlistener('addtrack', texttracklistchanges);
}));
};
/**
* turn on listeners for {@link videotracklist} and {@link {audiotracklist} events.
* this adds {@link eventtarget~eventlisteners} for `addtrack`, and `removetrack`.
*
* @fires tech#audiotrackchange
* @fires tech#videotrackchange
*/
tech.prototype.inittracklisteners = function inittracklisteners() {
var _this3 = this;
var tracktypes = ['video', 'audio'];
tracktypes.foreach(function (type) {
/**
* triggered when tracks are added or removed on the tech {@link audiotracklist}
*
* @event tech#audiotrackchange
* @type {eventtarget~event}
*/
/**
* triggered when tracks are added or removed on the tech {@link videotracklist}
*
* @event tech#videotrackchange
* @type {eventtarget~event}
*/
var tracklistchanges = function tracklistchanges() {
_this3.trigger(type + 'trackchange');
};
var tracks = _this3[type + 'tracks']();
tracks.addeventlistener('removetrack', tracklistchanges);
tracks.addeventlistener('addtrack', tracklistchanges);
_this3.on('dispose', function () {
tracks.removeeventlistener('removetrack', tracklistchanges);
tracks.removeeventlistener('addtrack', tracklistchanges);
});
});
};
/**
* emulate texttracks using vtt.js if necessary
*
* @fires tech#vttjsloaded
* @fires tech#vttjserror
*/
tech.prototype.addwebvttscript_ = function addwebvttscript_() {
var _this4 = this;
if (_window2['default'].webvtt) {
return;
}
// initially, tech.el_ is a child of a dummy-div wait until the component system
// signals that the tech is ready at which point tech.el_ is part of the dom
// before inserting the webvtt script
if (_document2['default'].body.contains(this.el())) {
var vtt = _dereq_(105);
// load via require if available and vtt.js script location was not passed in
// as an option. novtt builds will turn the above require call into an empty object
// which will cause this if check to always fail.
if (!this.options_['vtt.js'] && (0, _obj.isplain)(vtt) && object.keys(vtt).length > 0) {
this.trigger('vttjsloaded');
return;
}
// load vtt.js via the script location option or the cdn of no location was
// passed in
var script = _document2['default'].createelement('script');
script.src = this.options_['vtt.js'] || 'https://vjs.zencdn.net/vttjs/0.12.3/vtt.min.js';
script.onload = function () {
/**
* fired when vtt.js is loaded.
*
* @event tech#vttjsloaded
* @type {eventtarget~event}
*/
_this4.trigger('vttjsloaded');
};
script.onerror = function () {
/**
* fired when vtt.js was not loaded due to an error
*
* @event tech#vttjsloaded
* @type {eventtarget~event}
*/
_this4.trigger('vttjserror');
};
this.on('dispose', function () {
script.onload = null;
script.onerror = null;
});
// but have not loaded yet and we set it to true before the inject so that
// we don't overwrite the injected window.webvtt if it loads right away
_window2['default'].webvtt = true;
this.el().parentnode.appendchild(script);
} else {
this.ready(this.addwebvttscript_);
}
};
/**
* emulate texttracks
*
* @method emulatetexttracks
*/
tech.prototype.emulatetexttracks = function emulatetexttracks() {
var _this5 = this;
var tracks = this.texttracks();
if (!tracks) {
return;
}
var remotetracks = this.remotetexttracks();
var handleaddtrack = function handleaddtrack(e) {
return tracks.addtrack_(e.track);
};
var handleremovetrack = function handleremovetrack(e) {
return tracks.removetrack_(e.track);
};
remotetracks.on('addtrack', handleaddtrack);
remotetracks.on('removetrack', handleremovetrack);
this.addwebvttscript_();
var updatedisplay = function updatedisplay() {
return _this5.trigger('texttrackchange');
};
var texttrackschanges = function texttrackschanges() {
updatedisplay();
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
track.removeeventlistener('cuechange', updatedisplay);
if (track.mode === 'showing') {
track.addeventlistener('cuechange', updatedisplay);
}
}
};
texttrackschanges();
tracks.addeventlistener('change', texttrackschanges);
tracks.addeventlistener('addtrack', texttrackschanges);
tracks.addeventlistener('removetrack', texttrackschanges);
this.on('dispose', function () {
remotetracks.off('addtrack', handleaddtrack);
remotetracks.off('removetrack', handleremovetrack);
tracks.removeeventlistener('change', texttrackschanges);
tracks.removeeventlistener('addtrack', texttrackschanges);
tracks.removeeventlistener('removetrack', texttrackschanges);
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
track.removeeventlistener('cuechange', updatedisplay);
}
});
};
/**
* get the `tech`s {@link videotracklist}.
*
* @return {videotracklist}
* the video track list that the tech is currently using.
*/
tech.prototype.videotracks = function videotracks() {
this.videotracks_ = this.videotracks_ || new _videotracklist2['default']();
return this.videotracks_;
};
/**
* get the `tech`s {@link audiotracklist}.
*
* @return {audiotracklist}
* the audio track list that the tech is currently using.
*/
tech.prototype.audiotracks = function audiotracks() {
this.audiotracks_ = this.audiotracks_ || new _audiotracklist2['default']();
return this.audiotracks_;
};
/**
* get the `tech`s {@link texttracklist}.
*
* @return {texttracklist}
* the text track list that the tech is currently using.
*/
tech.prototype.texttracks = function texttracks() {
this.texttracks_ = this.texttracks_ || new _texttracklist2['default']();
return this.texttracks_;
};
/**
* get the `tech`s remote {@link texttracklist}, which is created from elements
* that were added to the dom.
*
* @return {texttracklist}
* the remote text track list that the tech is currently using.
*/
tech.prototype.remotetexttracks = function remotetexttracks() {
this.remotetexttracks_ = this.remotetexttracks_ || new _texttracklist2['default']();
return this.remotetexttracks_;
};
/**
* get the `tech`s {htmltrackelementlist}, which are the elements in the dom that are
* being used as texttracks.
*
* @return {htmltrackelementlist}
* the current html track elements that exist for the tech.
*/
tech.prototype.remotetexttrackels = function remotetexttrackels() {
this.remotetexttrackels_ = this.remotetexttrackels_ || new _htmltrackelementlist2['default']();
return this.remotetexttrackels_;
};
/**
* create and returns a remote {@link texttrack} object.
*
* @param {string} kind
* `texttrack` kind (subtitles, captions, descriptions, chapters, or metadata)
*
* @param {string} [label]
* label to identify the text track
*
* @param {string} [language]
* two letter language abbreviation
*
* @return {texttrack}
* the texttrack that gets created.
*/
tech.prototype.addtexttrack = function addtexttrack(kind, label, language) {
if (!kind) {
throw new error('texttrack kind is required but was not provided');
}
return createtrackhelper(this, kind, label, language);
};
/**
* create an emulated texttrack for use by addremotetexttrack
*
* this is intended to be overridden by classes that inherit from
* tech in order to create native or custom texttracks.
*
* @param {object} options
* the object should contain the options to initialize the texttrack with.
*
* @param {string} [options.kind]
* `texttrack` kind (subtitles, captions, descriptions, chapters, or metadata).
*
* @param {string} [options.label].
* label to identify the text track
*
* @param {string} [options.language]
* two letter language abbreviation.
*
* @return {htmltrackelement}
* the track element that gets created.
*/
tech.prototype.createremotetexttrack = function createremotetexttrack(options) {
var track = (0, _mergeoptions2['default'])(options, {
tech: this
});
return new _htmltrackelement2['default'](track);
};
/**
* creates a remote text track object and returns an html track element.
*
* > note: this can be an emulated {@link htmltrackelement} or a native one.
*
* @param {object} options
* see {@link tech#createremotetexttrack} for more detailed properties.
*
* @param {boolean} [manualcleanup=true]
* - when false: the texttrack will be automatically removed from the video
* element whenever the source changes
* - when true: the texttrack will have to be cleaned up manually
*
* @return {htmltrackelement}
* an html track element.
*
* @deprecated the default functionality for this function will be equivalent
* to "manualcleanup=false" in the future. the manualcleanup parameter will
* also be removed.
*/
tech.prototype.addremotetexttrack = function addremotetexttrack() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var manualcleanup = arguments[1];
var htmltrackelement = this.createremotetexttrack(options);
if (manualcleanup !== true && manualcleanup !== false) {
// deprecation warning
_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');
manualcleanup = true;
}
// store htmltrackelement and texttrack to remote list
this.remotetexttrackels().addtrackelement_(htmltrackelement);
this.remotetexttracks().addtrack_(htmltrackelement.track);
if (manualcleanup !== true) {
// create the texttracklist if it doesn't exist
this.autoremotetexttracks_.addtrack_(htmltrackelement.track);
}
return htmltrackelement;
};
/**
* remove a remote text track from the remote `texttracklist`.
*
* @param {texttrack} track
* `texttrack` to remove from the `texttracklist`
*/
tech.prototype.removeremotetexttrack = function removeremotetexttrack(track) {
var trackelement = this.remotetexttrackels().gettrackelementbytrack_(track);
// remove htmltrackelement and texttrack from remote list
this.remotetexttrackels().removetrackelement_(trackelement);
this.remotetexttracks().removetrack_(track);
this.autoremotetexttracks_.removetrack_(track);
};
/**
* a method to set a poster from a `tech`.
*
* @abstract
*/
tech.prototype.setposter = function setposter() {};
/*
* check if the tech can support the given mime-type.
*
* the base tech does not support any type, but source handlers might
* overwrite this.
*
* @param {string} type
* the mimetype to check for support
*
* @return {string}
* 'probably', 'maybe', or empty string
*
* @see [spec]{@link https://developer.mozilla.org/en-us/docs/web/api/htmlmediaelement/canplaytype}
*
* @abstract
*/
tech.prototype.canplaytype = function canplaytype() {
return '';
};
/*
* return whether the argument is a tech or not.
* can be passed either a class like `html5` or a instance like `player.tech_`
*
* @param {object} component
* the item to check
*
* @return {boolean}
* whether it is a tech or not
* - true if it is a tech
* - false if it is not
*/
tech.istech = function istech(component) {
return component.prototype instanceof tech || component instanceof tech || component === tech;
};
/**
* registers a `tech` into a shared list for videojs.
*
* @param {string} name
* name of the `tech` to register.
*
* @param {object} tech
* the `tech` class to register.
*/
tech.registertech = function registertech(name, tech) {
if (!tech.techs_) {
tech.techs_ = {};
}
if (!tech.istech(tech)) {
throw new error('tech ' + name + ' must be a tech');
}
tech.techs_[name] = tech;
return tech;
};
/**
* get a `tech` from the shared list by name.
*
* @param {string} name
* name of the component to get
*
* @return {tech|undefined}
* the `tech` or undefined if there was no tech with the name requsted.
*/
tech.gettech = function gettech(name) {
if (tech.techs_ && tech.techs_[name]) {
return tech.techs_[name];
}
if (_window2['default'] && _window2['default'].videojs && _window2['default'].videojs[name]) {
_log2['default'].warn('the ' + name + ' tech was added to the videojs object when it should be registered using videojs.registertech(name, tech)');
return _window2['default'].videojs[name];
}
};
return tech;
}(_component2['default']);
/**
* list of associated text tracks.
*
* @type {texttracklist}
* @private
*/
tech.prototype.texttracks_; // eslint-disable-line
/**
* list of associated audio tracks.
*
* @type {audiotracklist}
* @private
*/
tech.prototype.audiotracks_; // eslint-disable-line
/**
* list of associated video tracks.
*
* @type {videotracklist}
* @private
*/
tech.prototype.videotracks_; // eslint-disable-line
/**
* boolean indicating wether the `tech` supports volume control.
*
* @type {boolean}
* @default
*/
tech.prototype.featuresvolumecontrol = true;
/**
* boolean indicating wether the `tech` support fullscreen resize control.
* resizing plugins using request fullscreen reloads the plugin
*
* @type {boolean}
* @default
*/
tech.prototype.featuresfullscreenresize = false;
/**
* boolean indicating wether the `tech` supports changing the speed at which the video
* plays. examples:
* - set player to play 2x (twice) as fast
* - set player to play 0.5x (half) as fast
*
* @type {boolean}
* @default
*/
tech.prototype.featuresplaybackrate = false;
/**
* boolean indicating wether the `tech` supports the `progress` event. this is currently
* not triggered by video-js-swf. this will be used to determine if
* {@link tech#manualprogresson} should be called.
*
* @type {boolean}
* @default
*/
tech.prototype.featuresprogressevents = false;
/**
* boolean indicating wether the `tech` supports the `timeupdate` event. this is currently
* not triggered by video-js-swf. this will be used to determine if
* {@link tech#manualtimeupdates} should be called.
*
* @type {boolean}
* @default
*/
tech.prototype.featurestimeupdateevents = false;
/**
* boolean indicating wether the `tech` supports the native `texttrack`s.
* this will help us integrate with native `texttrack`s if the browser supports them.
*
* @type {boolean}
* @default
*/
tech.prototype.featuresnativetexttracks = false;
/**
* a functional mixin for techs that want to use the source handler pattern.
* source handlers are scripts for handling specific formats.
* the source handler pattern is used for adaptive formats (hls, dash) that
* manually load video data and feed it into a source buffer (media source extensions)
* example: `tech.withsourcehandlers.call(mytech);`
*
* @param {tech} _tech
* the tech to add source handler functions to.
*
* @mixes tech~sourcehandleradditions
*/
tech.withsourcehandlers = function (_tech) {
/**
* register a source handler
*
* @param {function} handler
* the source handler class
*
* @param {number} [index]
* register it at the following index
*/
_tech.registersourcehandler = function (handler, index) {
var handlers = _tech.sourcehandlers;
if (!handlers) {
handlers = _tech.sourcehandlers = [];
}
if (index === undefined) {
// add to the end of the list
index = handlers.length;
}
handlers.splice(index, 0, handler);
};
/**
* check if the tech can support the given type. also checks the
* techs sourcehandlers.
*
* @param {string} type
* the mimetype to check.
*
* @return {string}
* 'probably', 'maybe', or '' (empty string)
*/
_tech.canplaytype = function (type) {
var handlers = _tech.sourcehandlers || [];
var can = void 0;
for (var i = 0; i < handlers.length; i++) {
can = handlers[i].canplaytype(type);
if (can) {
return can;
}
}
return '';
};
/**
* returns the first source handler that supports the source.
*
* todo: answer question: should 'probably' be prioritized over 'maybe'
*
* @param {tech~sourceobject} source
* the source object
*
* @param {object} options
* the options passed to the tech
*
* @return {sourcehandler|null}
* the first source handler that supports the source or null if
* no sourcehandler supports the source
*/
_tech.selectsourcehandler = function (source, options) {
var handlers = _tech.sourcehandlers || [];
var can = void 0;
for (var i = 0; i < handlers.length; i++) {
can = handlers[i].canhandlesource(source, options);
if (can) {
return handlers[i];
}
}
return null;
};
/**
* check if the tech can support the given source.
*
* @param {tech~sourceobject} srcobj
* the source object
*
* @param {object} options
* the options passed to the tech
*
* @return {string}
* 'probably', 'maybe', or '' (empty string)
*/
_tech.canplaysource = function (srcobj, options) {
var sh = _tech.selectsourcehandler(srcobj, options);
if (sh) {
return sh.canhandlesource(srcobj, options);
}
return '';
};
/**
* when using a source handler, prefer its implementation of
* any function normally provided by the tech.
*/
var deferrable = ['seekable', 'duration'];
/**
* a wrapper around {@link tech#seekable} that will call a `sourcehandler`s seekable
* function if it exists, with a fallback to the techs seekable function.
*
* @method _tech.seekable
*/
/**
* a wrapper around {@link tech#duration} that will call a `sourcehandler`s duration
* function if it exists, otherwise it will fallback to the techs duration function.
*
* @method _tech.duration
*/
deferrable.foreach(function (fnname) {
var originalfn = this[fnname];
if (typeof originalfn !== 'function') {
return;
}
this[fnname] = function () {
if (this.sourcehandler_ && this.sourcehandler_[fnname]) {
return this.sourcehandler_[fnname].apply(this.sourcehandler_, arguments);
}
return originalfn.apply(this, arguments);
};
}, _tech.prototype);
/**
* create a function for setting the source using a source object
* and source handlers.
* should never be called unless a source handler was found.
*
* @param {tech~sourceobject} source
* a source object with src and type keys
*
* @return {tech}
* returns itself; this method is chainable
*/
_tech.prototype.setsource = function (source) {
var sh = _tech.selectsourcehandler(source, this.options_);
if (!sh) {
// fall back to a native source hander when unsupported sources are
// deliberately set
if (_tech.nativesourcehandler) {
sh = _tech.nativesourcehandler;
} else {
_log2['default'].error('no source hander found for the current source.');
}
}
// dispose any existing source handler
this.disposesourcehandler();
this.off('dispose', this.disposesourcehandler);
if (sh !== _tech.nativesourcehandler) {
this.currentsource_ = source;
// catch if someone replaced the src without calling setsource.
// if they do, set currentsource_ to null and dispose our source handler.
this.off(this.el_, 'loadstart', _tech.prototype.firstloadstartlistener_);
this.off(this.el_, 'loadstart', _tech.prototype.successiveloadstartlistener_);
this.one(this.el_, 'loadstart', _tech.prototype.firstloadstartlistener_);
}
this.sourcehandler_ = sh.handlesource(source, this, this.options_);
this.on('dispose', this.disposesourcehandler);
return this;
};
/**
* called once for the first loadstart of a video.
*
* @listens tech#loadstart
*/
_tech.prototype.firstloadstartlistener_ = function () {
this.one(this.el_, 'loadstart', _tech.prototype.successiveloadstartlistener_);
};
// on successive loadstarts when setsource has not been called again
/**
* called after the first loadstart for a video occurs.
*
* @listens tech#loadstart
*/
_tech.prototype.successiveloadstartlistener_ = function () {
this.disposesourcehandler();
this.one(this.el_, 'loadstart', _tech.prototype.successiveloadstartlistener_);
};
/**
* clean up any existing sourcehandlers and listeners when the tech is disposed.
*
* @listens tech#dispose
*/
_tech.prototype.disposesourcehandler = function () {
// if we have a source and get another one
// then we are loading something new
// than clear all of our current tracks
if (this.currentsource_) {
this.cleartracks(['audio', 'video']);
this.currentsource_ = null;
}
// always clean up auto-text tracks
this.cleanupautotexttracks();
if (this.sourcehandler_) {
this.off(this.el_, 'loadstart', _tech.prototype.firstloadstartlistener_);
this.off(this.el_, 'loadstart', _tech.prototype.successiveloadstartlistener_);
if (this.sourcehandler_.dispose) {
this.sourcehandler_.dispose();
}
this.sourcehandler_ = null;
}
};
};
_component2['default'].registercomponent('tech', tech);
// old name for tech
// @deprecated
_component2['default'].registercomponent('mediatechcontroller', tech);
tech.registertech('tech', tech);
exports['default'] = tech;
},{"105":105,"46":46,"5":5,"63":63,"65":65,"66":66,"70":70,"72":72,"76":76,"79":79,"83":83,"86":86,"87":87,"88":88,"90":90,"94":94,"95":95}],63:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _tracklist = _dereq_(74);
var _tracklist2 = _interoprequiredefault(_tracklist);
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file audio-track-list.js
*/
/**
* anywhere we call this function we diverge from the spec
* as we only support one enabled audiotrack at a time
*
* @param {audiotracklist} list
* list to work on
*
* @param {audiotrack} track
* the track to skip
*
* @private
*/
var disableothers = function disableothers(list, track) {
for (var i = 0; i < list.length; i++) {
if (track.id === list[i].id) {
continue;
}
// another audio track is enabled, disable it
list[i].enabled = false;
}
};
/**
* the current list of {@link audiotrack} for a media file.
*
* @see [spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotracklist}
* @extends tracklist
*/
var audiotracklist = function (_tracklist) {
_inherits(audiotracklist, _tracklist);
/**
* create an instance of this class.
*
* @param {audiotrack[]} [tracks=[]]
* a list of `audiotrack` to instantiate the list with.
*/
function audiotracklist() {
var _this, _ret;
var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
_classcallcheck(this, audiotracklist);
var list = void 0;
// make sure only 1 track is enabled
// sorted from last index to first index
for (var i = tracks.length - 1; i >= 0; i--) {
if (tracks[i].enabled) {
disableothers(tracks, tracks[i]);
break;
}
}
// ie8 forces us to implement inheritance ourselves
// as it does not support object.defineproperty properly
if (browser.is_ie8) {
list = _document2['default'].createelement('custom');
for (var prop in _tracklist2['default'].prototype) {
if (prop !== 'constructor') {
list[prop] = _tracklist2['default'].prototype[prop];
}
}
for (var _prop in audiotracklist.prototype) {
if (_prop !== 'constructor') {
list[_prop] = audiotracklist.prototype[_prop];
}
}
}
list = (_this = _possibleconstructorreturn(this, _tracklist.call(this, tracks, list)), _this);
list.changing_ = false;
return _ret = list, _possibleconstructorreturn(_this, _ret);
}
/**
* add an {@link audiotrack} to the `audiotracklist`.
*
* @param {audiotrack} track
* the audiotrack to add to the list
*
* @fires track#addtrack
* @private
*/
audiotracklist.prototype.addtrack_ = function addtrack_(track) {
var _this2 = this;
if (track.enabled) {
disableothers(this, track);
}
_tracklist.prototype.addtrack_.call(this, track);
// native tracks don't have this
if (!track.addeventlistener) {
return;
}
/**
* @listens audiotrack#enabledchange
* @fires tracklist#change
*/
track.addeventlistener('enabledchange', function () {
// when we are disabling other tracks (since we don't support
// more than one track at a time) we will set changing_
// to true so that we don't trigger additional change events
if (_this2.changing_) {
return;
}
_this2.changing_ = true;
disableothers(_this2, track);
_this2.changing_ = false;
_this2.trigger('change');
});
};
/**
* add an {@link audiotrack} to the `audiotracklist`.
*
* @param {audiotrack} track
* the audiotrack to add to the list
*
* @fires track#addtrack
*/
audiotracklist.prototype.addtrack = function addtrack(track) {
this.addtrack_(track);
};
/**
* remove an {@link audiotrack} from the `audiotracklist`.
*
* @param {audiotrack} track
* the audiotrack to remove from the list
*
* @fires track#removetrack
*/
audiotracklist.prototype.removetrack = function removetrack(track) {
_tracklist.prototype.removetrack_.call(this, track);
};
return audiotracklist;
}(_tracklist2['default']);
exports['default'] = audiotracklist;
},{"74":74,"78":78,"94":94}],64:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _trackenums = _dereq_(73);
var _track = _dereq_(75);
var _track2 = _interoprequiredefault(_track);
var _mergeoptions = _dereq_(87);
var _mergeoptions2 = _interoprequiredefault(_mergeoptions);
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; }
/**
* a representation of a single `audiotrack`. if it is part of an {@link audiotracklist}
* only one `audiotrack` in the list will be enabled at a time.
*
* @see [spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#audiotrack}
* @extends track
*/
var audiotrack = function (_track) {
_inherits(audiotrack, _track);
/**
* create an instance of this class.
*
* @param {object} [options={}]
* object of option names and values
*
* @param {audiotrack~kind} [options.kind='']
* a valid audio track kind
*
* @param {string} [options.id='vjs_track_' + guid.newguid()]
* a unique id for this audiotrack.
*
* @param {string} [options.label='']
* the menu label for this track.
*
* @param {string} [options.language='']
* a valid two character language code.
*
* @param {boolean} [options.enabled]
* if this track is the one that is currently playing. if this track is part of
* an {@link audiotracklist}, only one {@link audiotrack} will be enabled.
*/
function audiotrack() {
var _this, _ret;
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classcallcheck(this, audiotrack);
var settings = (0, _mergeoptions2['default'])(options, {
kind: _trackenums.audiotrackkind[options.kind] || ''
});
// on ie8 this will be a document element
// for every other browser this will be a normal object
var track = (_this = _possibleconstructorreturn(this, _track.call(this, settings)), _this);
var enabled = false;
if (browser.is_ie8) {
for (var prop in audiotrack.prototype) {
if (prop !== 'constructor') {
track[prop] = audiotrack.prototype[prop];
}
}
}
/**
* @member {boolean} enabled
* if this `audiotrack` is enabled or not. when setting this will
* fire {@link audiotrack#enabledchange} if the state of enabled is changed.
*
* @fires videotrack#selectedchange
*/
object.defineproperty(track, 'enabled', {
get: function get() {
return enabled;
},
set: function set(newenabled) {
// an invalid or unchanged value
if (typeof newenabled !== 'boolean' || newenabled === enabled) {
return;
}
enabled = newenabled;
/**
* an event that fires when enabled changes on this track. this allows
* the audiotracklist that holds this track to act accordingly.
*
* > note: this is not part of the spec! native tracks will do
* this internally without an event.
*
* @event audiotrack#enabledchange
* @type {eventtarget~event}
*/
this.trigger('enabledchange');
}
});
// if the user sets this track to selected then
// set selected to that true value otherwise
// we keep it false
if (settings.enabled) {
track.enabled = settings.enabled;
}
track.loaded_ = true;
return _ret = track, _possibleconstructorreturn(_this, _ret);
}
return audiotrack;
}(_track2['default']);
exports['default'] = audiotrack;
},{"73":73,"75":75,"78":78,"87":87}],65:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
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; } }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } } /**
* @file html-track-element-list.js
*/
/**
* the current list of {@link htmltrackelement}s.
*/
var htmltrackelementlist = function () {
/**
* create an instance of this class.
*
* @param {htmltrackelement[]} [tracks=[]]
* a list of `htmltrackelement` to instantiate the list with.
*/
function htmltrackelementlist() {
var trackelements = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
_classcallcheck(this, htmltrackelementlist);
var list = this; // eslint-disable-line
if (browser.is_ie8) {
list = _document2['default'].createelement('custom');
for (var prop in htmltrackelementlist.prototype) {
if (prop !== 'constructor') {
list[prop] = htmltrackelementlist.prototype[prop];
}
}
}
list.trackelements_ = [];
/**
* @member {number} length
* the current number of `track`s in the this trackist.
*/
object.defineproperty(list, 'length', {
get: function get() {
return this.trackelements_.length;
}
});
for (var i = 0, length = trackelements.length; i < length; i++) {
list.addtrackelement_(trackelements[i]);
}
if (browser.is_ie8) {
return list;
}
}
/**
* add an {@link htmltrackelement} to the `htmltrackelementlist`
*
* @param {htmltrackelement} trackelement
* the track element to add to the list.
*
* @private
*/
htmltrackelementlist.prototype.addtrackelement_ = function addtrackelement_(trackelement) {
var index = this.trackelements_.length;
if (!('' + index in this)) {
object.defineproperty(this, index, {
get: function get() {
return this.trackelements_[index];
}
});
}
// do not add duplicate elements
if (this.trackelements_.indexof(trackelement) === -1) {
this.trackelements_.push(trackelement);
}
};
/**
* get an {@link htmltrackelement} from the `htmltrackelementlist` given an
* {@link texttrack}.
*
* @param {texttrack} track
* the track associated with a track element.
*
* @return {htmltrackelement|undefined}
* the track element that was found or undefined.
*
* @private
*/
htmltrackelementlist.prototype.gettrackelementbytrack_ = function gettrackelementbytrack_(track) {
var trackelement_ = void 0;
for (var i = 0, length = this.trackelements_.length; i < length; i++) {
if (track === this.trackelements_[i].track) {
trackelement_ = this.trackelements_[i];
break;
}
}
return trackelement_;
};
/**
* remove a {@link htmltrackelement} from the `htmltrackelementlist`
*
* @param {htmltrackelement} trackelement
* the track element to remove from the list.
*
* @private
*/
htmltrackelementlist.prototype.removetrackelement_ = function removetrackelement_(trackelement) {
for (var i = 0, length = this.trackelements_.length; i < length; i++) {
if (trackelement === this.trackelements_[i]) {
this.trackelements_.splice(i, 1);
break;
}
}
};
return htmltrackelementlist;
}();
exports['default'] = htmltrackelementlist;
},{"78":78,"94":94}],66:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
var _eventtarget = _dereq_(42);
var _eventtarget2 = _interoprequiredefault(_eventtarget);
var _texttrack = _dereq_(72);
var _texttrack2 = _interoprequiredefault(_texttrack);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
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; } }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file html-track-element.js
*/
/**
* @typedef {htmltrackelement~readystate}
* @enum {number}
*/
var none = 0;
var loading = 1;
var loaded = 2;
var error = 3;
/**
* a single track represented in the dom.
*
* @see [spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement}
* @extends eventtarget
*/
var htmltrackelement = function (_eventtarget) {
_inherits(htmltrackelement, _eventtarget);
/**
* create an instance of this class.
*
* @param {object} options={}
* object of option names and values
*
* @param {tech} options.tech
* a reference to the tech that owns this htmltrackelement.
*
* @param {texttrack~kind} [options.kind='subtitles']
* a valid text track kind.
*
* @param {texttrack~mode} [options.mode='disabled']
* a valid text track mode.
*
* @param {string} [options.id='vjs_track_' + guid.newguid()]
* a unique id for this texttrack.
*
* @param {string} [options.label='']
* the menu label for this track.
*
* @param {string} [options.language='']
* a valid two character language code.
*
* @param {string} [options.srclang='']
* a valid two character language code. an alternative, but deprioritized
* vesion of `options.language`
*
* @param {string} [options.src]
* a url to texttrack cues.
*
* @param {boolean} [options.default]
* if this track should default to on or off.
*/
function htmltrackelement() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classcallcheck(this, htmltrackelement);
var _this = _possibleconstructorreturn(this, _eventtarget.call(this));
var readystate = void 0;
var trackelement = _this; // eslint-disable-line
if (browser.is_ie8) {
trackelement = _document2['default'].createelement('custom');
for (var prop in htmltrackelement.prototype) {
if (prop !== 'constructor') {
trackelement[prop] = htmltrackelement.prototype[prop];
}
}
}
var track = new _texttrack2['default'](options);
trackelement.kind = track.kind;
trackelement.src = track.src;
trackelement.srclang = track.language;
trackelement.label = track.label;
trackelement['default'] = track['default'];
/**
* @member {htmltrackelement~readystate} readystate
* the current ready state of the track element.
*/
object.defineproperty(trackelement, 'readystate', {
get: function get() {
return readystate;
}
});
/**
* @member {texttrack} track
* the underlying texttrack object.
*/
object.defineproperty(trackelement, 'track', {
get: function get() {
return track;
}
});
readystate = none;
/**
* @listens texttrack#loadeddata
* @fires htmltrackelement#load
*/
track.addeventlistener('loadeddata', function () {
readystate = loaded;
trackelement.trigger({
type: 'load',
target: trackelement
});
});
if (browser.is_ie8) {
var _ret;
return _ret = trackelement, _possibleconstructorreturn(_this, _ret);
}
return _this;
}
return htmltrackelement;
}(_eventtarget2['default']);
htmltrackelement.prototype.allowedevents_ = {
load: 'load'
};
htmltrackelement.none = none;
htmltrackelement.loading = loading;
htmltrackelement.loaded = loaded;
htmltrackelement.error = error;
exports['default'] = htmltrackelement;
},{"42":42,"72":72,"78":78,"94":94}],67:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
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; } }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } } /**
* @file text-track-cue-list.js
*/
/**
* @typedef {object} texttrackcue
*
* @property {string} id
* the unique id for this text track cue
*
* @property {number} starttime
* the start time for this text track cue
*
* @property {number} endtime
* the end time for this text track cue
*
* @property {boolean} pauseonexit
* pause when the end time is reached if true.
*
* @see [spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcue}
*/
/**
* a list of texttrackcues.
*
* @see [spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist}
*/
var texttrackcuelist = function () {
/**
* create an instance of this class..
*
* @param {array} cues
* a list of cues to be initialized with
*/
function texttrackcuelist(cues) {
_classcallcheck(this, texttrackcuelist);
var list = this; // eslint-disable-line
if (browser.is_ie8) {
list = _document2['default'].createelement('custom');
for (var prop in texttrackcuelist.prototype) {
if (prop !== 'constructor') {
list[prop] = texttrackcuelist.prototype[prop];
}
}
}
texttrackcuelist.prototype.setcues_.call(list, cues);
/**
* @member {number} length
* the current number of `texttrackcue`s in the texttrackcuelist.
*/
object.defineproperty(list, 'length', {
get: function get() {
return this.length_;
}
});
if (browser.is_ie8) {
return list;
}
}
/**
* a setter for cues in this list. creates getters
* an an index for the cues.
*
* @param {array} cues
* an array of cues to set
*
* @private
*/
texttrackcuelist.prototype.setcues_ = function setcues_(cues) {
var oldlength = this.length || 0;
var i = 0;
var l = cues.length;
this.cues_ = cues;
this.length_ = cues.length;
var defineprop = function defineprop(index) {
if (!('' + index in this)) {
object.defineproperty(this, '' + index, {
get: function get() {
return this.cues_[index];
}
});
}
};
if (oldlength < l) {
i = oldlength;
for (; i < l; i++) {
defineprop.call(this, i);
}
}
};
/**
* get a `texttrackcue` that is currently in the `texttrackcuelist` by id.
*
* @param {string} id
* the id of the cue that should be searched for.
*
* @return {texttrackcue|null}
* a single cue or null if none was found.
*/
texttrackcuelist.prototype.getcuebyid = function getcuebyid(id) {
var result = null;
for (var i = 0, l = this.length; i < l; i++) {
var cue = this[i];
if (cue.id === id) {
result = cue;
break;
}
}
return result;
};
return texttrackcuelist;
}();
exports['default'] = texttrackcuelist;
},{"78":78,"94":94}],68:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file text-track-display.js
*/
var darkgray = '#222';
var lightgray = '#ccc';
var fontmap = {
monospace: 'monospace',
sansserif: 'sans-serif',
serif: 'serif',
monospacesansserif: '"andale mono", "lucida console", monospace',
monospaceserif: '"courier new", monospace',
proportionalsansserif: 'sans-serif',
proportionalserif: 'serif',
casual: '"comic sans ms", impact, fantasy',
script: '"monotype corsiva", cursive',
smallcaps: '"andale mono", "lucida console", monospace, sans-serif'
};
/**
* construct an rgba color from a given hex color code.
*
* @param {number} color
* hex number for color, like #f0e.
*
* @param {number} opacity
* value for opacity, 0.0 - 1.0.
*
* @return {string}
* the rgba color that was created, like 'rgba(255, 0, 0, 0.3)'.
*
* @private
*/
function constructcolor(color, opacity) {
return 'rgba(' +
// color looks like "#f0e"
parseint(color[1] + color[1], 16) + ',' + parseint(color[2] + color[2], 16) + ',' + parseint(color[3] + color[3], 16) + ',' + opacity + ')';
}
/**
* try to update the style of a dom element. some style changes will throw an error,
* particularly in ie8. those should be noops.
*
* @param {element} el
* the dom element to be styled.
*
* @param {string} style
* the css property on the element that should be styled.
*
* @param {string} rule
* the style rule that should be applied to the property.
*/
function tryupdatestyle(el, style, rule) {
try {
el.style[style] = rule;
} catch (e) {
// satisfies linter.
return;
}
}
/**
* the component for displaying text track cues.
*
* @extends component
*/
var texttrackdisplay = function (_component) {
_inherits(texttrackdisplay, _component);
/**
* creates an instance of this class.
*
* @param {player} player
* the `player` that this class should be attached to.
*
* @param {object} [options]
* the key/value store of player options.
*
* @param {component~readycallback} [ready]
* the function to call when `texttrackdisplay` is ready.
*/
function texttrackdisplay(player, options, ready) {
_classcallcheck(this, texttrackdisplay);
var _this = _possibleconstructorreturn(this, _component.call(this, player, options, ready));
player.on('loadstart', fn.bind(_this, _this.toggledisplay));
player.on('texttrackchange', fn.bind(_this, _this.updatedisplay));
// this used to be called during player init, but was causing an error
// if a track should show by default and the display hadn't loaded yet.
// should probably be moved to an external track loader when we support
// tracks that don't need a display.
player.ready(fn.bind(_this, function () {
if (player.tech_ && player.tech_.featuresnativetexttracks) {
this.hide();
return;
}
player.on('fullscreenchange', fn.bind(this, this.updatedisplay));
var tracks = this.options_.playeroptions.tracks || [];
for (var i = 0; i < tracks.length; i++) {
this.player_.addremotetexttrack(tracks[i], true);
}
var modes = { captions: 1, subtitles: 1 };
var tracklist = this.player_.texttracks();
var firstdesc = void 0;
var firstcaptions = void 0;
if (tracklist) {
for (var _i = 0; _i < tracklist.length; _i++) {
var track = tracklist[_i];
if (track['default']) {
if (track.kind === 'descriptions' && !firstdesc) {
firstdesc = track;
} else if (track.kind in modes && !firstcaptions) {
firstcaptions = track;
}
}
}
// we want to show the first default track but captions and subtitles
// take precedence over descriptions.
// so, display the first default captions or subtitles track
// and otherwise the first default descriptions track.
if (firstcaptions) {
firstcaptions.mode = 'showing';
} else if (firstdesc) {
firstdesc.mode = 'showing';
}
}
}));
return _this;
}
/**
* turn display of {@link texttrack}'s from the current state into the other state.
* there are only two states:
* - 'shown'
* - 'hidden'
*
* @listens player#loadstart
*/
texttrackdisplay.prototype.toggledisplay = function toggledisplay() {
if (this.player_.tech_ && this.player_.tech_.featuresnativetexttracks) {
this.hide();
} else {
this.show();
}
};
/**
* create the {@link component}'s dom element.
*
* @return {element}
* the element that was created.
*/
texttrackdisplay.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-text-track-display'
}, {
'aria-live': 'off',
'aria-atomic': 'true'
});
};
/**
* clear all displayed {@link texttrack}s.
*/
texttrackdisplay.prototype.cleardisplay = function cleardisplay() {
if (typeof _window2['default'].webvtt === 'function') {
_window2['default'].webvtt.processcues(_window2['default'], [], this.el_);
}
};
/**
* update the displayed texttrack when a either a {@link player#texttrackchange} or
* a {@link player#fullscreenchange} is fired.
*
* @listens player#texttrackchange
* @listens player#fullscreenchange
*/
texttrackdisplay.prototype.updatedisplay = function updatedisplay() {
var tracks = this.player_.texttracks();
this.cleardisplay();
if (!tracks) {
return;
}
// track display prioritization model: if multiple tracks are 'showing',
// display the first 'subtitles' or 'captions' track which is 'showing',
// otherwise display the first 'descriptions' track which is 'showing'
var descriptionstrack = null;
var captionssubtitlestrack = null;
var i = tracks.length;
while (i--) {
var track = tracks[i];
if (track.mode === 'showing') {
if (track.kind === 'descriptions') {
descriptionstrack = track;
} else {
captionssubtitlestrack = track;
}
}
}
if (captionssubtitlestrack) {
if (this.getattribute('aria-live') !== 'off') {
this.setattribute('aria-live', 'off');
}
this.updatefortrack(captionssubtitlestrack);
} else if (descriptionstrack) {
if (this.getattribute('aria-live') !== 'assertive') {
this.setattribute('aria-live', 'assertive');
}
this.updatefortrack(descriptionstrack);
}
};
/**
* add an {@link texttrack} to to the {@link tech}s {@link texttracklist}.
*
* @param {texttrack} track
* text track object to be added to the list.
*/
texttrackdisplay.prototype.updatefortrack = function updatefortrack(track) {
if (typeof _window2['default'].webvtt !== 'function' || !track.activecues) {
return;
}
var overrides = this.player_.texttracksettings.getvalues();
var cues = [];
for (var _i2 = 0; _i2 < track.activecues.length; _i2++) {
cues.push(track.activecues[_i2]);
}
_window2['default'].webvtt.processcues(_window2['default'], cues, this.el_);
var i = cues.length;
while (i--) {
var cue = cues[i];
if (!cue) {
continue;
}
var cuediv = cue.displaystate;
if (overrides.color) {
cuediv.firstchild.style.color = overrides.color;
}
if (overrides.textopacity) {
tryupdatestyle(cuediv.firstchild, 'color', constructcolor(overrides.color || '#fff', overrides.textopacity));
}
if (overrides.backgroundcolor) {
cuediv.firstchild.style.backgroundcolor = overrides.backgroundcolor;
}
if (overrides.backgroundopacity) {
tryupdatestyle(cuediv.firstchild, 'backgroundcolor', constructcolor(overrides.backgroundcolor || '#000', overrides.backgroundopacity));
}
if (overrides.windowcolor) {
if (overrides.windowopacity) {
tryupdatestyle(cuediv, 'backgroundcolor', constructcolor(overrides.windowcolor, overrides.windowopacity));
} else {
cuediv.style.backgroundcolor = overrides.windowcolor;
}
}
if (overrides.edgestyle) {
if (overrides.edgestyle === 'dropshadow') {
cuediv.firstchild.style.textshadow = '2px 2px 3px ' + darkgray + ', 2px 2px 4px ' + darkgray + ', 2px 2px 5px ' + darkgray;
} else if (overrides.edgestyle === 'raised') {
cuediv.firstchild.style.textshadow = '1px 1px ' + darkgray + ', 2px 2px ' + darkgray + ', 3px 3px ' + darkgray;
} else if (overrides.edgestyle === 'depressed') {
cuediv.firstchild.style.textshadow = '1px 1px ' + lightgray + ', 0 1px ' + lightgray + ', -1px -1px ' + darkgray + ', 0 -1px ' + darkgray;
} else if (overrides.edgestyle === 'uniform') {
cuediv.firstchild.style.textshadow = '0 0 4px ' + darkgray + ', 0 0 4px ' + darkgray + ', 0 0 4px ' + darkgray + ', 0 0 4px ' + darkgray;
}
}
if (overrides.fontpercent && overrides.fontpercent !== 1) {
var fontsize = _window2['default'].parsefloat(cuediv.style.fontsize);
cuediv.style.fontsize = fontsize * overrides.fontpercent + 'px';
cuediv.style.height = 'auto';
cuediv.style.top = 'auto';
cuediv.style.bottom = '2px';
}
if (overrides.fontfamily && overrides.fontfamily !== 'default') {
if (overrides.fontfamily === 'small-caps') {
cuediv.firstchild.style.fontvariant = 'small-caps';
} else {
cuediv.firstchild.style.fontfamily = fontmap[overrides.fontfamily];
}
}
}
};
return texttrackdisplay;
}(_component2['default']);
_component2['default'].registercomponent('texttrackdisplay', texttrackdisplay);
exports['default'] = texttrackdisplay;
},{"5":5,"83":83,"95":95}],69:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
/**
* @file text-track-list-converter.js utilities for capturing text track state and
* re-creating tracks based on a capture.
*
* @module text-track-list-converter
*/
/**
* examine a single {@link texttrack} and return a json-compatible javascript object that
* represents the {@link texttrack}'s state.
*
* @param {texttrack} track
* the text track to query.
*
* @return {object}
* a serializable javascript representation of the texttrack.
* @private
*/
var tracktojson_ = function tracktojson_(track) {
var ret = ['kind', 'label', 'language', 'id', 'inbandmetadatatrackdispatchtype', 'mode', 'src'].reduce(function (acc, prop, i) {
if (track[prop]) {
acc[prop] = track[prop];
}
return acc;
}, {
cues: track.cues && array.prototype.map.call(track.cues, function (cue) {
return {
starttime: cue.starttime,
endtime: cue.endtime,
text: cue.text,
id: cue.id
};
})
});
return ret;
};
/**
* examine a {@link tech} and return a json-compatible javascript array that represents the
* state of all {@link texttrack}s currently configured. the return array is compatible with
* {@link text-track-list-converter:jsontotexttracks}.
*
* @param {tech} tech
* the tech object to query
*
* @return {array}
* a serializable javascript representation of the {@link tech}s
* {@link texttracklist}.
*/
var texttrackstojson = function texttrackstojson(tech) {
var trackels = tech.$$('track');
var trackobjs = array.prototype.map.call(trackels, function (t) {
return t.track;
});
var tracks = array.prototype.map.call(trackels, function (trackel) {
var json = tracktojson_(trackel.track);
if (trackel.src) {
json.src = trackel.src;
}
return json;
});
return tracks.concat(array.prototype.filter.call(tech.texttracks(), function (track) {
return trackobjs.indexof(track) === -1;
}).map(tracktojson_));
};
/**
* create a set of remote {@link texttrack}s on a {@link tech} based on an array of javascript
* object {@link texttrack} representations.
*
* @param {array} json
* an array of `texttrack` representation objects, like those that would be
* produced by `texttrackstojson`.
*
* @param {tech} tech
* the `tech` to create the `texttrack`s on.
*/
var jsontotexttracks = function jsontotexttracks(json, tech) {
json.foreach(function (track) {
var addedtrack = tech.addremotetexttrack(track).track;
if (!track.src && track.cues) {
track.cues.foreach(function (cue) {
return addedtrack.addcue(cue);
});
}
});
return tech.texttracks();
};
exports['default'] = { texttrackstojson: texttrackstojson, jsontotexttracks: jsontotexttracks, tracktojson_: tracktojson_ };
},{}],70:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _tracklist = _dereq_(74);
var _tracklist2 = _interoprequiredefault(_tracklist);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _browser = _dereq_(78);
var browser = _interoprequirewildcard(_browser);
var _document = _dereq_(94);
var _document2 = _interoprequiredefault(_document);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file text-track-list.js
*/
/**
* the current list of {@link texttrack} for a media file.
*
* @see [spec]{@link https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist}
* @extends tracklist
*/
var texttracklist = function (_tracklist) {
_inherits(texttracklist, _tracklist);
/**
* create an instance of this class.
*
* @param {texttrack[]} [tracks=[]]
* a list of `texttrack` to instantiate the list with.
*/
function texttracklist() {
var _this, _ret;
var tracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
_classcallcheck(this, texttracklist);
var list = void 0;
// ie8 forces us to implement inheritance ourselves
// as it does not support object.defineproperty properly
if (browser.is_ie8) {
list = _document2['default'].createelement('custom');
for (var prop in _tracklist2['default'].prototype) {
if (prop !== 'constructor') {
list[prop] = _tracklist2['default'].prototype[prop];
}
}
for (var _prop in texttracklist.prototype) {
if (_prop !== 'constructor') {
list[_prop] = texttracklist.prototype[_prop];
}
}
}
list = (_this = _possibleconstructorreturn(this, _tracklist.call(this, tracks, list)), _this);
return _ret = list, _possibleconstructorreturn(_this, _ret);
}
/**
* add a {@link texttrack} to the `texttracklist`
*
* @param {texttrack} track
* the text track to add to the list.
*
* @fires tracklist#addtrack
* @private
*/
texttracklist.prototype.addtrack_ = function addtrack_(track) {
_tracklist.prototype.addtrack_.call(this, track);
/**
* @listens texttrack#modechange
* @fires tracklist#change
*/
track.addeventlistener('modechange', fn.bind(this, function () {
this.trigger('change');
}));
};
return texttracklist;
}(_tracklist2['default']);
exports['default'] = texttracklist;
},{"74":74,"78":78,"83":83,"94":94}],71:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
var _window = _dereq_(95);
var _window2 = _interoprequiredefault(_window);
var _component = _dereq_(5);
var _component2 = _interoprequiredefault(_component);
var _dom = _dereq_(81);
var _fn = _dereq_(83);
var fn = _interoprequirewildcard(_fn);
var _obj = _dereq_(88);
var obj = _interoprequirewildcard(_obj);
var _log = _dereq_(86);
var _log2 = _interoprequiredefault(_log);
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; } }
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
function _classcallcheck(instance, constructor) { if (!(instance instanceof constructor)) { throw new typeerror("cannot call a class as a function"); } }
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; }
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; } /**
* @file text-track-settings.js
*/
var local_storage_key = 'vjs-text-track-settings';
var color_black = ['#000', 'black'];
var color_blue = ['#00f', 'blue'];
var color_cyan = ['#0ff', 'cyan'];
var color_green = ['#0f0', 'green'];
var color_magenta = ['#f0f', 'magenta'];
var color_red = ['#f00', 'red'];
var color_white = ['#fff', 'white'];
var color_yellow = ['#ff0', 'yellow'];
var opacity_opaque = ['1', 'opaque'];
var opacity_semi = ['0.5', 'semi-transparent'];
var opacity_trans = ['0', 'transparent'];
// configuration for the various