/**
* @license
* video.js 5.8.8
* 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 logs the number of milliseconds it took for the deferred function to be invoked
*/
var now = nativenow || function() {
return new date().gettime();
};
module.exports = now;
},{"../internal/getnative":20}],5:[function(_dereq_,module,exports){
var isobject = _dereq_('../lang/isobject'),
now = _dereq_('../date/now');
/** used as the `typeerror` message for "functions" methods. */
var func_error_text = 'expected a function';
/* native method references for those with the same name as other `lodash` methods. */
var nativemax = math.max;
/**
* creates a debounced function that delays invoking `func` until after `wait`
* milliseconds have elapsed since the last time the debounced function was
* invoked. the debounced function comes with a `cancel` method to cancel
* delayed invocations. provide an options object to indicate that `func`
* should be invoked on the leading and/or trailing edge of the `wait` timeout.
* subsequent calls to the debounced function return the result of the last
* `func` invocation.
*
* **note:** if `leading` and `trailing` options are `true`, `func` is invoked
* on the trailing edge of the timeout only if the the debounced function is
* invoked more than once during the `wait` timeout.
*
* see [david corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
* for details over the differences between `_.debounce` and `_.throttle`.
*
* @static
* @memberof _
* @category function
* @param {function} func the function to debounce.
* @param {number} [wait=0] the number of milliseconds to delay.
* @param {object} [options] the options object.
* @param {boolean} [options.leading=false] specify invoking on the leading
* edge of the timeout.
* @param {number} [options.maxwait] the maximum time `func` is allowed to be
* delayed before it's invoked.
* @param {boolean} [options.trailing=true] specify invoking on the trailing
* edge of the timeout.
* @returns {function} returns the new debounced function.
* @example
*
* // avoid costly calculations while the window size is in flux
* jquery(window).on('resize', _.debounce(calculatelayout, 150));
*
* // invoke `sendmail` when the click event is fired, debouncing subsequent calls
* jquery('#postbox').on('click', _.debounce(sendmail, 300, {
* 'leading': true,
* 'trailing': false
* }));
*
* // ensure `batchlog` is invoked once after 1 second of debounced calls
* var source = new eventsource('/stream');
* jquery(source).on('message', _.debounce(batchlog, 250, {
* 'maxwait': 1000
* }));
*
* // cancel a debounced call
* var todochanges = _.debounce(batchlog, 1000);
* object.observe(models.todo, todochanges);
*
* object.observe(models, function(changes) {
* if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
* todochanges.cancel();
* }
* }, ['delete']);
*
* // ...at some point `models.todo` is changed
* models.todo.completed = true;
*
* // ...before 1 second has passed `models.todo` is deleted
* // which cancels the debounced `todochanges` call
* delete models.todo;
*/
function debounce(func, wait, options) {
var args,
maxtimeoutid,
result,
stamp,
thisarg,
timeoutid,
trailingcall,
lastcalled = 0,
maxwait = false,
trailing = true;
if (typeof func != 'function') {
throw new typeerror(func_error_text);
}
wait = wait < 0 ? 0 : (+wait || 0);
if (options === true) {
var leading = true;
trailing = false;
} else if (isobject(options)) {
leading = !!options.leading;
maxwait = 'maxwait' in options && nativemax(+options.maxwait || 0, wait);
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function cancel() {
if (timeoutid) {
cleartimeout(timeoutid);
}
if (maxtimeoutid) {
cleartimeout(maxtimeoutid);
}
lastcalled = 0;
maxtimeoutid = timeoutid = trailingcall = undefined;
}
function complete(iscalled, id) {
if (id) {
cleartimeout(id);
}
maxtimeoutid = timeoutid = trailingcall = undefined;
if (iscalled) {
lastcalled = now();
result = func.apply(thisarg, args);
if (!timeoutid && !maxtimeoutid) {
args = thisarg = undefined;
}
}
}
function delayed() {
var remaining = wait - (now() - stamp);
if (remaining <= 0 || remaining > wait) {
complete(trailingcall, maxtimeoutid);
} else {
timeoutid = settimeout(delayed, remaining);
}
}
function maxdelayed() {
complete(trailing, timeoutid);
}
function debounced() {
args = arguments;
stamp = now();
thisarg = this;
trailingcall = trailing && (timeoutid || !leading);
if (maxwait === false) {
var leadingcall = leading && !timeoutid;
} else {
if (!maxtimeoutid && !leading) {
lastcalled = stamp;
}
var remaining = maxwait - (stamp - lastcalled),
iscalled = remaining <= 0 || remaining > maxwait;
if (iscalled) {
if (maxtimeoutid) {
maxtimeoutid = cleartimeout(maxtimeoutid);
}
lastcalled = stamp;
result = func.apply(thisarg, args);
}
else if (!maxtimeoutid) {
maxtimeoutid = settimeout(maxdelayed, remaining);
}
}
if (iscalled && timeoutid) {
timeoutid = cleartimeout(timeoutid);
}
else if (!timeoutid && wait !== maxwait) {
timeoutid = settimeout(delayed, wait);
}
if (leadingcall) {
iscalled = true;
result = func.apply(thisarg, args);
}
if (iscalled && !timeoutid && !maxtimeoutid) {
args = thisarg = undefined;
}
return result;
}
debounced.cancel = cancel;
return debounced;
}
module.exports = debounce;
},{"../date/now":4,"../lang/isobject":33}],6:[function(_dereq_,module,exports){
/** used as the `typeerror` message for "functions" methods. */
var func_error_text = 'expected a function';
/* native method references for those with the same name as other `lodash` methods. */
var nativemax = math.max;
/**
* creates a function that invokes `func` with the `this` binding of the
* created function and arguments from `start` and beyond provided as an array.
*
* **note:** this method is based on the [rest parameter](https://developer.mozilla.org/web/javascript/reference/functions/rest_parameters).
*
* @static
* @memberof _
* @category function
* @param {function} func the function to apply a rest parameter to.
* @param {number} [start=func.length-1] the start position of the rest parameter.
* @returns {function} returns the new function.
* @example
*
* var say = _.restparam(function(what, names) {
* return what + ' ' + _.initial(names).join(', ') +
* (_.size(names) > 1 ? ', & ' : '') + _.last(names);
* });
*
* say('hello', 'fred', 'barney', 'pebbles');
* // => 'hello fred, barney, & pebbles'
*/
function restparam(func, start) {
if (typeof func != 'function') {
throw new typeerror(func_error_text);
}
start = nativemax(start === undefined ? (func.length - 1) : (+start || 0), 0);
return function() {
var args = arguments,
index = -1,
length = nativemax(args.length - start, 0),
rest = array(length);
while (++index < length) {
rest[index] = args[start + index];
}
switch (start) {
case 0: return func.call(this, rest);
case 1: return func.call(this, args[0], rest);
case 2: return func.call(this, args[0], args[1], rest);
}
var otherargs = array(start + 1);
index = -1;
while (++index < start) {
otherargs[index] = args[index];
}
otherargs[start] = rest;
return func.apply(this, otherargs);
};
}
module.exports = restparam;
},{}],7:[function(_dereq_,module,exports){
var debounce = _dereq_('./debounce'),
isobject = _dereq_('../lang/isobject');
/** used as the `typeerror` message for "functions" methods. */
var func_error_text = 'expected a function';
/**
* creates a throttled function that only invokes `func` at most once per
* every `wait` milliseconds. the throttled function comes with a `cancel`
* method to cancel delayed invocations. provide an options object to indicate
* that `func` should be invoked on the leading and/or trailing edge of the
* `wait` timeout. subsequent calls to the throttled function return the
* result of the last `func` call.
*
* **note:** if `leading` and `trailing` options are `true`, `func` is invoked
* on the trailing edge of the timeout only if the the throttled function is
* invoked more than once during the `wait` timeout.
*
* see [david corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
* for details over the differences between `_.throttle` and `_.debounce`.
*
* @static
* @memberof _
* @category function
* @param {function} func the function to throttle.
* @param {number} [wait=0] the number of milliseconds to throttle invocations to.
* @param {object} [options] the options object.
* @param {boolean} [options.leading=true] specify invoking on the leading
* edge of the timeout.
* @param {boolean} [options.trailing=true] specify invoking on the trailing
* edge of the timeout.
* @returns {function} returns the new throttled function.
* @example
*
* // avoid excessively updating the position while scrolling
* jquery(window).on('scroll', _.throttle(updateposition, 100));
*
* // invoke `renewtoken` when the click event is fired, but not more than once every 5 minutes
* jquery('.interactive').on('click', _.throttle(renewtoken, 300000, {
* 'trailing': false
* }));
*
* // cancel a trailing throttled call
* jquery(window).on('popstate', throttled.cancel);
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (typeof func != 'function') {
throw new typeerror(func_error_text);
}
if (options === false) {
leading = false;
} else if (isobject(options)) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
return debounce(func, wait, { 'leading': leading, 'maxwait': +wait, 'trailing': trailing });
}
module.exports = throttle;
},{"../lang/isobject":33,"./debounce":5}],8:[function(_dereq_,module,exports){
/**
* copies the values of `source` to `array`.
*
* @private
* @param {array} source the array to copy values from.
* @param {array} [array=[]] the array to copy values to.
* @returns {array} returns `array`.
*/
function arraycopy(source, array) {
var index = -1,
length = source.length;
array || (array = array(length));
while (++index < length) {
array[index] = source[index];
}
return array;
}
module.exports = arraycopy;
},{}],9:[function(_dereq_,module,exports){
/**
* a specialized version of `_.foreach` for arrays without support for callback
* shorthands and `this` binding.
*
* @private
* @param {array} array the array to iterate over.
* @param {function} iteratee the function invoked per iteration.
* @returns {array} returns `array`.
*/
function arrayeach(array, iteratee) {
var index = -1,
length = array.length;
while (++index < length) {
if (iteratee(array[index], index, array) === false) {
break;
}
}
return array;
}
module.exports = arrayeach;
},{}],10:[function(_dereq_,module,exports){
/**
* copies properties of `source` to `object`.
*
* @private
* @param {object} source the object to copy properties from.
* @param {array} props the property names to copy.
* @param {object} [object={}] the object to copy properties to.
* @returns {object} returns `object`.
*/
function basecopy(source, props, object) {
object || (object = {});
var index = -1,
length = props.length;
while (++index < length) {
var key = props[index];
object[key] = source[key];
}
return object;
}
module.exports = basecopy;
},{}],11:[function(_dereq_,module,exports){
var createbasefor = _dereq_('./createbasefor');
/**
* the base implementation of `baseforin` and `baseforown` which iterates
* over `object` properties returned by `keysfunc` invoking `iteratee` for
* each property. iteratee functions may exit iteration early by explicitly
* returning `false`.
*
* @private
* @param {object} object the object to iterate over.
* @param {function} iteratee the function invoked per iteration.
* @param {function} keysfunc the function to get the keys of `object`.
* @returns {object} returns `object`.
*/
var basefor = createbasefor();
module.exports = basefor;
},{"./createbasefor":18}],12:[function(_dereq_,module,exports){
var basefor = _dereq_('./basefor'),
keysin = _dereq_('../object/keysin');
/**
* the base implementation of `_.forin` without support for callback
* shorthands and `this` binding.
*
* @private
* @param {object} object the object to iterate over.
* @param {function} iteratee the function invoked per iteration.
* @returns {object} returns `object`.
*/
function baseforin(object, iteratee) {
return basefor(object, iteratee, keysin);
}
module.exports = baseforin;
},{"../object/keysin":39,"./basefor":11}],13:[function(_dereq_,module,exports){
var arrayeach = _dereq_('./arrayeach'),
basemergedeep = _dereq_('./basemergedeep'),
isarray = _dereq_('../lang/isarray'),
isarraylike = _dereq_('./isarraylike'),
isobject = _dereq_('../lang/isobject'),
isobjectlike = _dereq_('./isobjectlike'),
istypedarray = _dereq_('../lang/istypedarray'),
keys = _dereq_('../object/keys');
/**
* the base implementation of `_.merge` without support for argument juggling,
* multiple sources, and `this` binding `customizer` functions.
*
* @private
* @param {object} object the destination object.
* @param {object} source the source object.
* @param {function} [customizer] the function to customize merged values.
* @param {array} [stacka=[]] tracks traversed source objects.
* @param {array} [stackb=[]] associates values with source counterparts.
* @returns {object} returns `object`.
*/
function basemerge(object, source, customizer, stacka, stackb) {
if (!isobject(object)) {
return object;
}
var issrcarr = isarraylike(source) && (isarray(source) || istypedarray(source)),
props = issrcarr ? undefined : keys(source);
arrayeach(props || source, function(srcvalue, key) {
if (props) {
key = srcvalue;
srcvalue = source[key];
}
if (isobjectlike(srcvalue)) {
stacka || (stacka = []);
stackb || (stackb = []);
basemergedeep(object, source, key, basemerge, customizer, stacka, stackb);
}
else {
var value = object[key],
result = customizer ? customizer(value, srcvalue, key, object, source) : undefined,
iscommon = result === undefined;
if (iscommon) {
result = srcvalue;
}
if ((result !== undefined || (issrcarr && !(key in object))) &&
(iscommon || (result === result ? (result !== value) : (value === value)))) {
object[key] = result;
}
}
});
return object;
}
module.exports = basemerge;
},{"../lang/isarray":30,"../lang/isobject":33,"../lang/istypedarray":36,"../object/keys":38,"./arrayeach":9,"./basemergedeep":14,"./isarraylike":21,"./isobjectlike":26}],14:[function(_dereq_,module,exports){
var arraycopy = _dereq_('./arraycopy'),
isarguments = _dereq_('../lang/isarguments'),
isarray = _dereq_('../lang/isarray'),
isarraylike = _dereq_('./isarraylike'),
isplainobject = _dereq_('../lang/isplainobject'),
istypedarray = _dereq_('../lang/istypedarray'),
toplainobject = _dereq_('../lang/toplainobject');
/**
* a specialized version of `basemerge` for arrays and objects which performs
* deep merges and tracks traversed objects enabling objects with circular
* references to be merged.
*
* @private
* @param {object} object the destination object.
* @param {object} source the source object.
* @param {string} key the key of the value to merge.
* @param {function} mergefunc the function to merge values.
* @param {function} [customizer] the function to customize merged values.
* @param {array} [stacka=[]] tracks traversed source objects.
* @param {array} [stackb=[]] associates values with source counterparts.
* @returns {boolean} returns `true` if the objects are equivalent, else `false`.
*/
function basemergedeep(object, source, key, mergefunc, customizer, stacka, stackb) {
var length = stacka.length,
srcvalue = source[key];
while (length--) {
if (stacka[length] == srcvalue) {
object[key] = stackb[length];
return;
}
}
var value = object[key],
result = customizer ? customizer(value, srcvalue, key, object, source) : undefined,
iscommon = result === undefined;
if (iscommon) {
result = srcvalue;
if (isarraylike(srcvalue) && (isarray(srcvalue) || istypedarray(srcvalue))) {
result = isarray(value)
? value
: (isarraylike(value) ? arraycopy(value) : []);
}
else if (isplainobject(srcvalue) || isarguments(srcvalue)) {
result = isarguments(value)
? toplainobject(value)
: (isplainobject(value) ? value : {});
}
else {
iscommon = false;
}
}
// add the source value to the stack of traversed objects and associate
// it with its merged value.
stacka.push(srcvalue);
stackb.push(result);
if (iscommon) {
// recursively merge objects and arrays (susceptible to call stack limits).
object[key] = mergefunc(result, srcvalue, customizer, stacka, stackb);
} else if (result === result ? (result !== value) : (value === value)) {
object[key] = result;
}
}
module.exports = basemergedeep;
},{"../lang/isarguments":29,"../lang/isarray":30,"../lang/isplainobject":34,"../lang/istypedarray":36,"../lang/toplainobject":37,"./arraycopy":8,"./isarraylike":21}],15:[function(_dereq_,module,exports){
var toobject = _dereq_('./toobject');
/**
* the base implementation of `_.property` without support for deep paths.
*
* @private
* @param {string} key the key of the property to get.
* @returns {function} returns the new function.
*/
function baseproperty(key) {
return function(object) {
return object == null ? undefined : toobject(object)[key];
};
}
module.exports = baseproperty;
},{"./toobject":28}],16:[function(_dereq_,module,exports){
var identity = _dereq_('../utility/identity');
/**
* a specialized version of `basecallback` which only supports `this` binding
* and specifying the number of arguments to provide to `func`.
*
* @private
* @param {function} func the function to bind.
* @param {*} thisarg the `this` binding of `func`.
* @param {number} [argcount] the number of arguments to provide to `func`.
* @returns {function} returns the callback.
*/
function bindcallback(func, thisarg, argcount) {
if (typeof func != 'function') {
return identity;
}
if (thisarg === undefined) {
return func;
}
switch (argcount) {
case 1: return function(value) {
return func.call(thisarg, value);
};
case 3: return function(value, index, collection) {
return func.call(thisarg, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(thisarg, accumulator, value, index, collection);
};
case 5: return function(value, other, key, object, source) {
return func.call(thisarg, value, other, key, object, source);
};
}
return function() {
return func.apply(thisarg, arguments);
};
}
module.exports = bindcallback;
},{"../utility/identity":42}],17:[function(_dereq_,module,exports){
var bindcallback = _dereq_('./bindcallback'),
isiterateecall = _dereq_('./isiterateecall'),
restparam = _dereq_('../function/restparam');
/**
* creates a `_.assign`, `_.defaults`, or `_.merge` function.
*
* @private
* @param {function} assigner the function to assign values.
* @returns {function} returns the new assigner function.
*/
function createassigner(assigner) {
return restparam(function(object, sources) {
var index = -1,
length = object == null ? 0 : sources.length,
customizer = length > 2 ? sources[length - 2] : undefined,
guard = length > 2 ? sources[2] : undefined,
thisarg = length > 1 ? sources[length - 1] : undefined;
if (typeof customizer == 'function') {
customizer = bindcallback(customizer, thisarg, 5);
length -= 2;
} else {
customizer = typeof thisarg == 'function' ? thisarg : undefined;
length -= (customizer ? 1 : 0);
}
if (guard && isiterateecall(sources[0], sources[1], guard)) {
customizer = length < 3 ? undefined : customizer;
length = 1;
}
while (++index < length) {
var source = sources[index];
if (source) {
assigner(object, source, customizer);
}
}
return object;
});
}
module.exports = createassigner;
},{"../function/restparam":6,"./bindcallback":16,"./isiterateecall":24}],18:[function(_dereq_,module,exports){
var toobject = _dereq_('./toobject');
/**
* creates a base function for `_.forin` or `_.forinright`.
*
* @private
* @param {boolean} [fromright] specify iterating from right to left.
* @returns {function} returns the new base function.
*/
function createbasefor(fromright) {
return function(object, iteratee, keysfunc) {
var iterable = toobject(object),
props = keysfunc(object),
length = props.length,
index = fromright ? length : -1;
while ((fromright ? index-- : ++index < length)) {
var key = props[index];
if (iteratee(iterable[key], key, iterable) === false) {
break;
}
}
return object;
};
}
module.exports = createbasefor;
},{"./toobject":28}],19:[function(_dereq_,module,exports){
var baseproperty = _dereq_('./baseproperty');
/**
* gets the "length" property value of `object`.
*
* **note:** this function is used to avoid a [jit bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
* that affects safari on at least ios 8.1-8.3 arm64.
*
* @private
* @param {object} object the object to query.
* @returns {*} returns the "length" value.
*/
var getlength = baseproperty('length');
module.exports = getlength;
},{"./baseproperty":15}],20:[function(_dereq_,module,exports){
var isnative = _dereq_('../lang/isnative');
/**
* gets the native function at `key` of `object`.
*
* @private
* @param {object} object the object to query.
* @param {string} key the key of the method to get.
* @returns {*} returns the function if it's native, else `undefined`.
*/
function getnative(object, key) {
var value = object == null ? undefined : object[key];
return isnative(value) ? value : undefined;
}
module.exports = getnative;
},{"../lang/isnative":32}],21:[function(_dereq_,module,exports){
var getlength = _dereq_('./getlength'),
islength = _dereq_('./islength');
/**
* checks if `value` is array-like.
*
* @private
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is array-like, else `false`.
*/
function isarraylike(value) {
return value != null && islength(getlength(value));
}
module.exports = isarraylike;
},{"./getlength":19,"./islength":25}],22:[function(_dereq_,module,exports){
/**
* checks if `value` is a host object in ie < 9.
*
* @private
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is a host object, else `false`.
*/
var ishostobject = (function() {
try {
object({ 'tostring': 0 } + '');
} catch(e) {
return function() { return false; };
}
return function(value) {
// ie < 9 presents many host objects as `object` objects that can coerce
// to strings despite having improperly defined `tostring` methods.
return typeof value.tostring != 'function' && typeof (value + '') == 'string';
};
}());
module.exports = ishostobject;
},{}],23:[function(_dereq_,module,exports){
/** used to detect unsigned integer values. */
var reisuint = /^\d+$/;
/**
* used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
* of an array-like value.
*/
var max_safe_integer = 9007199254740991;
/**
* checks if `value` is a valid array-like index.
*
* @private
* @param {*} value the value to check.
* @param {number} [length=max_safe_integer] the upper bounds of a valid index.
* @returns {boolean} returns `true` if `value` is a valid index, else `false`.
*/
function isindex(value, length) {
value = (typeof value == 'number' || reisuint.test(value)) ? +value : -1;
length = length == null ? max_safe_integer : length;
return value > -1 && value % 1 == 0 && value < length;
}
module.exports = isindex;
},{}],24:[function(_dereq_,module,exports){
var isarraylike = _dereq_('./isarraylike'),
isindex = _dereq_('./isindex'),
isobject = _dereq_('../lang/isobject');
/**
* checks if the provided arguments are from an iteratee call.
*
* @private
* @param {*} value the potential iteratee value argument.
* @param {*} index the potential iteratee index or key argument.
* @param {*} object the potential iteratee object argument.
* @returns {boolean} returns `true` if the arguments are from an iteratee call, else `false`.
*/
function isiterateecall(value, index, object) {
if (!isobject(object)) {
return false;
}
var type = typeof index;
if (type == 'number'
? (isarraylike(object) && isindex(index, object.length))
: (type == 'string' && index in object)) {
var other = object[index];
return value === value ? (value === other) : (other !== other);
}
return false;
}
module.exports = isiterateecall;
},{"../lang/isobject":33,"./isarraylike":21,"./isindex":23}],25:[function(_dereq_,module,exports){
/**
* used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
* of an array-like value.
*/
var max_safe_integer = 9007199254740991;
/**
* checks if `value` is a valid array-like length.
*
* **note:** this function is based on [`tolength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
*
* @private
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is a valid length, else `false`.
*/
function islength(value) {
return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= max_safe_integer;
}
module.exports = islength;
},{}],26:[function(_dereq_,module,exports){
/**
* checks if `value` is object-like.
*
* @private
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is object-like, else `false`.
*/
function isobjectlike(value) {
return !!value && typeof value == 'object';
}
module.exports = isobjectlike;
},{}],27:[function(_dereq_,module,exports){
var isarguments = _dereq_('../lang/isarguments'),
isarray = _dereq_('../lang/isarray'),
isindex = _dereq_('./isindex'),
islength = _dereq_('./islength'),
isstring = _dereq_('../lang/isstring'),
keysin = _dereq_('../object/keysin');
/** used for native method references. */
var objectproto = object.prototype;
/** used to check objects for own properties. */
var hasownproperty = objectproto.hasownproperty;
/**
* a fallback implementation of `object.keys` which creates an array of the
* own enumerable property names of `object`.
*
* @private
* @param {object} object the object to query.
* @returns {array} returns the array of property names.
*/
function shimkeys(object) {
var props = keysin(object),
propslength = props.length,
length = propslength && object.length;
var allowindexes = !!length && islength(length) &&
(isarray(object) || isarguments(object) || isstring(object));
var index = -1,
result = [];
while (++index < propslength) {
var key = props[index];
if ((allowindexes && isindex(key, length)) || hasownproperty.call(object, key)) {
result.push(key);
}
}
return result;
}
module.exports = shimkeys;
},{"../lang/isarguments":29,"../lang/isarray":30,"../lang/isstring":35,"../object/keysin":39,"./isindex":23,"./islength":25}],28:[function(_dereq_,module,exports){
var isobject = _dereq_('../lang/isobject'),
isstring = _dereq_('../lang/isstring'),
support = _dereq_('../support');
/**
* converts `value` to an object if it's not one.
*
* @private
* @param {*} value the value to process.
* @returns {object} returns the object.
*/
function toobject(value) {
if (support.unindexedchars && isstring(value)) {
var index = -1,
length = value.length,
result = object(value);
while (++index < length) {
result[index] = value.charat(index);
}
return result;
}
return isobject(value) ? value : object(value);
}
module.exports = toobject;
},{"../lang/isobject":33,"../lang/isstring":35,"../support":41}],29:[function(_dereq_,module,exports){
var isarraylike = _dereq_('../internal/isarraylike'),
isobjectlike = _dereq_('../internal/isobjectlike');
/** used for native method references. */
var objectproto = object.prototype;
/** used to check objects for own properties. */
var hasownproperty = objectproto.hasownproperty;
/** native method references. */
var propertyisenumerable = objectproto.propertyisenumerable;
/**
* checks if `value` is classified as an `arguments` object.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is correctly classified, else `false`.
* @example
*
* _.isarguments(function() { return arguments; }());
* // => true
*
* _.isarguments([1, 2, 3]);
* // => false
*/
function isarguments(value) {
return isobjectlike(value) && isarraylike(value) &&
hasownproperty.call(value, 'callee') && !propertyisenumerable.call(value, 'callee');
}
module.exports = isarguments;
},{"../internal/isarraylike":21,"../internal/isobjectlike":26}],30:[function(_dereq_,module,exports){
var getnative = _dereq_('../internal/getnative'),
islength = _dereq_('../internal/islength'),
isobjectlike = _dereq_('../internal/isobjectlike');
/** `object#tostring` result references. */
var arraytag = '[object array]';
/** used for native method references. */
var objectproto = object.prototype;
/**
* used to resolve the [`tostringtag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objtostring = objectproto.tostring;
/* native method references for those with the same name as other `lodash` methods. */
var nativeisarray = getnative(array, 'isarray');
/**
* checks if `value` is classified as an `array` object.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is correctly classified, else `false`.
* @example
*
* _.isarray([1, 2, 3]);
* // => true
*
* _.isarray(function() { return arguments; }());
* // => false
*/
var isarray = nativeisarray || function(value) {
return isobjectlike(value) && islength(value.length) && objtostring.call(value) == arraytag;
};
module.exports = isarray;
},{"../internal/getnative":20,"../internal/islength":25,"../internal/isobjectlike":26}],31:[function(_dereq_,module,exports){
var isobject = _dereq_('./isobject');
/** `object#tostring` result references. */
var functag = '[object function]';
/** used for native method references. */
var objectproto = object.prototype;
/**
* used to resolve the [`tostringtag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objtostring = objectproto.tostring;
/**
* checks if `value` is classified as a `function` object.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is correctly classified, else `false`.
* @example
*
* _.isfunction(_);
* // => true
*
* _.isfunction(/abc/);
* // => false
*/
function isfunction(value) {
// the use of `object#tostring` avoids issues with the `typeof` operator
// in older versions of chrome and safari which return 'function' for regexes
// and safari 8 which returns 'object' for typed array constructors.
return isobject(value) && objtostring.call(value) == functag;
}
module.exports = isfunction;
},{"./isobject":33}],32:[function(_dereq_,module,exports){
var isfunction = _dereq_('./isfunction'),
ishostobject = _dereq_('../internal/ishostobject'),
isobjectlike = _dereq_('../internal/isobjectlike');
/** used to detect host constructors (safari > 5). */
var reishostctor = /^\[object .+?constructor\]$/;
/** used for native method references. */
var objectproto = object.prototype;
/** used to resolve the decompiled source of functions. */
var fntostring = function.prototype.tostring;
/** used to check objects for own properties. */
var hasownproperty = objectproto.hasownproperty;
/** used to detect if a method is native. */
var reisnative = regexp('^' +
fntostring.call(hasownproperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
.replace(/hasownproperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
/**
* checks if `value` is a native function.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is a native function, else `false`.
* @example
*
* _.isnative(array.prototype.push);
* // => true
*
* _.isnative(_);
* // => false
*/
function isnative(value) {
if (value == null) {
return false;
}
if (isfunction(value)) {
return reisnative.test(fntostring.call(value));
}
return isobjectlike(value) && (ishostobject(value) ? reisnative : reishostctor).test(value);
}
module.exports = isnative;
},{"../internal/ishostobject":22,"../internal/isobjectlike":26,"./isfunction":31}],33:[function(_dereq_,module,exports){
/**
* checks if `value` is the [language type](https://es5.github.io/#x8) of `object`.
* (e.g. arrays, functions, objects, regexes, `new number(0)`, and `new string('')`)
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is an object, else `false`.
* @example
*
* _.isobject({});
* // => true
*
* _.isobject([1, 2, 3]);
* // => true
*
* _.isobject(1);
* // => false
*/
function isobject(value) {
// avoid a v8 jit bug in chrome 19-20.
// see https://code.google.com/p/v8/issues/detail?id=2291 for more details.
var type = typeof value;
return !!value && (type == 'object' || type == 'function');
}
module.exports = isobject;
},{}],34:[function(_dereq_,module,exports){
var baseforin = _dereq_('../internal/baseforin'),
isarguments = _dereq_('./isarguments'),
ishostobject = _dereq_('../internal/ishostobject'),
isobjectlike = _dereq_('../internal/isobjectlike'),
support = _dereq_('../support');
/** `object#tostring` result references. */
var objecttag = '[object object]';
/** used for native method references. */
var objectproto = object.prototype;
/** used to check objects for own properties. */
var hasownproperty = objectproto.hasownproperty;
/**
* used to resolve the [`tostringtag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objtostring = objectproto.tostring;
/**
* checks if `value` is a plain object, that is, an object created by the
* `object` constructor or one with a `[[prototype]]` of `null`.
*
* **note:** this method assumes objects created by the `object` constructor
* have no inherited enumerable properties.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is a plain object, else `false`.
* @example
*
* function foo() {
* this.a = 1;
* }
*
* _.isplainobject(new foo);
* // => false
*
* _.isplainobject([1, 2, 3]);
* // => false
*
* _.isplainobject({ 'x': 0, 'y': 0 });
* // => true
*
* _.isplainobject(object.create(null));
* // => true
*/
function isplainobject(value) {
var ctor;
// exit early for non `object` objects.
if (!(isobjectlike(value) && objtostring.call(value) == objecttag && !ishostobject(value) && !isarguments(value)) ||
(!hasownproperty.call(value, 'constructor') && (ctor = value.constructor, typeof ctor == 'function' && !(ctor instanceof ctor)))) {
return false;
}
// ie < 9 iterates inherited properties before own properties. if the first
// iterated property is an object's own property then there are no inherited
// enumerable properties.
var result;
if (support.ownlast) {
baseforin(value, function(subvalue, key, object) {
result = hasownproperty.call(object, key);
return false;
});
return result !== false;
}
// in most environments an object's own properties are iterated before
// its inherited properties. if the last iterated property is an object's
// own property then there are no inherited enumerable properties.
baseforin(value, function(subvalue, key) {
result = key;
});
return result === undefined || hasownproperty.call(value, result);
}
module.exports = isplainobject;
},{"../internal/baseforin":12,"../internal/ishostobject":22,"../internal/isobjectlike":26,"../support":41,"./isarguments":29}],35:[function(_dereq_,module,exports){
var isobjectlike = _dereq_('../internal/isobjectlike');
/** `object#tostring` result references. */
var stringtag = '[object string]';
/** used for native method references. */
var objectproto = object.prototype;
/**
* used to resolve the [`tostringtag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objtostring = objectproto.tostring;
/**
* checks if `value` is classified as a `string` primitive or object.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is correctly classified, else `false`.
* @example
*
* _.isstring('abc');
* // => true
*
* _.isstring(1);
* // => false
*/
function isstring(value) {
return typeof value == 'string' || (isobjectlike(value) && objtostring.call(value) == stringtag);
}
module.exports = isstring;
},{"../internal/isobjectlike":26}],36:[function(_dereq_,module,exports){
var islength = _dereq_('../internal/islength'),
isobjectlike = _dereq_('../internal/isobjectlike');
/** `object#tostring` result references. */
var argstag = '[object arguments]',
arraytag = '[object array]',
booltag = '[object boolean]',
datetag = '[object date]',
errortag = '[object error]',
functag = '[object function]',
maptag = '[object map]',
numbertag = '[object number]',
objecttag = '[object object]',
regexptag = '[object regexp]',
settag = '[object set]',
stringtag = '[object string]',
weakmaptag = '[object weakmap]';
var arraybuffertag = '[object arraybuffer]',
float32tag = '[object float32array]',
float64tag = '[object float64array]',
int8tag = '[object int8array]',
int16tag = '[object int16array]',
int32tag = '[object int32array]',
uint8tag = '[object uint8array]',
uint8clampedtag = '[object uint8clampedarray]',
uint16tag = '[object uint16array]',
uint32tag = '[object uint32array]';
/** used to identify `tostringtag` values of typed arrays. */
var typedarraytags = {};
typedarraytags[float32tag] = typedarraytags[float64tag] =
typedarraytags[int8tag] = typedarraytags[int16tag] =
typedarraytags[int32tag] = typedarraytags[uint8tag] =
typedarraytags[uint8clampedtag] = typedarraytags[uint16tag] =
typedarraytags[uint32tag] = true;
typedarraytags[argstag] = typedarraytags[arraytag] =
typedarraytags[arraybuffertag] = typedarraytags[booltag] =
typedarraytags[datetag] = typedarraytags[errortag] =
typedarraytags[functag] = typedarraytags[maptag] =
typedarraytags[numbertag] = typedarraytags[objecttag] =
typedarraytags[regexptag] = typedarraytags[settag] =
typedarraytags[stringtag] = typedarraytags[weakmaptag] = false;
/** used for native method references. */
var objectproto = object.prototype;
/**
* used to resolve the [`tostringtag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objtostring = objectproto.tostring;
/**
* checks if `value` is classified as a typed array.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to check.
* @returns {boolean} returns `true` if `value` is correctly classified, else `false`.
* @example
*
* _.istypedarray(new uint8array);
* // => true
*
* _.istypedarray([]);
* // => false
*/
function istypedarray(value) {
return isobjectlike(value) && islength(value.length) && !!typedarraytags[objtostring.call(value)];
}
module.exports = istypedarray;
},{"../internal/islength":25,"../internal/isobjectlike":26}],37:[function(_dereq_,module,exports){
var basecopy = _dereq_('../internal/basecopy'),
keysin = _dereq_('../object/keysin');
/**
* converts `value` to a plain object flattening inherited enumerable
* properties of `value` to own properties of the plain object.
*
* @static
* @memberof _
* @category lang
* @param {*} value the value to convert.
* @returns {object} returns the converted plain object.
* @example
*
* function foo() {
* this.b = 2;
* }
*
* foo.prototype.c = 3;
*
* _.assign({ 'a': 1 }, new foo);
* // => { 'a': 1, 'b': 2 }
*
* _.assign({ 'a': 1 }, _.toplainobject(new foo));
* // => { 'a': 1, 'b': 2, 'c': 3 }
*/
function toplainobject(value) {
return basecopy(value, keysin(value));
}
module.exports = toplainobject;
},{"../internal/basecopy":10,"../object/keysin":39}],38:[function(_dereq_,module,exports){
var getnative = _dereq_('../internal/getnative'),
isarraylike = _dereq_('../internal/isarraylike'),
isobject = _dereq_('../lang/isobject'),
shimkeys = _dereq_('../internal/shimkeys'),
support = _dereq_('../support');
/* native method references for those with the same name as other `lodash` methods. */
var nativekeys = getnative(object, 'keys');
/**
* creates an array of the own enumerable property names of `object`.
*
* **note:** non-object values are coerced to objects. see the
* [es spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
* for more details.
*
* @static
* @memberof _
* @category object
* @param {object} object the object to query.
* @returns {array} returns the array of property names.
* @example
*
* function foo() {
* this.a = 1;
* this.b = 2;
* }
*
* foo.prototype.c = 3;
*
* _.keys(new foo);
* // => ['a', 'b'] (iteration order is not guaranteed)
*
* _.keys('hi');
* // => ['0', '1']
*/
var keys = !nativekeys ? shimkeys : function(object) {
var ctor = object == null ? undefined : object.constructor;
if ((typeof ctor == 'function' && ctor.prototype === object) ||
(typeof object == 'function' ? support.enumprototypes : isarraylike(object))) {
return shimkeys(object);
}
return isobject(object) ? nativekeys(object) : [];
};
module.exports = keys;
},{"../internal/getnative":20,"../internal/isarraylike":21,"../internal/shimkeys":27,"../lang/isobject":33,"../support":41}],39:[function(_dereq_,module,exports){
var arrayeach = _dereq_('../internal/arrayeach'),
isarguments = _dereq_('../lang/isarguments'),
isarray = _dereq_('../lang/isarray'),
isfunction = _dereq_('../lang/isfunction'),
isindex = _dereq_('../internal/isindex'),
islength = _dereq_('../internal/islength'),
isobject = _dereq_('../lang/isobject'),
isstring = _dereq_('../lang/isstring'),
support = _dereq_('../support');
/** `object#tostring` result references. */
var arraytag = '[object array]',
booltag = '[object boolean]',
datetag = '[object date]',
errortag = '[object error]',
functag = '[object function]',
numbertag = '[object number]',
objecttag = '[object object]',
regexptag = '[object regexp]',
stringtag = '[object string]';
/** used to fix the jscript `[[dontenum]]` bug. */
var shadowprops = [
'constructor', 'hasownproperty', 'isprototypeof', 'propertyisenumerable',
'tolocalestring', 'tostring', 'valueof'
];
/** used for native method references. */
var errorproto = error.prototype,
objectproto = object.prototype,
stringproto = string.prototype;
/** used to check objects for own properties. */
var hasownproperty = objectproto.hasownproperty;
/**
* used to resolve the [`tostringtag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
* of values.
*/
var objtostring = objectproto.tostring;
/** used to avoid iterating over non-enumerable properties in ie < 9. */
var nonenumprops = {};
nonenumprops[arraytag] = nonenumprops[datetag] = nonenumprops[numbertag] = { 'constructor': true, 'tolocalestring': true, 'tostring': true, 'valueof': true };
nonenumprops[booltag] = nonenumprops[stringtag] = { 'constructor': true, 'tostring': true, 'valueof': true };
nonenumprops[errortag] = nonenumprops[functag] = nonenumprops[regexptag] = { 'constructor': true, 'tostring': true };
nonenumprops[objecttag] = { 'constructor': true };
arrayeach(shadowprops, function(key) {
for (var tag in nonenumprops) {
if (hasownproperty.call(nonenumprops, tag)) {
var props = nonenumprops[tag];
props[key] = hasownproperty.call(props, key);
}
}
});
/**
* creates an array of the own and inherited enumerable property names of `object`.
*
* **note:** non-object values are coerced to objects.
*
* @static
* @memberof _
* @category object
* @param {object} object the object to query.
* @returns {array} returns the array of property names.
* @example
*
* function foo() {
* this.a = 1;
* this.b = 2;
* }
*
* foo.prototype.c = 3;
*
* _.keysin(new foo);
* // => ['a', 'b', 'c'] (iteration order is not guaranteed)
*/
function keysin(object) {
if (object == null) {
return [];
}
if (!isobject(object)) {
object = object(object);
}
var length = object.length;
length = (length && islength(length) &&
(isarray(object) || isarguments(object) || isstring(object)) && length) || 0;
var ctor = object.constructor,
index = -1,
proto = (isfunction(ctor) && ctor.prototype) || objectproto,
isproto = proto === object,
result = array(length),
skipindexes = length > 0,
skiperrorprops = support.enumerrorprops && (object === errorproto || object instanceof error),
skipproto = support.enumprototypes && isfunction(object);
while (++index < length) {
result[index] = (index + '');
}
// lodash skips the `constructor` property when it infers it's iterating
// over a `prototype` object because ie < 9 can't set the `[[enumerable]]`
// attribute of an existing property and the `constructor` property of a
// prototype defaults to non-enumerable.
for (var key in object) {
if (!(skipproto && key == 'prototype') &&
!(skiperrorprops && (key == 'message' || key == 'name')) &&
!(skipindexes && isindex(key, length)) &&
!(key == 'constructor' && (isproto || !hasownproperty.call(object, key)))) {
result.push(key);
}
}
if (support.nonenumshadows && object !== objectproto) {
var tag = object === stringproto ? stringtag : (object === errorproto ? errortag : objtostring.call(object)),
nonenums = nonenumprops[tag] || nonenumprops[objecttag];
if (tag == objecttag) {
proto = objectproto;
}
length = shadowprops.length;
while (length--) {
key = shadowprops[length];
var nonenum = nonenums[key];
if (!(isproto && nonenum) &&
(nonenum ? hasownproperty.call(object, key) : object[key] !== proto[key])) {
result.push(key);
}
}
}
return result;
}
module.exports = keysin;
},{"../internal/arrayeach":9,"../internal/isindex":23,"../internal/islength":25,"../lang/isarguments":29,"../lang/isarray":30,"../lang/isfunction":31,"../lang/isobject":33,"../lang/isstring":35,"../support":41}],40:[function(_dereq_,module,exports){
var basemerge = _dereq_('../internal/basemerge'),
createassigner = _dereq_('../internal/createassigner');
/**
* recursively merges own enumerable properties of the source object(s), that
* don't resolve to `undefined` into the destination object. subsequent sources
* overwrite property assignments of previous sources. if `customizer` is
* provided it's invoked to produce the merged values of the destination and
* source properties. if `customizer` returns `undefined` merging is handled
* by the method instead. the `customizer` is bound to `thisarg` and invoked
* with five arguments: (objectvalue, sourcevalue, key, object, source).
*
* @static
* @memberof _
* @category object
* @param {object} object the destination object.
* @param {...object} [sources] the source objects.
* @param {function} [customizer] the function to customize assigned values.
* @param {*} [thisarg] the `this` binding of `customizer`.
* @returns {object} returns `object`.
* @example
*
* var users = {
* 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
* };
*
* var ages = {
* 'data': [{ 'age': 36 }, { 'age': 40 }]
* };
*
* _.merge(users, ages);
* // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
*
* // using a customizer callback
* var object = {
* 'fruits': ['apple'],
* 'vegetables': ['beet']
* };
*
* var other = {
* 'fruits': ['banana'],
* 'vegetables': ['carrot']
* };
*
* _.merge(object, other, function(a, b) {
* if (_.isarray(a)) {
* return a.concat(b);
* }
* });
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
*/
var merge = createassigner(basemerge);
module.exports = merge;
},{"../internal/basemerge":13,"../internal/createassigner":17}],41:[function(_dereq_,module,exports){
/** used for native method references. */
var arrayproto = array.prototype,
errorproto = error.prototype,
objectproto = object.prototype;
/** native method references. */
var propertyisenumerable = objectproto.propertyisenumerable,
splice = arrayproto.splice;
/**
* an object environment feature flags.
*
* @static
* @memberof _
* @type object
*/
var support = {};
(function(x) {
var ctor = function() { this.x = x; },
object = { '0': x, 'length': x },
props = [];
ctor.prototype = { 'valueof': x, 'y': x };
for (var key in new ctor) { props.push(key); }
/**
* detect if `name` or `message` properties of `error.prototype` are
* enumerable by default (ie < 9, safari < 5.1).
*
* @memberof _.support
* @type boolean
*/
support.enumerrorprops = propertyisenumerable.call(errorproto, 'message') ||
propertyisenumerable.call(errorproto, 'name');
/**
* detect if `prototype` properties are enumerable by default.
*
* firefox < 3.6, opera > 9.50 - opera < 11.60, and safari < 5.1
* (if the prototype or a property on the prototype has been set)
* incorrectly set the `[[enumerable]]` value of a function's `prototype`
* property to `true`.
*
* @memberof _.support
* @type boolean
*/
support.enumprototypes = propertyisenumerable.call(ctor, 'prototype');
/**
* detect if properties shadowing those on `object.prototype` are non-enumerable.
*
* in ie < 9 an object's own properties, shadowing non-enumerable ones,
* are made non-enumerable as well (a.k.a the jscript `[[dontenum]]` bug).
*
* @memberof _.support
* @type boolean
*/
support.nonenumshadows = !/valueof/.test(props);
/**
* detect if own properties are iterated after inherited properties (ie < 9).
*
* @memberof _.support
* @type boolean
*/
support.ownlast = props[0] != 'x';
/**
* detect if `array#shift` and `array#splice` augment array-like objects
* correctly.
*
* firefox < 10, compatibility modes of ie 8, and ie < 9 have buggy array
* `shift()` and `splice()` functions that fail to remove the last element,
* `value[0]`, of array-like objects even though the "length" property is
* set to `0`. the `shift()` method is buggy in compatibility modes of ie 8,
* while `splice()` is buggy regardless of mode in ie < 9.
*
* @memberof _.support
* @type boolean
*/
support.spliceobjects = (splice.call(object, 0, 1), !object[0]);
/**
* detect lack of support for accessing string characters by index.
*
* ie < 8 can't access characters by index. ie 8 can only access characters
* by index on string literals, not string objects.
*
* @memberof _.support
* @type boolean
*/
support.unindexedchars = ('x'[0] + object('x')[0]) != 'xx';
}(1, 0));
module.exports = support;
},{}],42:[function(_dereq_,module,exports){
/**
* this method returns the first argument provided to it.
*
* @static
* @memberof _
* @category utility
* @param {*} value any value.
* @returns {*} returns `value`.
* @example
*
* var object = { 'user': 'fred' };
*
* _.identity(object) === object;
* // => true
*/
function identity(value) {
return value;
}
module.exports = identity;
},{}],43:[function(_dereq_,module,exports){
'use strict';
var keys = _dereq_('object-keys');
module.exports = function hassymbols() {
if (typeof symbol !== 'function' || typeof object.getownpropertysymbols !== 'function') { return false; }
if (typeof symbol.iterator === 'symbol') { return true; }
var obj = {};
var sym = symbol('test');
if (typeof sym === 'string') { return false; }
// temp disabled per https://github.com/ljharb/object.assign/issues/17
// if (sym instanceof symbol) { return false; }
// temp disabled per https://github.com/webreflection/get-own-property-symbols/issues/4
// if (!(object(sym) instanceof symbol)) { return false; }
var symval = 42;
obj[sym] = symval;
for (sym in obj) { return false; }
if (keys(obj).length !== 0) { return false; }
if (typeof object.keys === 'function' && object.keys(obj).length !== 0) { return false; }
if (typeof object.getownpropertynames === 'function' && object.getownpropertynames(obj).length !== 0) { return false; }
var syms = object.getownpropertysymbols(obj);
if (syms.length !== 1 || syms[0] !== sym) { return false; }
if (!object.prototype.propertyisenumerable.call(obj, sym)) { return false; }
if (typeof object.getownpropertydescriptor === 'function') {
var descriptor = object.getownpropertydescriptor(obj, sym);
if (descriptor.value !== symval || descriptor.enumerable !== true) { return false; }
}
return true;
};
},{"object-keys":50}],44:[function(_dereq_,module,exports){
'use strict';
// modified from https://github.com/es-shims/es6-shim
var keys = _dereq_('object-keys');
var bind = _dereq_('function-bind');
var canbeobject = function (obj) {
return typeof obj !== 'undefined' && obj !== null;
};
var hassymbols = _dereq_('./hassymbols')();
var toobject = object;
var push = bind.call(function.call, array.prototype.push);
var propisenumerable = bind.call(function.call, object.prototype.propertyisenumerable);
module.exports = function assign(target, source1) {
if (!canbeobject(target)) { throw new typeerror('target must be an object'); }
var objtarget = toobject(target);
var s, source, i, props, syms, value, key;
for (s = 1; s < arguments.length; ++s) {
source = toobject(arguments[s]);
props = keys(source);
if (hassymbols && object.getownpropertysymbols) {
syms = object.getownpropertysymbols(source);
for (i = 0; i < syms.length; ++i) {
key = syms[i];
if (propisenumerable(source, key)) {
push(props, key);
}
}
}
for (i = 0; i < props.length; ++i) {
key = props[i];
value = source[key];
if (propisenumerable(source, key)) {
objtarget[key] = value;
}
}
}
return objtarget;
};
},{"./hassymbols":43,"function-bind":49,"object-keys":50}],45:[function(_dereq_,module,exports){
'use strict';
var defineproperties = _dereq_('define-properties');
var implementation = _dereq_('./implementation');
var getpolyfill = _dereq_('./polyfill');
var shim = _dereq_('./shim');
defineproperties(implementation, {
implementation: implementation,
getpolyfill: getpolyfill,
shim: shim
});
module.exports = implementation;
},{"./implementation":44,"./polyfill":52,"./shim":53,"define-properties":46}],46:[function(_dereq_,module,exports){
'use strict';
var keys = _dereq_('object-keys');
var foreach = _dereq_('foreach');
var hassymbols = typeof symbol === 'function' && typeof symbol() === 'symbol';
var tostr = object.prototype.tostring;
var isfunction = function (fn) {
return typeof fn === 'function' && tostr.call(fn) === '[object function]';
};
var arepropertydescriptorssupported = function () {
var obj = {};
try {
object.defineproperty(obj, 'x', { enumerable: false, value: obj });
/* eslint-disable no-unused-vars, no-restricted-syntax */
for (var _ in obj) { return false; }
/* eslint-enable no-unused-vars, no-restricted-syntax */
return obj.x === obj;
} catch (e) { /* this is ie 8. */
return false;
}
};
var supportsdescriptors = object.defineproperty && arepropertydescriptorssupported();
var defineproperty = function (object, name, value, predicate) {
if (name in object && (!isfunction(predicate) || !predicate())) {
return;
}
if (supportsdescriptors) {
object.defineproperty(object, name, {
configurable: true,
enumerable: false,
value: value,
writable: true
});
} else {
object[name] = value;
}
};
var defineproperties = function (object, map) {
var predicates = arguments.length > 2 ? arguments[2] : {};
var props = keys(map);
if (hassymbols) {
props = props.concat(object.getownpropertysymbols(map));
}
foreach(props, function (name) {
defineproperty(object, name, map[name], predicates[name]);
});
};
defineproperties.supportsdescriptors = !!supportsdescriptors;
module.exports = defineproperties;
},{"foreach":47,"object-keys":50}],47:[function(_dereq_,module,exports){
var hasown = object.prototype.hasownproperty;
var tostring = object.prototype.tostring;
module.exports = function foreach (obj, fn, ctx) {
if (tostring.call(fn) !== '[object function]') {
throw new typeerror('iterator must be a function');
}
var l = obj.length;
if (l === +l) {
for (var i = 0; i < l; i++) {
fn.call(ctx, obj[i], i, obj);
}
} else {
for (var k in obj) {
if (hasown.call(obj, k)) {
fn.call(ctx, obj[k], k, obj);
}
}
}
};
},{}],48:[function(_dereq_,module,exports){
var error_message = 'function.prototype.bind called on incompatible ';
var slice = array.prototype.slice;
var tostr = object.prototype.tostring;
var functype = '[object function]';
module.exports = function bind(that) {
var target = this;
if (typeof target !== 'function' || tostr.call(target) !== functype) {
throw new typeerror(error_message + target);
}
var args = slice.call(arguments, 1);
var bound;
var binder = function () {
if (this instanceof bound) {
var result = target.apply(
this,
args.concat(slice.call(arguments))
);
if (object(result) === result) {
return result;
}
return this;
} else {
return target.apply(
that,
args.concat(slice.call(arguments))
);
}
};
var boundlength = math.max(0, target.length - args.length);
var boundargs = [];
for (var i = 0; i < boundlength; i++) {
boundargs.push('$' + i);
}
bound = function('binder', 'return function (' + boundargs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
if (target.prototype) {
var empty = function empty() {};
empty.prototype = target.prototype;
bound.prototype = new empty();
empty.prototype = null;
}
return bound;
};
},{}],49:[function(_dereq_,module,exports){
var implementation = _dereq_('./implementation');
module.exports = function.prototype.bind || implementation;
},{"./implementation":48}],50:[function(_dereq_,module,exports){
'use strict';
// modified from https://github.com/es-shims/es5-shim
var has = object.prototype.hasownproperty;
var tostr = object.prototype.tostring;
var slice = array.prototype.slice;
var isargs = _dereq_('./isarguments');
var hasdontenumbug = !({ tostring: null }).propertyisenumerable('tostring');
var hasprotoenumbug = function () {}.propertyisenumerable('prototype');
var dontenums = [
'tostring',
'tolocalestring',
'valueof',
'hasownproperty',
'isprototypeof',
'propertyisenumerable',
'constructor'
];
var equalsconstructorprototype = function (o) {
var ctor = o.constructor;
return ctor && ctor.prototype === o;
};
var blacklistedkeys = {
$console: true,
$frame: true,
$frameelement: true,
$frames: true,
$parent: true,
$self: true,
$webkitindexeddb: true,
$webkitstorageinfo: true,
$window: true
};
var hasautomationequalitybug = (function () {
/* global window */
if (typeof window === 'undefined') { return false; }
for (var k in window) {
try {
if (!blacklistedkeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
try {
equalsconstructorprototype(window[k]);
} catch (e) {
return true;
}
}
} catch (e) {
return true;
}
}
return false;
}());
var equalsconstructorprototypeifnotbuggy = function (o) {
/* global window */
if (typeof window === 'undefined' || !hasautomationequalitybug) {
return equalsconstructorprototype(o);
}
try {
return equalsconstructorprototype(o);
} catch (e) {
return false;
}
};
var keysshim = function keys(object) {
var isobject = object !== null && typeof object === 'object';
var isfunction = tostr.call(object) === '[object function]';
var isarguments = isargs(object);
var isstring = isobject && tostr.call(object) === '[object string]';
var thekeys = [];
if (!isobject && !isfunction && !isarguments) {
throw new typeerror('object.keys called on a non-object');
}
var skipproto = hasprotoenumbug && isfunction;
if (isstring && object.length > 0 && !has.call(object, 0)) {
for (var i = 0; i < object.length; ++i) {
thekeys.push(string(i));
}
}
if (isarguments && object.length > 0) {
for (var j = 0; j < object.length; ++j) {
thekeys.push(string(j));
}
} else {
for (var name in object) {
if (!(skipproto && name === 'prototype') && has.call(object, name)) {
thekeys.push(string(name));
}
}
}
if (hasdontenumbug) {
var skipconstructor = equalsconstructorprototypeifnotbuggy(object);
for (var k = 0; k < dontenums.length; ++k) {
if (!(skipconstructor && dontenums[k] === 'constructor') && has.call(object, dontenums[k])) {
thekeys.push(dontenums[k]);
}
}
}
return thekeys;
};
keysshim.shim = function shimobjectkeys() {
if (object.keys) {
var keysworkswitharguments = (function () {
// safari 5.0 bug
return (object.keys(arguments) || '').length === 2;
}(1, 2));
if (!keysworkswitharguments) {
var originalkeys = object.keys;
object.keys = function keys(object) {
if (isargs(object)) {
return originalkeys(slice.call(object));
} else {
return originalkeys(object);
}
};
}
} else {
object.keys = keysshim;
}
return object.keys || keysshim;
};
module.exports = keysshim;
},{"./isarguments":51}],51:[function(_dereq_,module,exports){
'use strict';
var tostr = object.prototype.tostring;
module.exports = function isarguments(value) {
var str = tostr.call(value);
var isargs = str === '[object arguments]';
if (!isargs) {
isargs = str !== '[object array]' &&
value !== null &&
typeof value === 'object' &&
typeof value.length === 'number' &&
value.length >= 0 &&
tostr.call(value.callee) === '[object function]';
}
return isargs;
};
},{}],52:[function(_dereq_,module,exports){
'use strict';
var implementation = _dereq_('./implementation');
var lacksproperenumerationorder = function () {
if (!object.assign) {
return false;
}
// v8, specifically in node 4.x, has a bug with incorrect property enumeration order
// note: this does not detect the bug unless there's 20 characters
var str = 'abcdefghijklmnopqrst';
var letters = str.split('');
var map = {};
for (var i = 0; i < letters.length; ++i) {
map[letters[i]] = letters[i];
}
var obj = object.assign({}, map);
var actual = '';
for (var k in obj) {
actual += k;
}
return str !== actual;
};
var assignhaspendingexceptions = function () {
if (!object.assign || !object.preventextensions) {
return false;
}
// firefox 37 still has "pending exception" logic in its object.assign implementation,
// which is 72% slower than our shim, and firefox 40's native implementation.
var thrower = object.preventextensions({ 1: 2 });
try {
object.assign(thrower, 'xy');
} catch (e) {
return thrower[1] === 'y';
}
};
module.exports = function getpolyfill() {
if (!object.assign) {
return implementation;
}
if (lacksproperenumerationorder()) {
return implementation;
}
if (assignhaspendingexceptions()) {
return implementation;
}
return object.assign;
};
},{"./implementation":44}],53:[function(_dereq_,module,exports){
'use strict';
var define = _dereq_('define-properties');
var getpolyfill = _dereq_('./polyfill');
module.exports = function shimassign() {
var polyfill = getpolyfill();
define(
object,
{ assign: polyfill },
{ assign: function () { return object.assign !== polyfill; } }
);
return polyfill;
};
},{"./polyfill":52,"define-properties":46}],54:[function(_dereq_,module,exports){
module.exports = safeparsetuple
function safeparsetuple(obj, reviver) {
var json
var error = null
try {
json = json.parse(obj, reviver)
} catch (err) {
error = err
}
return [error, json]
}
},{}],55:[function(_dereq_,module,exports){
function clean (s) {
return s.replace(/\n\r?\s*/g, '')
}
module.exports = function tsml (sa) {
var s = ''
, i = 0
for (; i < arguments.length; i++)
s += clean(sa[i]) + (arguments[i + 1] || '')
return s
}
},{}],56:[function(_dereq_,module,exports){
"use strict";
var window = _dereq_("global/window")
var once = _dereq_("once")
var isfunction = _dereq_("is-function")
var parseheaders = _dereq_("parse-headers")
var xtend = _dereq_("xtend")
module.exports = createxhr
createxhr.xmlhttprequest = window.xmlhttprequest || noop
createxhr.xdomainrequest = "withcredentials" in (new createxhr.xmlhttprequest()) ? createxhr.xmlhttprequest : window.xdomainrequest
foreacharray(["get", "put", "post", "patch", "head", "delete"], function(method) {
createxhr[method === "delete" ? "del" : method] = function(uri, options, callback) {
options = initparams(uri, options, callback)
options.method = method.touppercase()
return _createxhr(options)
}
})
function foreacharray(array, iterator) {
for (var i = 0; i < array.length; i++) {
iterator(array[i])
}
}
function isempty(obj){
for(var i in obj){
if(obj.hasownproperty(i)) return false
}
return true
}
function initparams(uri, options, callback) {
var params = uri
if (isfunction(options)) {
callback = options
if (typeof uri === "string") {
params = {uri:uri}
}
} else {
params = xtend(options, {uri: uri})
}
params.callback = callback
return params
}
function createxhr(uri, options, callback) {
options = initparams(uri, options, callback)
return _createxhr(options)
}
function _createxhr(options) {
var callback = options.callback
if(typeof callback === "undefined"){
throw new error("callback argument missing")
}
callback = once(callback)
function readystatechange() {
if (xhr.readystate === 4) {
loadfunc()
}
}
function getbody() {
// chrome with requesttype=blob throws errors arround when even testing access to responsetext
var body = undefined
if (xhr.response) {
body = xhr.response
} else if (xhr.responsetype === "text" || !xhr.responsetype) {
body = xhr.responsetext || xhr.responsexml
}
if (isjson) {
try {
body = json.parse(body)
} catch (e) {}
}
return body
}
var failureresponse = {
body: undefined,
headers: {},
statuscode: 0,
method: method,
url: uri,
rawrequest: xhr
}
function errorfunc(evt) {
cleartimeout(timeouttimer)
if(!(evt instanceof error)){
evt = new error("" + (evt || "unknown xmlhttprequest error") )
}
evt.statuscode = 0
callback(evt, failureresponse)
}
// will load the data & process the response in a special response object
function loadfunc() {
if (aborted) return
var status
cleartimeout(timeouttimer)
if(options.usexdr && xhr.status===undefined) {
//ie8 cors get successful response doesn't have a status field, but body is fine
status = 200
} else {
status = (xhr.status === 1223 ? 204 : xhr.status)
}
var response = failureresponse
var err = null
if (status !== 0){
response = {
body: getbody(),
statuscode: status,
method: method,
headers: {},
url: uri,
rawrequest: xhr
}
if(xhr.getallresponseheaders){ //remember xhr can in fact be xdr for cors in ie
response.headers = parseheaders(xhr.getallresponseheaders())
}
} else {
err = new error("internal xmlhttprequest error")
}
callback(err, response, response.body)
}
var xhr = options.xhr || null
if (!xhr) {
if (options.cors || options.usexdr) {
xhr = new createxhr.xdomainrequest()
}else{
xhr = new createxhr.xmlhttprequest()
}
}
var key
var aborted
var uri = xhr.url = options.uri || options.url
var method = xhr.method = options.method || "get"
var body = options.body || options.data || null
var headers = xhr.headers = options.headers || {}
var sync = !!options.sync
var isjson = false
var timeouttimer
if ("json" in options) {
isjson = true
headers["accept"] || headers["accept"] || (headers["accept"] = "application/json") //don't override existing accept header declared by user
if (method !== "get" && method !== "head") {
headers["content-type"] || headers["content-type"] || (headers["content-type"] = "application/json") //don't override existing accept header declared by user
body = json.stringify(options.json)
}
}
xhr.onreadystatechange = readystatechange
xhr.onload = loadfunc
xhr.onerror = errorfunc
// ie9 must have onprogress be set to a unique function.
xhr.onprogress = function () {
// ie must die
}
xhr.ontimeout = errorfunc
xhr.open(method, uri, !sync, options.username, options.password)
//has to be after open
if(!sync) {
xhr.withcredentials = !!options.withcredentials
}
// cannot set timeout with sync request
// not setting timeout on the xhr object, because of old webkits etc. not handling that correctly
// both npm's request and jquery 1.x use this kind of timeout, so this is being consistent
if (!sync && options.timeout > 0 ) {
timeouttimer = settimeout(function(){
aborted=true//ie9 may still call readystatechange
xhr.abort("timeout")
var e = new error("xmlhttprequest timeout")
e.code = "etimedout"
errorfunc(e)
}, options.timeout )
}
if (xhr.setrequestheader) {
for(key in headers){
if(headers.hasownproperty(key)){
xhr.setrequestheader(key, headers[key])
}
}
} else if (options.headers && !isempty(options.headers)) {
throw new error("headers cannot be set on an xdomainrequest object")
}
if ("responsetype" in options) {
xhr.responsetype = options.responsetype
}
if ("beforesend" in options &&
typeof options.beforesend === "function"
) {
options.beforesend(xhr)
}
xhr.send(body)
return xhr
}
function noop() {}
},{"global/window":2,"is-function":57,"once":58,"parse-headers":61,"xtend":62}],57:[function(_dereq_,module,exports){
module.exports = isfunction
var tostring = object.prototype.tostring
function isfunction (fn) {
var string = tostring.call(fn)
return string === '[object function]' ||
(typeof fn === 'function' && string !== '[object regexp]') ||
(typeof window !== 'undefined' &&
// ie8 and below
(fn === window.settimeout ||
fn === window.alert ||
fn === window.confirm ||
fn === window.prompt))
};
},{}],58:[function(_dereq_,module,exports){
module.exports = once
once.proto = once(function () {
object.defineproperty(function.prototype, 'once', {
value: function () {
return once(this)
},
configurable: true
})
})
function once (fn) {
var called = false
return function () {
if (called) return
called = true
return fn.apply(this, arguments)
}
}
},{}],59:[function(_dereq_,module,exports){
var isfunction = _dereq_('is-function')
module.exports = foreach
var tostring = object.prototype.tostring
var hasownproperty = object.prototype.hasownproperty
function foreach(list, iterator, context) {
if (!isfunction(iterator)) {
throw new typeerror('iterator must be a function')
}
if (arguments.length < 3) {
context = this
}
if (tostring.call(list) === '[object array]')
foreacharray(list, iterator, context)
else if (typeof list === 'string')
foreachstring(list, iterator, context)
else
foreachobject(list, iterator, context)
}
function foreacharray(array, iterator, context) {
for (var i = 0, len = array.length; i < len; i++) {
if (hasownproperty.call(array, i)) {
iterator.call(context, array[i], i, array)
}
}
}
function foreachstring(string, iterator, context) {
for (var i = 0, len = string.length; i < len; i++) {
// no such thing as a sparse string.
iterator.call(context, string.charat(i), i, string)
}
}
function foreachobject(object, iterator, context) {
for (var k in object) {
if (hasownproperty.call(object, k)) {
iterator.call(context, object[k], k, object)
}
}
}
},{"is-function":57}],60:[function(_dereq_,module,exports){
exports = module.exports = trim;
function trim(str){
return str.replace(/^\s*|\s*$/g, '');
}
exports.left = function(str){
return str.replace(/^\s*/, '');
};
exports.right = function(str){
return str.replace(/\s*$/, '');
};
},{}],61:[function(_dereq_,module,exports){
var trim = _dereq_('trim')
, foreach = _dereq_('for-each')
, isarray = function(arg) {
return object.prototype.tostring.call(arg) === '[object array]';
}
module.exports = function (headers) {
if (!headers)
return {}
var result = {}
foreach(
trim(headers).split('\n')
, function (row) {
var index = row.indexof(':')
, key = trim(row.slice(0, index)).tolowercase()
, value = trim(row.slice(index + 1))
if (typeof(result[key]) === 'undefined') {
result[key] = value
} else if (isarray(result[key])) {
result[key].push(value)
} else {
result[key] = [ result[key], value ]
}
}
)
return result
}
},{"for-each":59,"trim":60}],62:[function(_dereq_,module,exports){
module.exports = extend
var hasownproperty = object.prototype.hasownproperty;
function extend() {
var target = {}
for (var i = 0; i < arguments.length; i++) {
var source = arguments[i]
for (var key in source) {
if (hasownproperty.call(source, key)) {
target[key] = source[key]
}
}
}
return target
}
},{}],63:[function(_dereq_,module,exports){
/**
* @file big-play-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _buttonjs = _dereq_('./button.js');
var _buttonjs2 = _interoprequiredefault(_buttonjs);
var _componentjs = _dereq_('./component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* initial play button. shows before the video has played. the hiding of the
* big play button is done via css and player states.
*
* @param {object} player main player
* @param {object=} options object of option names and values
* @extends button
* @class bigplaybutton
*/
var bigplaybutton = (function (_button) {
_inherits(bigplaybutton, _button);
function bigplaybutton(player, options) {
_classcallcheck(this, bigplaybutton);
_button.call(this, player, options);
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
bigplaybutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-big-play-button';
};
/**
* handles click for play
*
* @method handleclick
*/
bigplaybutton.prototype.handleclick = function handleclick() {
this.player_.play();
};
return bigplaybutton;
})(_buttonjs2['default']);
bigplaybutton.prototype.controltext_ = 'play video';
_componentjs2['default'].registercomponent('bigplaybutton', bigplaybutton);
exports['default'] = bigplaybutton;
module.exports = exports['default'];
},{"./button.js":64,"./component.js":67}],64:[function(_dereq_,module,exports){
/**
* @file button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _clickablecomponentjs = _dereq_('./clickable-component.js');
var _clickablecomponentjs2 = _interoprequiredefault(_clickablecomponentjs);
var _component = _dereq_('./component');
var _component2 = _interoprequiredefault(_component);
var _utilseventsjs = _dereq_('./utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var _utilsfnjs = _dereq_('./utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilslogjs = _dereq_('./utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
/**
* base class for all buttons
*
* @param {object} player main player
* @param {object=} options object of option names and values
* @extends clickablecomponent
* @class button
*/
var button = (function (_clickablecomponent) {
_inherits(button, _clickablecomponent);
function button(player, options) {
_classcallcheck(this, button);
_clickablecomponent.call(this, player, options);
}
/**
* create the component's dom element
*
* @param {string=} type element's node type. e.g. 'div'
* @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}
* @method createel
*/
button.prototype.createel = function createel() {
var tag = arguments.length <= 0 || arguments[0] === undefined ? 'button' : arguments[0];
var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
props = _objectassign2['default']({
classname: this.buildcssclass()
}, props);
if (tag !== 'button') {
_utilslogjs2['default'].warn('creating a button with an html element of ' + tag + ' is deprecated; use clickablecomponent instead.');
}
// add attributes for button element
attributes = _objectassign2['default']({
type: 'button', // necessary since the default button type is "submit"
'aria-live': 'polite' // let the screen reader user know that the text of the button may change
}, attributes);
var el = _component2['default'].prototype.createel.call(this, tag, props, attributes);
this.createcontroltextel(el);
return el;
};
/**
* adds a child component inside this button
*
* @param {string|component} child the class name or instance of a child to add
* @param {object=} options options, including options to be passed to children of the child.
* @return {component} the child component (created by this process if a string was used)
* @deprecated
* @method addchild
*/
button.prototype.addchild = function addchild(child) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var classname = this.constructor.name;
_utilslogjs2['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);
};
/**
* handle keypress (document level) - extend with specific functionality for button
*
* @method handlekeypress
*/
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) {} else {
_clickablecomponent.prototype.handlekeypress.call(this, event); // pass keypress handling up for unsupported keys
}
};
return button;
})(_clickablecomponentjs2['default']);
_component2['default'].registercomponent('button', button);
exports['default'] = button;
module.exports = exports['default'];
},{"./clickable-component.js":65,"./component":67,"./utils/events.js":133,"./utils/fn.js":134,"./utils/log.js":137,"global/document":1,"object.assign":45}],65:[function(_dereq_,module,exports){
/**
* @file button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _component = _dereq_('./component');
var _component2 = _interoprequiredefault(_component);
var _utilsdomjs = _dereq_('./utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilseventsjs = _dereq_('./utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var _utilsfnjs = _dereq_('./utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilslogjs = _dereq_('./utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
/**
* clickable component which is clickable or keyboard actionable, but is not a native html button
*
* @param {object} player main player
* @param {object=} options object of option names and values
* @extends component
* @class clickablecomponent
*/
var clickablecomponent = (function (_component) {
_inherits(clickablecomponent, _component);
function clickablecomponent(player, options) {
_classcallcheck(this, clickablecomponent);
_component.call(this, player, options);
this.emittapevents();
this.on('tap', this.handleclick);
this.on('click', this.handleclick);
this.on('focus', this.handlefocus);
this.on('blur', this.handleblur);
}
/**
* create the component's dom element
*
* @param {string=} type element's node type. e.g. 'div'
* @param {object=} props an object of properties that should be set on the element
* @param {object=} attributes an object of attributes that should be set on the element
* @return {element}
* @method createel
*/
clickablecomponent.prototype.createel = function createel() {
var tag = arguments.length <= 0 || arguments[0] === undefined ? 'div' : arguments[0];
var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
props = _objectassign2['default']({
classname: this.buildcssclass(),
tabindex: 0
}, props);
if (tag === 'button') {
_utilslogjs2['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 = _objectassign2['default']({
role: 'button',
'aria-live': 'polite' // let the screen reader user know that the text of the element may change
}, attributes);
var el = _component.prototype.createel.call(this, tag, props, attributes);
this.createcontroltextel(el);
return el;
};
/**
* create control text
*
* @param {element} el parent element for the control text
* @return {element}
* @method controltext
*/
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_);
return this.controltextel_;
};
/**
* controls text - both request and localize
*
* @param {string} text text for element
* @return {string}
* @method controltext
*/
clickablecomponent.prototype.controltext = function controltext(text) {
if (!text) return this.controltext_ || 'need text';
this.controltext_ = text;
this.controltextel_.innerhtml = this.localize(this.controltext_);
return this;
};
/**
* allows sub components to stack css class names
*
* @return {string}
* @method buildcssclass
*/
clickablecomponent.prototype.buildcssclass = function buildcssclass() {
return 'vjs-control vjs-button ' + _component.prototype.buildcssclass.call(this);
};
/**
* adds a child component inside this clickable-component
*
* @param {string|component} child the class name or instance of a child to add
* @param {object=} options options, including options to be passed to children of the child.
* @return {component} the child component (created by this process if a string was used)
* @method addchild
*/
clickablecomponent.prototype.addchild = function addchild(child) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
// todo: fix adding an actionable child to a clickablecomponent; currently
// it will cause issues with assistive technology (e.g. screen readers)
// which support aria, since an element with role="button" cannot have
// actionable child elements.
//let classname = this.constructor.name;
//log.warn(`adding a child to a clickablecomponent (${classname}) can cause issues with assistive technology which supports aria, since an element with role="button" cannot have actionable child elements.`);
return _component.prototype.addchild.call(this, child, options);
};
/**
* handle click - override with specific functionality for component
*
* @method handleclick
*/
clickablecomponent.prototype.handleclick = function handleclick() {};
/**
* handle focus - add keyboard functionality to element
*
* @method handlefocus
*/
clickablecomponent.prototype.handlefocus = function handlefocus() {
events.on(_globaldocument2['default'], 'keydown', fn.bind(this, this.handlekeypress));
};
/**
* handle keypress (document level) - trigger click when space or enter key is pressed
*
* @method handlekeypress
*/
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) {
_component.prototype.handlekeypress.call(this, event); // pass keypress handling up for unsupported keys
}
};
/**
* handle blur - remove keyboard triggers
*
* @method handleblur
*/
clickablecomponent.prototype.handleblur = function handleblur() {
events.off(_globaldocument2['default'], 'keydown', fn.bind(this, this.handlekeypress));
};
return clickablecomponent;
})(_component2['default']);
_component2['default'].registercomponent('clickablecomponent', clickablecomponent);
exports['default'] = clickablecomponent;
module.exports = exports['default'];
},{"./component":67,"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/log.js":137,"global/document":1,"object.assign":45}],66:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
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 _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; }
var _button = _dereq_('./button');
var _button2 = _interoprequiredefault(_button);
var _component = _dereq_('./component');
var _component2 = _interoprequiredefault(_component);
/**
* the `closebutton` component is a button which fires a "close" event
* when it is activated.
*
* @extends button
* @class closebutton
*/
var closebutton = (function (_button) {
_inherits(closebutton, _button);
function closebutton(player, options) {
_classcallcheck(this, closebutton);
_button.call(this, player, options);
this.controltext(options && options.controltext || this.localize('close'));
}
closebutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-close-button ' + _button.prototype.buildcssclass.call(this);
};
closebutton.prototype.handleclick = function handleclick() {
this.trigger({ type: 'close', bubbles: false });
};
return closebutton;
})(_button2['default']);
_component2['default'].registercomponent('closebutton', closebutton);
exports['default'] = closebutton;
module.exports = exports['default'];
},{"./button":64,"./component":67}],67:[function(_dereq_,module,exports){
/**
* @file component.js
*
* player component - base class for all ui objects
*/
'use strict';
exports.__esmodule = true;
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'); } }
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _utilsdomjs = _dereq_('./utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('./utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsguidjs = _dereq_('./utils/guid.js');
var guid = _interoprequirewildcard(_utilsguidjs);
var _utilseventsjs = _dereq_('./utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var _utilslogjs = _dereq_('./utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _utilstotitlecasejs = _dereq_('./utils/to-title-case.js');
var _utilstotitlecasejs2 = _interoprequiredefault(_utilstotitlecasejs);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
var _utilsmergeoptionsjs = _dereq_('./utils/merge-options.js');
var _utilsmergeoptionsjs2 = _interoprequiredefault(_utilsmergeoptionsjs);
/**
* base ui component class
* components are embeddable ui objects that are represented by both a
* javascript object and an element in the dom. they can be children of other
* components, and can have many children themselves.
* ```js
* // adding a button to the player
* var button = player.addchild('button');
* button.el(); // -> button element
* ```
* ```html
*
*
button
*
* ```
* components are also event targets.
* ```js
* button.on('click', function(){
* console.log('button clicked!');
* });
* button.trigger('customevent');
* ```
*
* @param {object} player main player
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @class component
*/
var component = (function () {
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_ = _utilsmergeoptionsjs2['default']({}, this.options_);
// updated options with supplied options
options = this.options_ = _utilsmergeoptionsjs2['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
*
* @method dispose
*/
component.prototype.dispose = function dispose() {
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 component's player
*
* @return {player}
* @method player
*/
component.prototype.player = function player() {
return this.player_;
};
/**
* deep merge of options objects
* whenever a property is an object on both options objects
* the two properties will be merged using mergeoptions.
*
* ```js
* parent.prototype.options_ = {
* optionset: {
* 'childone': { 'foo': 'bar', 'asdf': 'fdsa' },
* 'childtwo': {},
* 'childthree': {}
* }
* }
* newoptions = {
* optionset: {
* 'childone': { 'foo': 'baz', 'abc': '123' }
* 'childtwo': null,
* 'childfour': {}
* }
* }
*
* this.options(newoptions);
* ```
* result
* ```js
* {
* optionset: {
* 'childone': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' },
* 'childtwo': null, // disabled. won't be initialized.
* 'childthree': {},
* 'childfour': {}
* }
* }
* ```
*
* @param {object} obj object of new option values
* @return {object} a new object of this.options_ and obj merged
* @method options
*/
component.prototype.options = function options(obj) {
_utilslogjs2['default'].warn('this.options() has been deprecated and will be moved to the constructor in 6.0');
if (!obj) {
return this.options_;
}
this.options_ = _utilsmergeoptionsjs2['default'](this.options_, obj);
return this.options_;
};
/**
* get the component's dom element
* ```js
* var domel = mycomponent.el();
* ```
*
* @return {element}
* @method el
*/
component.prototype.el = function el() {
return this.el_;
};
/**
* create the component's dom element
*
* @param {string=} tagname element's 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}
* @method createel
*/
component.prototype.createel = function createel(tagname, properties, attributes) {
return dom.createel(tagname, properties, attributes);
};
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 where children are inserted.
* will either be the same as el() or a new element defined in createel().
*
* @return {element}
* @method contentel
*/
component.prototype.contentel = function contentel() {
return this.contentel_ || this.el_;
};
/**
* get the component's id
* ```js
* var id = mycomponent.id();
* ```
*
* @return {string}
* @method id
*/
component.prototype.id = function id() {
return this.id_;
};
/**
* get the component's name. the name is often used to reference the component.
* ```js
* var name = mycomponent.name();
* ```
*
* @return {string}
* @method name
*/
component.prototype.name = function name() {
return this.name_;
};
/**
* get an array of all child components
* ```js
* var kids = mycomponent.children();
* ```
*
* @return {array} the children
* @method children
*/
component.prototype.children = function children() {
return this.children_;
};
/**
* returns a child component with the provided id
*
* @return {component}
* @method getchildbyid
*/
component.prototype.getchildbyid = function getchildbyid(id) {
return this.childindex_[id];
};
/**
* returns a child component with the provided name
*
* @return {component}
* @method getchild
*/
component.prototype.getchild = function getchild(name) {
return this.childnameindex_[name];
};
/**
* adds a child component inside this component
* ```js
* mycomponent.el();
* // ->
* mycomponent.children();
* // [empty array]
*
* var mybutton = mycomponent.addchild('mybutton');
* // ->
mybutton
* // -> mybutton === mycomponent.children()[0];
* ```
* pass in options for child constructors and options for children of the child
* ```js
* var mybutton = mycomponent.addchild('mybutton', {
* text: 'press me',
* buttonchildexample: {
* buttonchildoption: true
* }
* });
* ```
*
* @param {string|component} child the class name or instance of a child to add
* @param {object=} options options, including options to be passed to children of the child.
* @param {number} index into our children array to attempt to add the child
* @return {component} the child component (created by this process if a string was used)
* @method addchild
*/
component.prototype.addchild = function addchild(child) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var index = arguments.length <= 2 || arguments[2] === undefined ? this.children_.length : arguments[2];
var component = undefined;
var componentname = undefined;
// if child is a string, create nt with options
if (typeof child === 'string') {
componentname = 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) {
_utilslogjs2['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 = {};
}
// if no componentclass in options, assume componentclass is the name lowercased
// (e.g. playbutton)
var componentclassname = options.componentclass || _utilstotitlecasejs2['default'](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 && 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, and the
* child component's element from this component's element
*
* @param {component} component component to remove
* @method removechild
*/
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 components from options
* ```js
* // when an instance of mycomponent is created, all children in options
* // will be added to the instance by their name strings and options
* mycomponent.prototype.options_ = {
* children: [
* 'mychildcomponent'
* ],
* mychildcomponent: {
* mychildoption: true
* }
* };
*
* // or when creating the component
* var mycomp = new mycomponent(player, {
* children: [
* 'mychildcomponent'
* ],
* mychildcomponent: {
* mychildoption: true
* }
* });
* ```
* the children option can also be an array of
* child options objects (that also include a 'name' key).
* this can be used if you have two child components of the
* same type that need different options.
* ```js
* var mycomp = new mycomponent(player, {
* children: [
* 'button',
* {
* name: 'button',
* someotheroption: true
* },
* {
* name: 'button',
* someotheroption: false
* }
* ]
* });
* ```
*
* @method initchildren
*/
component.prototype.initchildren = function initchildren() {
var _this = this;
var children = this.options_.children;
if (children) {
(function () {
// `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 = undefined;
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;
} else {
return child === wchild.name;
}
});
})).map(function (child) {
var name = undefined,
opts = undefined;
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 || _utilstotitlecasejs2['default'](child.name));
return c && !tech.istech(c);
}).foreach(handleadd);
})();
}
};
/**
* allows sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
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
* ```js
* var myfunc = function(){
* var mycomponent = this;
* // do something when the event is fired
* };
*
* mycomponent.on('eventtype', myfunc);
* ```
* the context of myfunc will be mycomponent unless previously bound.
* alternatively, you can add a listener to another element or component.
* ```js
* mycomponent.on(otherelement, 'eventname', myfunc);
* mycomponent.on(othercomponent, 'eventname', myfunc);
* ```
* the benefit of using this over `vjsevents.on(otherelement, 'eventname', myfunc)`
* and `othercomponent.on('eventname', myfunc)` is that this way the listeners
* will be automatically cleaned up when either component is disposed.
* it will also bind mycomponent as the context of myfunc.
* **note**: when using this on elements in the page other than window
* and document (both permanent), if you remove the element from the dom
* you need to call `mycomponent.trigger(el, 'dispose')` on it to clean up
* references to it and allow the browser to garbage collect it.
*
* @param {string|component} first the event type or other component
* @param {function|string} second the event handler or event type
* @param {function} third the event handler
* @return {component}
* @method on
*/
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 {
(function () {
var target = first;
var type = second;
var fn = fn.bind(_this2, 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;
_this2.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
* ```js
* mycomponent.off('eventtype', myfunc);
* ```
* if myfunc is excluded, all listeners for the event type will be removed.
* if eventtype is excluded, all listeners will be removed from the component.
* alternatively you can use `off` to remove listeners that were added to other
* elements or components using `mycomponent.on(othercomponent...`.
* in this case both the event type and listener function are required.
* ```js
* mycomponent.off(otherelement, 'eventtype', myfunc);
* mycomponent.off(othercomponent, 'eventtype', myfunc);
* ```
*
* @param {string=|component} first the event type or other component
* @param {function=|string} second the listener function or event type
* @param {function=} third the listener for other component
* @return {component}
* @method off
*/
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 to be triggered only once and then removed
* ```js
* mycomponent.one('eventname', myfunc);
* ```
* alternatively you can add a listener to another element or component
* that will be triggered only once.
* ```js
* mycomponent.one(otherelement, 'eventname', myfunc);
* mycomponent.one(othercomponent, 'eventname', myfunc);
* ```
*
* @param {string|component} first the event type or other component
* @param {function|string} second the listener function or event type
* @param {function=} third the listener function for other component
* @return {component}
* @method one
*/
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 {
(function () {
var target = first;
var type = second;
var fn = fn.bind(_this3, 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;
_this3.on(target, type, newfunc);
})();
}
return this;
};
/**
* trigger an event on an element
* ```js
* mycomponent.trigger('eventname');
* mycomponent.trigger({'type':'eventname'});
* mycomponent.trigger('eventname', {data: 'some data'});
* mycomponent.trigger({'type':'eventname'}, {data: 'some data'});
* ```
*
* @param {event|object|string} event a string (the type) or an event object with a type attribute
* @param {object} [hash] data hash to pass along with the event
* @return {component} self
* @method trigger
*/
component.prototype.trigger = function trigger(event, hash) {
events.trigger(this.el_, event, hash);
return this;
};
/**
* bind a listener to the component's ready state.
* different from event listeners in that if the ready event has already happened
* it will trigger the function immediately.
*
* @param {function} fn ready listener
* @param {boolean} sync exec the listener synchronously if component is ready
* @return {component}
* @method ready
*/
component.prototype.ready = function ready(fn) {
var sync = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];
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 the ready listeners
*
* @return {component}
* @method triggerready
*/
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
this.trigger('ready');
}, 1);
};
/**
* finds a single dom element matching `selector` within the component's
* `contentel` or another custom context.
*
* @method $
* @param {string} selector
* a valid css selector, which will be passed to `queryselector`.
*
* @param {element|string} [context=document]
* a dom element within which to query. can also be a selector
* string in which case the first matching element will be used
* as context. if missing (or no element matches selector), falls
* back to `document`.
*
* @return {element|null}
*/
component.prototype.$ = function $(selector, context) {
return dom.$(selector, context || this.contentel());
};
/**
* finds a all dom elements matching `selector` within the component's
* `contentel` or another custom context.
*
* @method $$
* @param {string} selector
* a valid css selector, which will be passed to `queryselectorall`.
*
* @param {element|string} [context=document]
* a dom element within which to query. can also be a selector
* string in which case the first matching element will be used
* as context. if missing (or no element matches selector), falls
* back to `document`.
*
* @return {nodelist}
*/
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 classname to check
* @return {component}
* @method hasclass
*/
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 classname to add
* @return {component}
* @method addclass
*/
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 classname to remove
* @return {component}
* @method removeclass
*/
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
*
* @param {string} classtotoggle
* @param {boolean|function} [predicate]
* can be a function that returns a boolean. if `true`, the class
* will be added; if `false`, the class will be removed. if not
* given, the class will be added if not present and vice versa.
*
* @return {component}
* @method toggleclass
*/
component.prototype.toggleclass = function toggleclass(classtotoggle, predicate) {
dom.toggleelclass(this.el_, classtotoggle, predicate);
return this;
};
/**
* show the component element if hidden
*
* @return {component}
* @method show
*/
component.prototype.show = function show() {
this.removeclass('vjs-hidden');
return this;
};
/**
* hide the component element if currently showing
*
* @return {component}
* @method hide
*/
component.prototype.hide = function hide() {
this.addclass('vjs-hidden');
return this;
};
/**
* lock an item in its visible state
* to be used with fadein/fadeout.
*
* @return {component}
* @private
* @method lockshowing
*/
component.prototype.lockshowing = function lockshowing() {
this.addclass('vjs-lock-showing');
return this;
};
/**
* unlock an item to be hidden
* to be used with fadein/fadeout.
*
* @return {component}
* @private
* @method unlockshowing
*/
component.prototype.unlockshowing = function unlockshowing() {
this.removeclass('vjs-lock-showing');
return this;
};
/**
* set or get the width of the component (css values)
* setting the video tag dimension values only works with values in pixels.
* percent values will not work.
* some percents can be used, but width()/height() will return the number + %,
* not the actual computed width/height.
*
* @param {number|string=} num optional width number
* @param {boolean} skiplisteners skip the 'resize' event trigger
* @return {component} this component, when setting the width
* @return {number|string} the width, when getting
* @method width
*/
component.prototype.width = function width(num, skiplisteners) {
return this.dimension('width', num, skiplisteners);
};
/**
* get or set the height of the component (css values)
* setting the video tag dimension values only works with values in pixels.
* percent values will not work.
* some percents can be used, but width()/height() will return the number + %,
* not the actual computed width/height.
*
* @param {number|string=} num new component height
* @param {boolean=} skiplisteners skip the resize event trigger
* @return {component} this component, when setting the height
* @return {number|string} the height, when getting
* @method height
*/
component.prototype.height = function height(num, skiplisteners) {
return this.dimension('height', num, skiplisteners);
};
/**
* set both width and height at the same time
*
* @param {number|string} width width of player
* @param {number|string} height height of player
* @return {component} the component
* @method dimensions
*/
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
* this is the shared code for the width() and height() methods.
* all for an integer, integer + 'px' or integer + '%';
* known issue: hidden elements officially have a width of 0. we're defaulting
* to the style.width value and falling back to computedstyle which has the
* hidden element issue. info, but probably not an efficient fix:
* http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/
*
* @param {string} widthorheight 'width' or 'height'
* @param {number|string=} num new dimension
* @param {boolean=} skiplisteners skip resize event trigger
* @return {component} the component if a dimension was set
* @return {number|string} the dimension if nothing was set
* @private
* @method dimension
*/
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) {
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' + _utilstotitlecasejs2['default'](widthorheight)], 10);
};
/**
* emit 'tap' events when touch events are supported
* this is used to support toggling the controls through a tap on the video.
* we're requiring them to be enabled because otherwise every component would
* have this extra overhead unnecessarily, on mobile devices where extra
* overhead is especially bad.
*
* @private
* @method emittapevents
*/
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 = undefined;
this.on('touchstart', function (event) {
// if more than one finger, don't consider treating this as a click
if (event.touches.length === 1) {
// copy the touches object to prevent modifying the original
firsttouch = _objectassign2['default']({}, event.touches[0]);
// 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();
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)
}
}
});
};
/**
* report user touch activity when touch events occur
* user activity is used to determine when controls should show/hide. it's
* relatively simple when it comes to mouse events, because any mouse event
* should show the controls. so we capture mouse events that bubble up to the
* player and report activity when that happens.
* with touch events it isn't as easy. we can't rely on touch events at the
* player level, because a tap (touchstart + touchend) on the video itself on
* mobile devices is meant to turn controls off (and on). user activity is
* 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)
* also a touchmove, touch+hold, and anything other than a tap is not supposed
* to turn the controls back on on a mobile device.
* here we're setting the default component behavior to report user activity
* whenever touch events happen, and this can be turned off by components that
* want touch events to act differently.
*
* @method enabletouchactivity
*/
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 = undefined;
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);
};
/**
* creates timeout and sets up disposal automatically.
*
* @param {function} fn the function to run after the timeout.
* @param {number} timeout number of ms to delay before executing specified function.
* @return {number} returns the timeout id
* @method settimeout
*/
component.prototype.settimeout = function settimeout(fn, timeout) {
fn = fn.bind(this, fn);
// window.settimeout would be preferable here, but due to some bizarre issue with sinon and/or phantomjs, we can't.
var timeoutid = _globalwindow2['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 and removes the associated dispose listener
*
* @param {number} timeoutid the id of the timeout to clear
* @return {number} returns the timeout id
* @method cleartimeout
*/
component.prototype.cleartimeout = function cleartimeout(timeoutid) {
_globalwindow2['default'].cleartimeout(timeoutid);
var disposefn = function disposefn() {};
disposefn.guid = 'vjs-timeout-' + timeoutid;
this.off('dispose', disposefn);
return timeoutid;
};
/**
* creates an interval and sets up disposal automatically.
*
* @param {function} fn the function to run every n seconds.
* @param {number} interval number of ms to delay before executing specified function.
* @return {number} returns the interval id
* @method setinterval
*/
component.prototype.setinterval = function setinterval(fn, interval) {
fn = fn.bind(this, fn);
var intervalid = _globalwindow2['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 and removes the associated dispose listener
*
* @param {number} intervalid the id of the interval to clear
* @return {number} returns the interval id
* @method clearinterval
*/
component.prototype.clearinterval = function clearinterval(intervalid) {
_globalwindow2['default'].clearinterval(intervalid);
var disposefn = function disposefn() {};
disposefn.guid = 'vjs-interval-' + intervalid;
this.off('dispose', disposefn);
return intervalid;
};
/**
* registers a component
*
* @param {string} name name of the component to register
* @param {object} comp the component to register
* @static
* @method registercomponent
*/
component.registercomponent = function registercomponent(name, comp) {
if (!component.components_) {
component.components_ = {};
}
component.components_[name] = comp;
return comp;
};
/**
* gets a component by name
*
* @param {string} name name of the component to get
* @return {component}
* @static
* @method getcomponent
*/
component.getcomponent = function getcomponent(name) {
if (component.components_ && component.components_[name]) {
return component.components_[name];
}
if (_globalwindow2['default'] && _globalwindow2['default'].videojs && _globalwindow2['default'].videojs[name]) {
_utilslogjs2['default'].warn('the ' + name + ' component was added to the videojs object when it should be registered using videojs.registercomponent(name, component)');
return _globalwindow2['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
* @static
* @deprecated
* @method extend
*/
component.extend = function extend(props) {
props = props || {};
_utilslogjs2['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;
module.exports = exports['default'];
},{"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/guid.js":136,"./utils/log.js":137,"./utils/merge-options.js":138,"./utils/to-title-case.js":141,"global/window":2,"object.assign":45}],68:[function(_dereq_,module,exports){
/**
* @file control-bar.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
// required children
var _playtogglejs = _dereq_('./play-toggle.js');
var _playtogglejs2 = _interoprequiredefault(_playtogglejs);
var _timecontrolscurrenttimedisplayjs = _dereq_('./time-controls/current-time-display.js');
var _timecontrolscurrenttimedisplayjs2 = _interoprequiredefault(_timecontrolscurrenttimedisplayjs);
var _timecontrolsdurationdisplayjs = _dereq_('./time-controls/duration-display.js');
var _timecontrolsdurationdisplayjs2 = _interoprequiredefault(_timecontrolsdurationdisplayjs);
var _timecontrolstimedividerjs = _dereq_('./time-controls/time-divider.js');
var _timecontrolstimedividerjs2 = _interoprequiredefault(_timecontrolstimedividerjs);
var _timecontrolsremainingtimedisplayjs = _dereq_('./time-controls/remaining-time-display.js');
var _timecontrolsremainingtimedisplayjs2 = _interoprequiredefault(_timecontrolsremainingtimedisplayjs);
var _livedisplayjs = _dereq_('./live-display.js');
var _livedisplayjs2 = _interoprequiredefault(_livedisplayjs);
var _progresscontrolprogresscontroljs = _dereq_('./progress-control/progress-control.js');
var _progresscontrolprogresscontroljs2 = _interoprequiredefault(_progresscontrolprogresscontroljs);
var _fullscreentogglejs = _dereq_('./fullscreen-toggle.js');
var _fullscreentogglejs2 = _interoprequiredefault(_fullscreentogglejs);
var _volumecontrolvolumecontroljs = _dereq_('./volume-control/volume-control.js');
var _volumecontrolvolumecontroljs2 = _interoprequiredefault(_volumecontrolvolumecontroljs);
var _volumemenubuttonjs = _dereq_('./volume-menu-button.js');
var _volumemenubuttonjs2 = _interoprequiredefault(_volumemenubuttonjs);
var _mutetogglejs = _dereq_('./mute-toggle.js');
var _mutetogglejs2 = _interoprequiredefault(_mutetogglejs);
var _texttrackcontrolschaptersbuttonjs = _dereq_('./text-track-controls/chapters-button.js');
var _texttrackcontrolschaptersbuttonjs2 = _interoprequiredefault(_texttrackcontrolschaptersbuttonjs);
var _texttrackcontrolssubtitlesbuttonjs = _dereq_('./text-track-controls/subtitles-button.js');
var _texttrackcontrolssubtitlesbuttonjs2 = _interoprequiredefault(_texttrackcontrolssubtitlesbuttonjs);
var _texttrackcontrolscaptionsbuttonjs = _dereq_('./text-track-controls/captions-button.js');
var _texttrackcontrolscaptionsbuttonjs2 = _interoprequiredefault(_texttrackcontrolscaptionsbuttonjs);
var _playbackratemenuplaybackratemenubuttonjs = _dereq_('./playback-rate-menu/playback-rate-menu-button.js');
var _playbackratemenuplaybackratemenubuttonjs2 = _interoprequiredefault(_playbackratemenuplaybackratemenubuttonjs);
var _spacercontrolscustomcontrolspacerjs = _dereq_('./spacer-controls/custom-control-spacer.js');
var _spacercontrolscustomcontrolspacerjs2 = _interoprequiredefault(_spacercontrolscustomcontrolspacerjs);
/**
* container of main controls
*
* @extends component
* @class controlbar
*/
var controlbar = (function (_component) {
_inherits(controlbar, _component);
function controlbar() {
_classcallcheck(this, controlbar);
_component.apply(this, arguments);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
controlbar.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-control-bar',
dir: 'ltr'
}, {
'role': 'group' // the control bar is a group, so it can contain menuitems
});
};
return controlbar;
})(_componentjs2['default']);
controlbar.prototype.options_ = {
loadevent: 'play',
children: ['playtoggle', 'volumemenubutton', 'currenttimedisplay', 'timedivider', 'durationdisplay', 'progresscontrol', 'livedisplay', 'remainingtimedisplay', 'customcontrolspacer', 'playbackratemenubutton', 'chaptersbutton', 'subtitlesbutton', 'captionsbutton', 'fullscreentoggle']
};
_componentjs2['default'].registercomponent('controlbar', controlbar);
exports['default'] = controlbar;
module.exports = exports['default'];
},{"../component.js":67,"./fullscreen-toggle.js":69,"./live-display.js":70,"./mute-toggle.js":71,"./play-toggle.js":72,"./playback-rate-menu/playback-rate-menu-button.js":73,"./progress-control/progress-control.js":78,"./spacer-controls/custom-control-spacer.js":80,"./text-track-controls/captions-button.js":83,"./text-track-controls/chapters-button.js":84,"./text-track-controls/subtitles-button.js":87,"./time-controls/current-time-display.js":90,"./time-controls/duration-display.js":91,"./time-controls/remaining-time-display.js":92,"./time-controls/time-divider.js":93,"./volume-control/volume-control.js":95,"./volume-menu-button.js":97}],69:[function(_dereq_,module,exports){
/**
* @file fullscreen-toggle.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _buttonjs = _dereq_('../button.js');
var _buttonjs2 = _interoprequiredefault(_buttonjs);
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* toggle fullscreen video
*
* @extends button
* @class fullscreentoggle
*/
var fullscreentoggle = (function (_button) {
_inherits(fullscreentoggle, _button);
function fullscreentoggle() {
_classcallcheck(this, fullscreentoggle);
_button.apply(this, arguments);
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
fullscreentoggle.prototype.buildcssclass = function buildcssclass() {
return 'vjs-fullscreen-control ' + _button.prototype.buildcssclass.call(this);
};
/**
* handles click for full screen
*
* @method handleclick
*/
fullscreentoggle.prototype.handleclick = function handleclick() {
if (!this.player_.isfullscreen()) {
this.player_.requestfullscreen();
this.controltext('non-fullscreen');
} else {
this.player_.exitfullscreen();
this.controltext('fullscreen');
}
};
return fullscreentoggle;
})(_buttonjs2['default']);
fullscreentoggle.prototype.controltext_ = 'fullscreen';
_componentjs2['default'].registercomponent('fullscreentoggle', fullscreentoggle);
exports['default'] = fullscreentoggle;
module.exports = exports['default'];
},{"../button.js":64,"../component.js":67}],70:[function(_dereq_,module,exports){
/**
* @file live-display.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _component = _dereq_('../component');
var _component2 = _interoprequiredefault(_component);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
/**
* displays the live indicator
* todo - future make it click to snap to live
*
* @extends component
* @class livedisplay
*/
var livedisplay = (function (_component) {
_inherits(livedisplay, _component);
function livedisplay(player, options) {
_classcallcheck(this, livedisplay);
_component.call(this, player, options);
this.updateshowing();
this.on(this.player(), 'durationchange', this.updateshowing);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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;
};
livedisplay.prototype.updateshowing = function updateshowing() {
if (this.player().duration() === infinity) {
this.show();
} else {
this.hide();
}
};
return livedisplay;
})(_component2['default']);
_component2['default'].registercomponent('livedisplay', livedisplay);
exports['default'] = livedisplay;
module.exports = exports['default'];
},{"../component":67,"../utils/dom.js":132}],71:[function(_dereq_,module,exports){
/**
* @file mute-toggle.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _button = _dereq_('../button');
var _button2 = _interoprequiredefault(_button);
var _component = _dereq_('../component');
var _component2 = _interoprequiredefault(_component);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
/**
* a button component for muting the audio
*
* @param {player|object} player
* @param {object=} options
* @extends button
* @class mutetoggle
*/
var mutetoggle = (function (_button) {
_inherits(mutetoggle, _button);
function mutetoggle(player, options) {
_classcallcheck(this, mutetoggle);
_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 () {
this.update(); // we need to update the button to account for a default muted state.
if (player.tech_['featuresvolumecontrol'] === false) {
this.addclass('vjs-hidden');
} else {
this.removeclass('vjs-hidden');
}
});
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
mutetoggle.prototype.buildcssclass = function buildcssclass() {
return 'vjs-mute-control ' + _button.prototype.buildcssclass.call(this);
};
/**
* handle click on mute
*
* @method handleclick
*/
mutetoggle.prototype.handleclick = function handleclick() {
this.player_.muted(this.player_.muted() ? false : true);
};
/**
* update volume
*
* @method update
*/
mutetoggle.prototype.update = function update() {
var vol = this.player_.volume(),
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']);
mutetoggle.prototype.controltext_ = 'mute';
_component2['default'].registercomponent('mutetoggle', mutetoggle);
exports['default'] = mutetoggle;
module.exports = exports['default'];
},{"../button":64,"../component":67,"../utils/dom.js":132}],72:[function(_dereq_,module,exports){
/**
* @file play-toggle.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _buttonjs = _dereq_('../button.js');
var _buttonjs2 = _interoprequiredefault(_buttonjs);
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* button to toggle between play and pause
*
* @param {player|object} player
* @param {object=} options
* @extends button
* @class playtoggle
*/
var playtoggle = (function (_button) {
_inherits(playtoggle, _button);
function playtoggle(player, options) {
_classcallcheck(this, playtoggle);
_button.call(this, player, options);
this.on(player, 'play', this.handleplay);
this.on(player, 'pause', this.handlepause);
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
playtoggle.prototype.buildcssclass = function buildcssclass() {
return 'vjs-play-control ' + _button.prototype.buildcssclass.call(this);
};
/**
* handle click to toggle between play and pause
*
* @method handleclick
*/
playtoggle.prototype.handleclick = function handleclick() {
if (this.player_.paused()) {
this.player_.play();
} else {
this.player_.pause();
}
};
/**
* add the vjs-playing class to the element so it can change appearance
*
* @method handleplay
*/
playtoggle.prototype.handleplay = function handleplay() {
this.removeclass('vjs-paused');
this.addclass('vjs-playing');
this.controltext('pause'); // change the button text to "pause"
};
/**
* add the vjs-paused class to the element so it can change appearance
*
* @method handlepause
*/
playtoggle.prototype.handlepause = function handlepause() {
this.removeclass('vjs-playing');
this.addclass('vjs-paused');
this.controltext('play'); // change the button text to "play"
};
return playtoggle;
})(_buttonjs2['default']);
playtoggle.prototype.controltext_ = 'play';
_componentjs2['default'].registercomponent('playtoggle', playtoggle);
exports['default'] = playtoggle;
module.exports = exports['default'];
},{"../button.js":64,"../component.js":67}],73:[function(_dereq_,module,exports){
/**
* @file playback-rate-menu-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _menumenubuttonjs = _dereq_('../../menu/menu-button.js');
var _menumenubuttonjs2 = _interoprequiredefault(_menumenubuttonjs);
var _menumenujs = _dereq_('../../menu/menu.js');
var _menumenujs2 = _interoprequiredefault(_menumenujs);
var _playbackratemenuitemjs = _dereq_('./playback-rate-menu-item.js');
var _playbackratemenuitemjs2 = _interoprequiredefault(_playbackratemenuitemjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
/**
* the component for controlling the playback rate
*
* @param {player|object} player
* @param {object=} options
* @extends menubutton
* @class playbackratemenubutton
*/
var playbackratemenubutton = (function (_menubutton) {
_inherits(playbackratemenubutton, _menubutton);
function playbackratemenubutton(player, options) {
_classcallcheck(this, playbackratemenubutton);
_menubutton.call(this, player, options);
this.updatevisibility();
this.updatelabel();
this.on(player, 'loadstart', this.updatevisibility);
this.on(player, 'ratechange', this.updatelabel);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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;
};
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
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 items
* @method createmenu
*/
playbackratemenubutton.prototype.createmenu = function createmenu() {
var menu = new _menumenujs2['default'](this.player());
var rates = this.playbackrates();
if (rates) {
for (var i = rates.length - 1; i >= 0; i--) {
menu.addchild(new _playbackratemenuitemjs2['default'](this.player(), { 'rate': rates[i] + 'x' }));
}
}
return menu;
};
/**
* updates aria accessibility attributes
*
* @method updateariaattributes
*/
playbackratemenubutton.prototype.updateariaattributes = function updateariaattributes() {
// current playback rate
this.el().setattribute('aria-valuenow', this.player().playbackrate());
};
/**
* handle menu item click
*
* @method handleclick
*/
playbackratemenubutton.prototype.handleclick = function handleclick() {
// 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} possible playback rates
* @method playbackrates
*/
playbackratemenubutton.prototype.playbackrates = function playbackrates() {
return this.options_['playbackrates'] || this.options_.playeroptions && this.options_.playeroptions['playbackrates'];
};
/**
* get supported playback rates
*
* @return {array} supported playback rates
* @method playbackratesupported
*/
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
*
* @method updatevisibility
*/
playbackratemenubutton.prototype.updatevisibility = function updatevisibility() {
if (this.playbackratesupported()) {
this.removeclass('vjs-hidden');
} else {
this.addclass('vjs-hidden');
}
};
/**
* update button label when rate changed
*
* @method updatelabel
*/
playbackratemenubutton.prototype.updatelabel = function updatelabel() {
if (this.playbackratesupported()) {
this.labelel_.innerhtml = this.player().playbackrate() + 'x';
}
};
return playbackratemenubutton;
})(_menumenubuttonjs2['default']);
playbackratemenubutton.prototype.controltext_ = 'playback rate';
_componentjs2['default'].registercomponent('playbackratemenubutton', playbackratemenubutton);
exports['default'] = playbackratemenubutton;
module.exports = exports['default'];
},{"../../component.js":67,"../../menu/menu-button.js":104,"../../menu/menu.js":106,"../../utils/dom.js":132,"./playback-rate-menu-item.js":74}],74:[function(_dereq_,module,exports){
/**
* @file playback-rate-menu-item.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _menumenuitemjs = _dereq_('../../menu/menu-item.js');
var _menumenuitemjs2 = _interoprequiredefault(_menumenuitemjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* the specific menu item type for selecting a playback rate
*
* @param {player|object} player
* @param {object=} options
* @extends menuitem
* @class playbackratemenuitem
*/
var playbackratemenuitem = (function (_menuitem) {
_inherits(playbackratemenuitem, _menuitem);
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;
_menuitem.call(this, player, options);
this.label = label;
this.rate = rate;
this.on(player, 'ratechange', this.update);
}
/**
* handle click on menu item
*
* @method handleclick
*/
playbackratemenuitem.prototype.handleclick = function handleclick() {
_menuitem.prototype.handleclick.call(this);
this.player().playbackrate(this.rate);
};
/**
* update playback rate with selected rate
*
* @method update
*/
playbackratemenuitem.prototype.update = function update() {
this.selected(this.player().playbackrate() === this.rate);
};
return playbackratemenuitem;
})(_menumenuitemjs2['default']);
playbackratemenuitem.prototype.contenteltype = 'button';
_componentjs2['default'].registercomponent('playbackratemenuitem', playbackratemenuitem);
exports['default'] = playbackratemenuitem;
module.exports = exports['default'];
},{"../../component.js":67,"../../menu/menu-item.js":105}],75:[function(_dereq_,module,exports){
/**
* @file load-progress-bar.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
/**
* shows load progress
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class loadprogressbar
*/
var loadprogressbar = (function (_component) {
_inherits(loadprogressbar, _component);
function loadprogressbar(player, options) {
_classcallcheck(this, loadprogressbar);
_component.call(this, player, options);
this.on(player, 'progress', this.update);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
loadprogressbar.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-load-progress',
innerhtml: '' + this.localize('loaded') + ': 0%'
});
};
/**
* update progress bar
*
* @method update
*/
loadprogressbar.prototype.update = function update() {
var buffered = this.player_.buffered();
var duration = this.player_.duration();
var bufferedend = this.player_.bufferedend();
var children = this.el_.children;
// get the percent width of a time compared to the total end
var percentify = function percentify(time, end) {
var percent = time / end || 0; // no nan
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());
}
// 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]);
}
};
return loadprogressbar;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('loadprogressbar', loadprogressbar);
exports['default'] = loadprogressbar;
module.exports = exports['default'];
},{"../../component.js":67,"../../utils/dom.js":132}],76:[function(_dereq_,module,exports){
/**
* @file mouse-time-display.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsformattimejs = _dereq_('../../utils/format-time.js');
var _utilsformattimejs2 = _interoprequiredefault(_utilsformattimejs);
var _lodashcompatfunctionthrottle = _dereq_('lodash-compat/function/throttle');
var _lodashcompatfunctionthrottle2 = _interoprequiredefault(_lodashcompatfunctionthrottle);
/**
* the mouse time display component shows the time you will seek to
* when hovering over the progress bar
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class mousetimedisplay
*/
var mousetimedisplay = (function (_component) {
_inherits(mousetimedisplay, _component);
function mousetimedisplay(player, options) {
var _this = this;
_classcallcheck(this, mousetimedisplay);
_component.call(this, player, options);
this.update(0, 0);
player.on('ready', function () {
_this.on(player.controlbar.progresscontrol.el(), 'mousemove', _lodashcompatfunctionthrottle2['default'](fn.bind(_this, _this.handlemousemove), 25));
});
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
mousetimedisplay.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-mouse-display'
});
};
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);
};
mousetimedisplay.prototype.update = function update(newtime, position) {
var time = _utilsformattimejs2['default'](newtime, this.player_.duration());
this.el().style.left = position + 'px';
this.el().setattribute('data-current-time', time);
};
mousetimedisplay.prototype.calculatedistance = function calculatedistance(event) {
return dom.getpointerposition(this.el().parentnode, event).x;
};
return mousetimedisplay;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('mousetimedisplay', mousetimedisplay);
exports['default'] = mousetimedisplay;
module.exports = exports['default'];
},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/fn.js":134,"../../utils/format-time.js":135,"lodash-compat/function/throttle":7}],77:[function(_dereq_,module,exports){
/**
* @file play-progress-bar.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsformattimejs = _dereq_('../../utils/format-time.js');
var _utilsformattimejs2 = _interoprequiredefault(_utilsformattimejs);
/**
* shows play progress
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class playprogressbar
*/
var playprogressbar = (function (_component) {
_inherits(playprogressbar, _component);
function playprogressbar(player, options) {
_classcallcheck(this, playprogressbar);
_component.call(this, player, options);
this.updatedataattr();
this.on(player, 'timeupdate', this.updatedataattr);
player.ready(fn.bind(this, this.updatedataattr));
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
playprogressbar.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-play-progress vjs-slider-bar',
innerhtml: '' + this.localize('progress') + ': 0%'
});
};
playprogressbar.prototype.updatedataattr = function updatedataattr() {
var time = this.player_.scrubbing() ? this.player_.getcache().currenttime : this.player_.currenttime();
this.el_.setattribute('data-current-time', _utilsformattimejs2['default'](time, this.player_.duration()));
};
return playprogressbar;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('playprogressbar', playprogressbar);
exports['default'] = playprogressbar;
module.exports = exports['default'];
},{"../../component.js":67,"../../utils/fn.js":134,"../../utils/format-time.js":135}],78:[function(_dereq_,module,exports){
/**
* @file progress-control.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _seekbarjs = _dereq_('./seek-bar.js');
var _seekbarjs2 = _interoprequiredefault(_seekbarjs);
var _mousetimedisplayjs = _dereq_('./mouse-time-display.js');
var _mousetimedisplayjs2 = _interoprequiredefault(_mousetimedisplayjs);
/**
* the progress control component contains the seek bar, load progress,
* and play progress
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class progresscontrol
*/
var progresscontrol = (function (_component) {
_inherits(progresscontrol, _component);
function progresscontrol() {
_classcallcheck(this, progresscontrol);
_component.apply(this, arguments);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
progresscontrol.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-progress-control vjs-control'
});
};
return progresscontrol;
})(_componentjs2['default']);
progresscontrol.prototype.options_ = {
children: ['seekbar']
};
_componentjs2['default'].registercomponent('progresscontrol', progresscontrol);
exports['default'] = progresscontrol;
module.exports = exports['default'];
},{"../../component.js":67,"./mouse-time-display.js":76,"./seek-bar.js":79}],79:[function(_dereq_,module,exports){
/**
* @file seek-bar.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _slidersliderjs = _dereq_('../../slider/slider.js');
var _slidersliderjs2 = _interoprequiredefault(_slidersliderjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _loadprogressbarjs = _dereq_('./load-progress-bar.js');
var _loadprogressbarjs2 = _interoprequiredefault(_loadprogressbarjs);
var _playprogressbarjs = _dereq_('./play-progress-bar.js');
var _playprogressbarjs2 = _interoprequiredefault(_playprogressbarjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsformattimejs = _dereq_('../../utils/format-time.js');
var _utilsformattimejs2 = _interoprequiredefault(_utilsformattimejs);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
/**
* seek bar and holder for the progress bars
*
* @param {player|object} player
* @param {object=} options
* @extends slider
* @class seekbar
*/
var seekbar = (function (_slider) {
_inherits(seekbar, _slider);
function seekbar(player, options) {
_classcallcheck(this, seekbar);
_slider.call(this, player, options);
this.on(player, 'timeupdate', this.updateariaattributes);
player.ready(fn.bind(this, this.updateariaattributes));
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
seekbar.prototype.createel = function createel() {
return _slider.prototype.createel.call(this, 'div', {
classname: 'vjs-progress-holder'
}, {
'aria-label': 'video progress bar'
});
};
/**
* update aria accessibility attributes
*
* @method updateariaattributes
*/
seekbar.prototype.updateariaattributes = function updateariaattributes() {
// allows for smooth scrubbing, when player can't keep up.
var time = this.player_.scrubbing() ? this.player_.getcache().currenttime : this.player_.currenttime();
this.el_.setattribute('aria-valuenow', (this.getpercent() * 100).tofixed(2)); // machine readable value of progress bar (percentage complete)
this.el_.setattribute('aria-valuetext', _utilsformattimejs2['default'](time, this.player_.duration())); // human readable value of progress bar (time complete)
};
/**
* get percentage of video played
*
* @return {number} percentage played
* @method getpercent
*/
seekbar.prototype.getpercent = function getpercent() {
var percent = this.player_.currenttime() / this.player_.duration();
return percent >= 1 ? 1 : percent;
};
/**
* handle mouse down on seek bar
*
* @method handlemousedown
*/
seekbar.prototype.handlemousedown = function handlemousedown(event) {
_slider.prototype.handlemousedown.call(this, event);
this.player_.scrubbing(true);
this.videowasplaying = !this.player_.paused();
this.player_.pause();
};
/**
* handle mouse move on seek bar
*
* @method handlemousemove
*/
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
*
* @method handlemouseup
*/
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
*
* @method stepforward
*/
seekbar.prototype.stepforward = function stepforward() {
this.player_.currenttime(this.player_.currenttime() + 5); // more quickly fast forward for keyboard-only users
};
/**
* move more quickly rewind for keyboard-only users
*
* @method stepback
*/
seekbar.prototype.stepback = function stepback() {
this.player_.currenttime(this.player_.currenttime() - 5); // more quickly rewind for keyboard-only users
};
return seekbar;
})(_slidersliderjs2['default']);
seekbar.prototype.options_ = {
children: ['loadprogressbar', 'mousetimedisplay', 'playprogressbar'],
'barname': 'playprogressbar'
};
seekbar.prototype.playerevent = 'timeupdate';
_componentjs2['default'].registercomponent('seekbar', seekbar);
exports['default'] = seekbar;
module.exports = exports['default'];
},{"../../component.js":67,"../../slider/slider.js":114,"../../utils/fn.js":134,"../../utils/format-time.js":135,"./load-progress-bar.js":75,"./play-progress-bar.js":77,"object.assign":45}],80:[function(_dereq_,module,exports){
/**
* @file custom-control-spacer.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _spacerjs = _dereq_('./spacer.js');
var _spacerjs2 = _interoprequiredefault(_spacerjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* spacer specifically meant to be used as an insertion point for new plugins, etc.
*
* @extends spacer
* @class customcontrolspacer
*/
var customcontrolspacer = (function (_spacer) {
_inherits(customcontrolspacer, _spacer);
function customcontrolspacer() {
_classcallcheck(this, customcontrolspacer);
_spacer.apply(this, arguments);
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
customcontrolspacer.prototype.buildcssclass = function buildcssclass() {
return 'vjs-custom-control-spacer ' + _spacer.prototype.buildcssclass.call(this);
};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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;
})(_spacerjs2['default']);
_componentjs2['default'].registercomponent('customcontrolspacer', customcontrolspacer);
exports['default'] = customcontrolspacer;
module.exports = exports['default'];
},{"../../component.js":67,"./spacer.js":81}],81:[function(_dereq_,module,exports){
/**
* @file spacer.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* 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
* @class spacer
*/
var spacer = (function (_component) {
_inherits(spacer, _component);
function spacer() {
_classcallcheck(this, spacer);
_component.apply(this, arguments);
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
spacer.prototype.buildcssclass = function buildcssclass() {
return 'vjs-spacer ' + _component.prototype.buildcssclass.call(this);
};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
spacer.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: this.buildcssclass()
});
};
return spacer;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('spacer', spacer);
exports['default'] = spacer;
module.exports = exports['default'];
},{"../../component.js":67}],82:[function(_dereq_,module,exports){
/**
* @file caption-settings-menu-item.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _texttrackmenuitemjs = _dereq_('./text-track-menu-item.js');
var _texttrackmenuitemjs2 = _interoprequiredefault(_texttrackmenuitemjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* the menu item for caption track settings menu
*
* @param {player|object} player
* @param {object=} options
* @extends texttrackmenuitem
* @class captionsettingsmenuitem
*/
var captionsettingsmenuitem = (function (_texttrackmenuitem) {
_inherits(captionsettingsmenuitem, _texttrackmenuitem);
function captionsettingsmenuitem(player, options) {
_classcallcheck(this, captionsettingsmenuitem);
options['track'] = {
'kind': options['kind'],
'player': player,
'label': options['kind'] + ' settings',
'selectable': false,
'default': false,
mode: 'disabled'
};
// captionsettingsmenuitem has no concept of 'selected'
options['selectable'] = false;
_texttrackmenuitem.call(this, player, options);
this.addclass('vjs-texttrack-settings');
this.controltext(', opens ' + options['kind'] + ' settings dialog');
}
/**
* handle click on menu item
*
* @method handleclick
*/
captionsettingsmenuitem.prototype.handleclick = function handleclick() {
this.player().getchild('texttracksettings').show();
this.player().getchild('texttracksettings').el_.focus();
};
return captionsettingsmenuitem;
})(_texttrackmenuitemjs2['default']);
_componentjs2['default'].registercomponent('captionsettingsmenuitem', captionsettingsmenuitem);
exports['default'] = captionsettingsmenuitem;
module.exports = exports['default'];
},{"../../component.js":67,"./text-track-menu-item.js":89}],83:[function(_dereq_,module,exports){
/**
* @file captions-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _texttrackbuttonjs = _dereq_('./text-track-button.js');
var _texttrackbuttonjs2 = _interoprequiredefault(_texttrackbuttonjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _captionsettingsmenuitemjs = _dereq_('./caption-settings-menu-item.js');
var _captionsettingsmenuitemjs2 = _interoprequiredefault(_captionsettingsmenuitemjs);
/**
* the button component for toggling and selecting captions
*
* @param {object} player player object
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends texttrackbutton
* @class captionsbutton
*/
var captionsbutton = (function (_texttrackbutton) {
_inherits(captionsbutton, _texttrackbutton);
function captionsbutton(player, options, ready) {
_classcallcheck(this, captionsbutton);
_texttrackbutton.call(this, player, options, ready);
this.el_.setattribute('aria-label', 'captions menu');
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
captionsbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-captions-button ' + _texttrackbutton.prototype.buildcssclass.call(this);
};
/**
* update caption menu items
*
* @method update
*/
captionsbutton.prototype.update = function update() {
var threshold = 2;
_texttrackbutton.prototype.update.call(this);
// if native, then threshold is 1 because no settings button
if (this.player().tech_ && this.player().tech_['featuresnativetexttracks']) {
threshold = 1;
}
if (this.items && this.items.length > threshold) {
this.show();
} else {
this.hide();
}
};
/**
* create caption menu items
*
* @return {array} array of menu items
* @method createitems
*/
captionsbutton.prototype.createitems = function createitems() {
var items = [];
if (!(this.player().tech_ && this.player().tech_['featuresnativetexttracks'])) {
items.push(new _captionsettingsmenuitemjs2['default'](this.player_, { 'kind': this.kind_ }));
}
return _texttrackbutton.prototype.createitems.call(this, items);
};
return captionsbutton;
})(_texttrackbuttonjs2['default']);
captionsbutton.prototype.kind_ = 'captions';
captionsbutton.prototype.controltext_ = 'captions';
_componentjs2['default'].registercomponent('captionsbutton', captionsbutton);
exports['default'] = captionsbutton;
module.exports = exports['default'];
},{"../../component.js":67,"./caption-settings-menu-item.js":82,"./text-track-button.js":88}],84:[function(_dereq_,module,exports){
/**
* @file chapters-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _texttrackbuttonjs = _dereq_('./text-track-button.js');
var _texttrackbuttonjs2 = _interoprequiredefault(_texttrackbuttonjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _texttrackmenuitemjs = _dereq_('./text-track-menu-item.js');
var _texttrackmenuitemjs2 = _interoprequiredefault(_texttrackmenuitemjs);
var _chapterstrackmenuitemjs = _dereq_('./chapters-track-menu-item.js');
var _chapterstrackmenuitemjs2 = _interoprequiredefault(_chapterstrackmenuitemjs);
var _menumenujs = _dereq_('../../menu/menu.js');
var _menumenujs2 = _interoprequiredefault(_menumenujs);
var _utilsdomjs = _dereq_('../../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilstotitlecasejs = _dereq_('../../utils/to-title-case.js');
var _utilstotitlecasejs2 = _interoprequiredefault(_utilstotitlecasejs);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
/**
* 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
*
* @param {object} player player object
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends texttrackbutton
* @class chaptersbutton
*/
var chaptersbutton = (function (_texttrackbutton) {
_inherits(chaptersbutton, _texttrackbutton);
function chaptersbutton(player, options, ready) {
_classcallcheck(this, chaptersbutton);
_texttrackbutton.call(this, player, options, ready);
this.el_.setattribute('aria-label', 'chapters menu');
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
chaptersbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-chapters-button ' + _texttrackbutton.prototype.buildcssclass.call(this);
};
/**
* create a menu item for each text track
*
* @return {array} array of menu items
* @method createitems
*/
chaptersbutton.prototype.createitems = function createitems() {
var items = [];
var tracks = this.player_.texttracks();
if (!tracks) {
return items;
}
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
if (track['kind'] === this.kind_) {
items.push(new _texttrackmenuitemjs2['default'](this.player_, {
'track': track
}));
}
}
return items;
};
/**
* create menu from chapter buttons
*
* @return {menu} menu of chapter buttons
* @method createmenu
*/
chaptersbutton.prototype.createmenu = function createmenu() {
var _this = this;
var tracks = this.player_.texttracks() || [];
var chapterstrack = undefined;
var items = this.items = [];
for (var i = 0, _length = tracks.length; i < _length; i++) {
var track = tracks[i];
if (track['kind'] === this.kind_) {
chapterstrack = track;
break;
}
}
var menu = this.menu;
if (menu === undefined) {
menu = new _menumenujs2['default'](this.player_);
var title = dom.createel('li', {
classname: 'vjs-menu-title',
innerhtml: _utilstotitlecasejs2['default'](this.kind_),
tabindex: -1
});
menu.children_.unshift(title);
dom.insertelfirst(title, menu.contentel());
}
if (chapterstrack && chapterstrack.cues == null) {
chapterstrack['mode'] = 'hidden';
var remotetexttrackel = this.player_.remotetexttrackels().gettrackelementbytrack_(chapterstrack);
if (remotetexttrackel) {
remotetexttrackel.addeventlistener('load', function (event) {
return _this.update();
});
}
}
if (chapterstrack && chapterstrack.cues && chapterstrack.cues.length > 0) {
var cues = chapterstrack['cues'],
cue = undefined;
for (var i = 0, l = cues.length; i < l; i++) {
cue = cues[i];
var mi = new _chapterstrackmenuitemjs2['default'](this.player_, {
'track': chapterstrack,
'cue': cue
});
items.push(mi);
menu.addchild(mi);
}
this.addchild(menu);
}
if (this.items.length > 0) {
this.show();
}
return menu;
};
return chaptersbutton;
})(_texttrackbuttonjs2['default']);
chaptersbutton.prototype.kind_ = 'chapters';
chaptersbutton.prototype.controltext_ = 'chapters';
_componentjs2['default'].registercomponent('chaptersbutton', chaptersbutton);
exports['default'] = chaptersbutton;
module.exports = exports['default'];
},{"../../component.js":67,"../../menu/menu.js":106,"../../utils/dom.js":132,"../../utils/fn.js":134,"../../utils/to-title-case.js":141,"./chapters-track-menu-item.js":85,"./text-track-button.js":88,"./text-track-menu-item.js":89,"global/window":2}],85:[function(_dereq_,module,exports){
/**
* @file chapters-track-menu-item.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _menumenuitemjs = _dereq_('../../menu/menu-item.js');
var _menumenuitemjs2 = _interoprequiredefault(_menumenuitemjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
/**
* the chapter track menu item
*
* @param {player|object} player
* @param {object=} options
* @extends menuitem
* @class chapterstrackmenuitem
*/
var chapterstrackmenuitem = (function (_menuitem) {
_inherits(chapterstrackmenuitem, _menuitem);
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['label'] = cue.text;
options['selected'] = cue['starttime'] <= currenttime && currenttime < cue['endtime'];
_menuitem.call(this, player, options);
this.track = track;
this.cue = cue;
track.addeventlistener('cuechange', fn.bind(this, this.update));
}
/**
* handle click on menu item
*
* @method handleclick
*/
chapterstrackmenuitem.prototype.handleclick = function handleclick() {
_menuitem.prototype.handleclick.call(this);
this.player_.currenttime(this.cue.starttime);
this.update(this.cue.starttime);
};
/**
* update chapter menu item
*
* @method update
*/
chapterstrackmenuitem.prototype.update = function update() {
var cue = this.cue;
var currenttime = this.player_.currenttime();
// vjs.log(currenttime, cue.starttime);
this.selected(cue['starttime'] <= currenttime && currenttime < cue['endtime']);
};
return chapterstrackmenuitem;
})(_menumenuitemjs2['default']);
_componentjs2['default'].registercomponent('chapterstrackmenuitem', chapterstrackmenuitem);
exports['default'] = chapterstrackmenuitem;
module.exports = exports['default'];
},{"../../component.js":67,"../../menu/menu-item.js":105,"../../utils/fn.js":134}],86:[function(_dereq_,module,exports){
/**
* @file off-text-track-menu-item.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _texttrackmenuitemjs = _dereq_('./text-track-menu-item.js');
var _texttrackmenuitemjs2 = _interoprequiredefault(_texttrackmenuitemjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* a special menu item for turning of a specific type of text track
*
* @param {player|object} player
* @param {object=} options
* @extends texttrackmenuitem
* @class offtexttrackmenuitem
*/
var offtexttrackmenuitem = (function (_texttrackmenuitem) {
_inherits(offtexttrackmenuitem, _texttrackmenuitem);
function offtexttrackmenuitem(player, options) {
_classcallcheck(this, offtexttrackmenuitem);
// create pseudo track info
// requires options['kind']
options['track'] = {
'kind': options['kind'],
'player': player,
'label': options['kind'] + ' off',
'default': false,
'mode': 'disabled'
};
// menuitem is selectable
options['selectable'] = true;
_texttrackmenuitem.call(this, player, options);
this.selected(true);
}
/**
* handle text track change
*
* @param {object} event event object
* @method handletrackschange
*/
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;
})(_texttrackmenuitemjs2['default']);
_componentjs2['default'].registercomponent('offtexttrackmenuitem', offtexttrackmenuitem);
exports['default'] = offtexttrackmenuitem;
module.exports = exports['default'];
},{"../../component.js":67,"./text-track-menu-item.js":89}],87:[function(_dereq_,module,exports){
/**
* @file subtitles-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _texttrackbuttonjs = _dereq_('./text-track-button.js');
var _texttrackbuttonjs2 = _interoprequiredefault(_texttrackbuttonjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* the button component for toggling and selecting subtitles
*
* @param {object} player player object
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends texttrackbutton
* @class subtitlesbutton
*/
var subtitlesbutton = (function (_texttrackbutton) {
_inherits(subtitlesbutton, _texttrackbutton);
function subtitlesbutton(player, options, ready) {
_classcallcheck(this, subtitlesbutton);
_texttrackbutton.call(this, player, options, ready);
this.el_.setattribute('aria-label', 'subtitles menu');
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
subtitlesbutton.prototype.buildcssclass = function buildcssclass() {
return 'vjs-subtitles-button ' + _texttrackbutton.prototype.buildcssclass.call(this);
};
return subtitlesbutton;
})(_texttrackbuttonjs2['default']);
subtitlesbutton.prototype.kind_ = 'subtitles';
subtitlesbutton.prototype.controltext_ = 'subtitles';
_componentjs2['default'].registercomponent('subtitlesbutton', subtitlesbutton);
exports['default'] = subtitlesbutton;
module.exports = exports['default'];
},{"../../component.js":67,"./text-track-button.js":88}],88:[function(_dereq_,module,exports){
/**
* @file text-track-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _menumenubuttonjs = _dereq_('../../menu/menu-button.js');
var _menumenubuttonjs2 = _interoprequiredefault(_menumenubuttonjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _texttrackmenuitemjs = _dereq_('./text-track-menu-item.js');
var _texttrackmenuitemjs2 = _interoprequiredefault(_texttrackmenuitemjs);
var _offtexttrackmenuitemjs = _dereq_('./off-text-track-menu-item.js');
var _offtexttrackmenuitemjs2 = _interoprequiredefault(_offtexttrackmenuitemjs);
/**
* the base class for buttons that toggle specific text track types (e.g. subtitles)
*
* @param {player|object} player
* @param {object=} options
* @extends menubutton
* @class texttrackbutton
*/
var texttrackbutton = (function (_menubutton) {
_inherits(texttrackbutton, _menubutton);
function texttrackbutton(player, options) {
_classcallcheck(this, texttrackbutton);
_menubutton.call(this, player, options);
var tracks = this.player_.texttracks();
if (this.items.length <= 1) {
this.hide();
}
if (!tracks) {
return;
}
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);
});
}
// create a menu item for each text track
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 _offtexttrackmenuitemjs2['default'](this.player_, { 'kind': this.kind_ }));
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 _texttrackmenuitemjs2['default'](this.player_, {
// menuitem is selectable
'selectable': true,
'track': track
}));
}
}
return items;
};
return texttrackbutton;
})(_menumenubuttonjs2['default']);
_componentjs2['default'].registercomponent('texttrackbutton', texttrackbutton);
exports['default'] = texttrackbutton;
module.exports = exports['default'];
},{"../../component.js":67,"../../menu/menu-button.js":104,"../../utils/fn.js":134,"./off-text-track-menu-item.js":86,"./text-track-menu-item.js":89}],89:[function(_dereq_,module,exports){
/**
* @file text-track-menu-item.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _menumenuitemjs = _dereq_('../../menu/menu-item.js');
var _menumenuitemjs2 = _interoprequiredefault(_menumenuitemjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
/**
* the specific menu item type for selecting a language within a text track kind
*
* @param {player|object} player
* @param {object=} options
* @extends menuitem
* @class texttrackmenuitem
*/
var texttrackmenuitem = (function (_menuitem) {
_inherits(texttrackmenuitem, _menuitem);
function texttrackmenuitem(player, options) {
var _this = this;
_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';
_menuitem.call(this, player, options);
this.track = track;
if (tracks) {
(function () {
var changehandler = fn.bind(_this, _this.handletrackschange);
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) {
(function () {
var event = undefined;
_this.on(['tap', 'click'], function () {
if (typeof _globalwindow2['default'].event !== 'object') {
// android 2.3 throws an illegal constructor error for window.event
try {
event = new _globalwindow2['default'].event('change');
} catch (err) {}
}
if (!event) {
event = _globaldocument2['default'].createevent('event');
event.initevent('change', true, true);
}
tracks.dispatchevent(event);
});
})();
}
}
/**
* handle click on text track
*
* @method handleclick
*/
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 change
*
* @method handletrackschange
*/
texttrackmenuitem.prototype.handletrackschange = function handletrackschange(event) {
this.selected(this.track['mode'] === 'showing');
};
return texttrackmenuitem;
})(_menumenuitemjs2['default']);
_componentjs2['default'].registercomponent('texttrackmenuitem', texttrackmenuitem);
exports['default'] = texttrackmenuitem;
module.exports = exports['default'];
},{"../../component.js":67,"../../menu/menu-item.js":105,"../../utils/fn.js":134,"global/document":1,"global/window":2}],90:[function(_dereq_,module,exports){
/**
* @file current-time-display.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsformattimejs = _dereq_('../../utils/format-time.js');
var _utilsformattimejs2 = _interoprequiredefault(_utilsformattimejs);
/**
* displays the current time
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class currenttimedisplay
*/
var currenttimedisplay = (function (_component) {
_inherits(currenttimedisplay, _component);
function currenttimedisplay(player, options) {
_classcallcheck(this, currenttimedisplay);
_component.call(this, player, options);
this.on(player, 'timeupdate', this.updatecontent);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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
*
* @method updatecontent
*/
currenttimedisplay.prototype.updatecontent = function updatecontent() {
// 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 = _utilsformattimejs2['default'](time, this.player_.duration());
if (formattedtime !== this.formattedtime_) {
this.formattedtime_ = formattedtime;
this.contentel_.innerhtml = '' + localizedtext + ' ' + formattedtime;
}
};
return currenttimedisplay;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('currenttimedisplay', currenttimedisplay);
exports['default'] = currenttimedisplay;
module.exports = exports['default'];
},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/format-time.js":135}],91:[function(_dereq_,module,exports){
/**
* @file duration-display.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsformattimejs = _dereq_('../../utils/format-time.js');
var _utilsformattimejs2 = _interoprequiredefault(_utilsformattimejs);
/**
* displays the duration
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class durationdisplay
*/
var durationdisplay = (function (_component) {
_inherits(durationdisplay, _component);
function durationdisplay(player, options) {
_classcallcheck(this, durationdisplay);
_component.call(this, player, options);
// this might need to be changed to 'durationchange' instead of 'timeupdate' eventually,
// however the durationchange event fires before this.player_.duration() is set,
// so the value cannot be written out using this method.
// once the order of durationchange and this.player_.duration() being set is figured out,
// this can be updated.
this.on(player, 'timeupdate', this.updatecontent);
this.on(player, 'loadedmetadata', this.updatecontent);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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
*
* @method updatecontent
*/
durationdisplay.prototype.updatecontent = function updatecontent() {
var duration = this.player_.duration();
if (duration && this.duration_ !== duration) {
this.duration_ = duration;
var localizedtext = this.localize('duration time');
var formattedtime = _utilsformattimejs2['default'](duration);
this.contentel_.innerhtml = '' + localizedtext + ' ' + formattedtime; // label the duration time for screen reader users
}
};
return durationdisplay;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('durationdisplay', durationdisplay);
exports['default'] = durationdisplay;
module.exports = exports['default'];
},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/format-time.js":135}],92:[function(_dereq_,module,exports){
/**
* @file remaining-time-display.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsformattimejs = _dereq_('../../utils/format-time.js');
var _utilsformattimejs2 = _interoprequiredefault(_utilsformattimejs);
/**
* displays the time left in the video
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class remainingtimedisplay
*/
var remainingtimedisplay = (function (_component) {
_inherits(remainingtimedisplay, _component);
function remainingtimedisplay(player, options) {
_classcallcheck(this, remainingtimedisplay);
_component.call(this, player, options);
this.on(player, 'timeupdate', this.updatecontent);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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
*
* @method updatecontent
*/
remainingtimedisplay.prototype.updatecontent = function updatecontent() {
if (this.player_.duration()) {
var localizedtext = this.localize('remaining time');
var formattedtime = _utilsformattimejs2['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;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('remainingtimedisplay', remainingtimedisplay);
exports['default'] = remainingtimedisplay;
module.exports = exports['default'];
},{"../../component.js":67,"../../utils/dom.js":132,"../../utils/format-time.js":135}],93:[function(_dereq_,module,exports){
/**
* @file time-divider.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* the separator between the current time and duration.
* can be hidden if it's not needed in the design.
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class timedivider
*/
var timedivider = (function (_component) {
_inherits(timedivider, _component);
function timedivider() {
_classcallcheck(this, timedivider);
_component.apply(this, arguments);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
timedivider.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-time-control vjs-time-divider',
innerhtml: '
/
'
});
};
return timedivider;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('timedivider', timedivider);
exports['default'] = timedivider;
module.exports = exports['default'];
},{"../../component.js":67}],94:[function(_dereq_,module,exports){
/**
* @file volume-bar.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _slidersliderjs = _dereq_('../../slider/slider.js');
var _slidersliderjs2 = _interoprequiredefault(_slidersliderjs);
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsfnjs = _dereq_('../../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
// required children
var _volumeleveljs = _dereq_('./volume-level.js');
var _volumeleveljs2 = _interoprequiredefault(_volumeleveljs);
/**
* the bar that contains the volume level and can be clicked on to adjust the level
*
* @param {player|object} player
* @param {object=} options
* @extends slider
* @class volumebar
*/
var volumebar = (function (_slider) {
_inherits(volumebar, _slider);
function volumebar(player, options) {
_classcallcheck(this, volumebar);
_slider.call(this, player, options);
this.on(player, 'volumechange', this.updateariaattributes);
player.ready(fn.bind(this, this.updateariaattributes));
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
volumebar.prototype.createel = function createel() {
return _slider.prototype.createel.call(this, 'div', {
classname: 'vjs-volume-bar vjs-slider-bar'
}, {
'aria-label': 'volume level'
});
};
/**
* handle mouse move on volume bar
*
* @method handlemousemove
*/
volumebar.prototype.handlemousemove = function handlemousemove(event) {
this.checkmuted();
this.player_.volume(this.calculatedistance(event));
};
volumebar.prototype.checkmuted = function checkmuted() {
if (this.player_.muted()) {
this.player_.muted(false);
}
};
/**
* get percent of volume level
*
* @retun {number} volume level percent
* @method getpercent
*/
volumebar.prototype.getpercent = function getpercent() {
if (this.player_.muted()) {
return 0;
} else {
return this.player_.volume();
}
};
/**
* increase volume level for keyboard users
*
* @method stepforward
*/
volumebar.prototype.stepforward = function stepforward() {
this.checkmuted();
this.player_.volume(this.player_.volume() + 0.1);
};
/**
* decrease volume level for keyboard users
*
* @method stepback
*/
volumebar.prototype.stepback = function stepback() {
this.checkmuted();
this.player_.volume(this.player_.volume() - 0.1);
};
/**
* update aria accessibility attributes
*
* @method updateariaattributes
*/
volumebar.prototype.updateariaattributes = function updateariaattributes() {
// 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;
})(_slidersliderjs2['default']);
volumebar.prototype.options_ = {
children: ['volumelevel'],
'barname': 'volumelevel'
};
volumebar.prototype.playerevent = 'volumechange';
_componentjs2['default'].registercomponent('volumebar', volumebar);
exports['default'] = volumebar;
module.exports = exports['default'];
},{"../../component.js":67,"../../slider/slider.js":114,"../../utils/fn.js":134,"./volume-level.js":96}],95:[function(_dereq_,module,exports){
/**
* @file volume-control.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
// required children
var _volumebarjs = _dereq_('./volume-bar.js');
var _volumebarjs2 = _interoprequiredefault(_volumebarjs);
/**
* the component for controlling the volume level
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class volumecontrol
*/
var volumecontrol = (function (_component) {
_inherits(volumecontrol, _component);
function volumecontrol(player, options) {
_classcallcheck(this, volumecontrol);
_component.call(this, player, options);
// hide volume controls when they're not supported by the current tech
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');
}
});
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
volumecontrol.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-volume-control vjs-control'
});
};
return volumecontrol;
})(_componentjs2['default']);
volumecontrol.prototype.options_ = {
children: ['volumebar']
};
_componentjs2['default'].registercomponent('volumecontrol', volumecontrol);
exports['default'] = volumecontrol;
module.exports = exports['default'];
},{"../../component.js":67,"./volume-bar.js":94}],96:[function(_dereq_,module,exports){
/**
* @file volume-level.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
/**
* shows volume level
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class volumelevel
*/
var volumelevel = (function (_component) {
_inherits(volumelevel, _component);
function volumelevel() {
_classcallcheck(this, volumelevel);
_component.apply(this, arguments);
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
volumelevel.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-volume-level',
innerhtml: ''
});
};
return volumelevel;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('volumelevel', volumelevel);
exports['default'] = volumelevel;
module.exports = exports['default'];
},{"../../component.js":67}],97:[function(_dereq_,module,exports){
/**
* @file volume-menu-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _popuppopupjs = _dereq_('../popup/popup.js');
var _popuppopupjs2 = _interoprequiredefault(_popuppopupjs);
var _popuppopupbuttonjs = _dereq_('../popup/popup-button.js');
var _popuppopupbuttonjs2 = _interoprequiredefault(_popuppopupbuttonjs);
var _mutetogglejs = _dereq_('./mute-toggle.js');
var _mutetogglejs2 = _interoprequiredefault(_mutetogglejs);
var _volumecontrolvolumebarjs = _dereq_('./volume-control/volume-bar.js');
var _volumecontrolvolumebarjs2 = _interoprequiredefault(_volumecontrolvolumebarjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
/**
* button for volume popup
*
* @param {player|object} player
* @param {object=} options
* @extends popupbutton
* @class volumemenubutton
*/
var volumemenubutton = (function (_popupbutton) {
_inherits(volumemenubutton, _popupbutton);
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;
_popupbutton.call(this, player, options);
// same listeners as mutetoggle
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');
});
}
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
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;
};
/**
* allow sub components to stack css class names
*
* @return {popup} the volume popup button
* @method createpopup
*/
volumemenubutton.prototype.createpopup = function createpopup() {
var popup = new _popuppopupjs2['default'](this.player_, {
contenteltype: 'div'
});
var vb = new _volumecontrolvolumebarjs2['default'](this.player_, this.options_.volumebar);
popup.addchild(vb);
this.menucontent = popup;
this.volumebar = vb;
this.attachvolumebarevents();
return popup;
};
/**
* handle click on volume popup and calls super
*
* @method handleclick
*/
volumemenubutton.prototype.handleclick = function handleclick() {
_mutetogglejs2['default'].prototype.handleclick.call(this);
_popupbutton.prototype.handleclick.call(this);
};
volumemenubutton.prototype.attachvolumebarevents = function attachvolumebarevents() {
this.menucontent.on(['mousedown', 'touchdown'], fn.bind(this, this.handlemousedown));
};
volumemenubutton.prototype.handlemousedown = function handlemousedown(event) {
this.on(['mousemove', 'touchmove'], fn.bind(this.volumebar, this.volumebar.handlemousemove));
this.on(_globaldocument2['default'], ['mouseup', 'touchend'], this.handlemouseup);
};
volumemenubutton.prototype.handlemouseup = function handlemouseup(event) {
this.off(['mousemove', 'touchmove'], fn.bind(this.volumebar, this.volumebar.handlemousemove));
};
return volumemenubutton;
})(_popuppopupbuttonjs2['default']);
volumemenubutton.prototype.volumeupdate = _mutetogglejs2['default'].prototype.update;
volumemenubutton.prototype.controltext_ = 'mute';
_componentjs2['default'].registercomponent('volumemenubutton', volumemenubutton);
exports['default'] = volumemenubutton;
module.exports = exports['default'];
},{"../component.js":67,"../popup/popup-button.js":110,"../popup/popup.js":111,"../utils/fn.js":134,"./mute-toggle.js":71,"./volume-control/volume-bar.js":94,"global/document":1}],98:[function(_dereq_,module,exports){
/**
* @file error-display.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _component = _dereq_('./component');
var _component2 = _interoprequiredefault(_component);
var _modaldialog = _dereq_('./modal-dialog');
var _modaldialog2 = _interoprequiredefault(_modaldialog);
var _utilsdom = _dereq_('./utils/dom');
var dom = _interoprequirewildcard(_utilsdom);
var _utilsmergeoptions = _dereq_('./utils/merge-options');
var _utilsmergeoptions2 = _interoprequiredefault(_utilsmergeoptions);
/**
* display that an error has occurred making the video unplayable.
*
* @extends modaldialog
* @class errordisplay
*/
var errordisplay = (function (_modaldialog) {
_inherits(errordisplay, _modaldialog);
/**
* constructor for error display modal.
*
* @param {player} player
* @param {object} [options]
*/
function errordisplay(player, options) {
_classcallcheck(this, errordisplay);
_modaldialog.call(this, player, options);
this.on(player, 'error', this.open);
}
/**
* include the old class for backward-compatibility.
*
* this can be removed in 6.0.
*
* @method buildcssclass
* @deprecated
* @return {string}
*/
errordisplay.prototype.buildcssclass = function buildcssclass() {
return 'vjs-error-display ' + _modaldialog.prototype.buildcssclass.call(this);
};
/**
* generates the modal content based on the player error.
*
* @return {string|null}
*/
errordisplay.prototype.content = function content() {
var error = this.player().error();
return error ? this.localize(error.message) : '';
};
return errordisplay;
})(_modaldialog2['default']);
errordisplay.prototype.options_ = _utilsmergeoptions2['default'](_modaldialog2['default'].prototype.options_, {
fillalways: true,
temporary: false,
uncloseable: true
});
_component2['default'].registercomponent('errordisplay', errordisplay);
exports['default'] = errordisplay;
module.exports = exports['default'];
},{"./component":67,"./modal-dialog":107,"./utils/dom":132,"./utils/merge-options":138}],99:[function(_dereq_,module,exports){
/**
* @file event-target.js
*/
'use strict';
exports.__esmodule = true;
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; } }
var _utilseventsjs = _dereq_('./utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var eventtarget = function eventtarget() {};
eventtarget.prototype.allowedevents_ = {};
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.prototype;
events.on(this, type, fn);
this.addeventlistener = ael;
};
eventtarget.prototype.addeventlistener = eventtarget.prototype.on;
eventtarget.prototype.off = function (type, fn) {
events.off(this, type, fn);
};
eventtarget.prototype.removeeventlistener = eventtarget.prototype.off;
eventtarget.prototype.one = function (type, fn) {
events.one(this, type, fn);
};
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);
};
// the standard dom eventtarget.dispatchevent() is aliased to trigger()
eventtarget.prototype.dispatchevent = eventtarget.prototype.trigger;
exports['default'] = eventtarget;
module.exports = exports['default'];
},{"./utils/events.js":133}],100:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _utilslog = _dereq_('./utils/log');
var _utilslog2 = _interoprequiredefault(_utilslog);
/*
* @file extend.js
*
* a combination of node inherits and babel's inherits (after transpile).
* both work the same but node adds `super_` to the subclass
* and bable adds the superclass as __proto__. both seem useful.
*/
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);
}
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
* ```js
* var button = videojs.getcomponent('button');
* ```
* ```js
* var mybutton = videojs.extend(button, {
* constructor: function(player, options) {
* button.call(this, player, options);
* },
* onclick: function() {
* // dosomething
* }
* });
* ```
*/
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 (typeof subclassmethods === 'object') {
if (typeof subclassmethods.init === 'function') {
_utilslog2['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;
module.exports = exports['default'];
},{"./utils/log":137}],101:[function(_dereq_,module,exports){
/**
* @file fullscreen-api.js
*/
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
/*
* store the browser-specific methods for the fullscreen api
* @type {object|undefined}
* @private
*/
var fullscreenapi = {};
// browser api methods
// map approach from screenful.js - https://github.com/sindresorhus/screenfull.js
var apimap = [
// spec: https://dvcs.w3.org/hg/fullscreen/raw-file/tip/overview.html
['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 = undefined;
// determine the supported set of functions
for (var i = 0; i < apimap.length; i++) {
// check for exitfullscreen function
if (apimap[i][1] in _globaldocument2['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;
module.exports = exports['default'];
},{"global/document":1}],102:[function(_dereq_,module,exports){
/**
* @file loading-spinner.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _component = _dereq_('./component');
var _component2 = _interoprequiredefault(_component);
/* loading spinner
================================================================================ */
/**
* loading spinner for waiting events
*
* @extends component
* @class loadingspinner
*/
var loadingspinner = (function (_component) {
_inherits(loadingspinner, _component);
function loadingspinner() {
_classcallcheck(this, loadingspinner);
_component.apply(this, arguments);
}
/**
* create the component's dom element
*
* @method createel
*/
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;
module.exports = exports['default'];
},{"./component":67}],103:[function(_dereq_,module,exports){
/**
* @file media-error.js
*/
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
/*
* custom mediaerror to mimic the html5 mediaerror
*
* @param {number} code the media error code
*/
var mediaerror = function mediaerror(code) {
if (typeof code === 'number') {
this.code = code;
} else if (typeof code === 'string') {
// default code is zero, so this is a custom error
this.message = code;
} else if (typeof code === 'object') {
// object
_objectassign2['default'](this, code);
}
if (!this.message) {
this.message = mediaerror.defaultmessages[this.code] || '';
}
};
/*
* the error code that refers two one of the defined
* mediaerror types
*
* @type {number}
*/
mediaerror.prototype.code = 0;
/*
* an optional message to be shown with the error.
* message is not part of the html5 video spec
* but allows for more informative custom errors.
*
* @type {string}
*/
mediaerror.prototype.message = '';
/*
* an optional status code that can be set by plugins
* to allow even more detail about the error.
* for example the hls plugin might provide the specific
* http status code that was returned when the error
* occurred, then allowing a custom error overlay
* to display more information.
*
* @type {array}
*/
mediaerror.prototype.status = null;
mediaerror.errortypes = ['media_err_custom', // = 0
'media_err_aborted', // = 1
'media_err_network', // = 2
'media_err_decode', // = 3
'media_err_src_not_supported', // = 4
'media_err_encrypted' // = 5
];
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;
}
exports['default'] = mediaerror;
module.exports = exports['default'];
},{"object.assign":45}],104:[function(_dereq_,module,exports){
/**
* @file menu-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _clickablecomponentjs = _dereq_('../clickable-component.js');
var _clickablecomponentjs2 = _interoprequiredefault(_clickablecomponentjs);
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _menujs = _dereq_('./menu.js');
var _menujs2 = _interoprequiredefault(_menujs);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilstotitlecasejs = _dereq_('../utils/to-title-case.js');
var _utilstotitlecasejs2 = _interoprequiredefault(_utilstotitlecasejs);
/**
* a button class with a popup menu
*
* @param {player|object} player
* @param {object=} options
* @extends button
* @class menubutton
*/
var menubutton = (function (_clickablecomponent) {
_inherits(menubutton, _clickablecomponent);
function menubutton(player) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
_classcallcheck(this, menubutton);
_clickablecomponent.call(this, player, options);
this.update();
this.el_.setattribute('aria-haspopup', true);
this.el_.setattribute('role', 'menuitem');
this.on('keydown', this.handlesubmenukeypress);
}
/**
* update menu
*
* @method update
*/
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 === 0) {
this.hide();
} else if (this.items && this.items.length > 1) {
this.show();
}
};
/**
* create menu
*
* @return {menu} the constructed menu
* @method createmenu
*/
menubutton.prototype.createmenu = function createmenu() {
var menu = new _menujs2['default'](this.player_);
// add a title list item to the top
if (this.options_.title) {
var title = dom.createel('li', {
classname: 'vjs-menu-title',
innerhtml: _utilstotitlecasejs2['default'](this.options_.title),
tabindex: -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.
*
* @method createitems
*/
menubutton.prototype.createitems = function createitems() {};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
menubutton.prototype.createel = function createel() {
return _clickablecomponent.prototype.createel.call(this, 'div', {
classname: this.buildcssclass()
});
};
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
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);
};
/**
* when you click the button it adds focus, which
* will show the menu indefinitely.
* so we'll remove focus when the mouse leaves the button.
* focus is needed for tab navigation.
* allow sub components to stack css class names
*
* @method handleclick
*/
menubutton.prototype.handleclick = function handleclick() {
this.one('mouseout', fn.bind(this, function () {
this.menu.unlockshowing();
this.el_.blur();
}));
if (this.buttonpressed_) {
this.unpressbutton();
} else {
this.pressbutton();
}
};
/**
* handle key press on menu
*
* @param {object} event key press event
* @method handlekeypress
*/
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 key press on submenu
*
* @param {object} event key press event
* @method handlesubmenukeypress
*/
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();
}
}
};
/**
* makes changes based on button pressed
*
* @method pressbutton
*/
menubutton.prototype.pressbutton = function pressbutton() {
this.buttonpressed_ = true;
this.menu.lockshowing();
this.el_.setattribute('aria-expanded', true);
this.menu.focus(); // set the focus into the submenu
};
/**
* makes changes based on button unpressed
*
* @method unpressbutton
*/
menubutton.prototype.unpressbutton = function unpressbutton() {
this.buttonpressed_ = false;
this.menu.unlockshowing();
this.el_.setattribute('aria-expanded', false);
this.el_.focus(); // set focus back to this menu button
};
return menubutton;
})(_clickablecomponentjs2['default']);
_componentjs2['default'].registercomponent('menubutton', menubutton);
exports['default'] = menubutton;
module.exports = exports['default'];
},{"../clickable-component.js":65,"../component.js":67,"../utils/dom.js":132,"../utils/fn.js":134,"../utils/to-title-case.js":141,"./menu.js":106}],105:[function(_dereq_,module,exports){
/**
* @file menu-item.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _clickablecomponentjs = _dereq_('../clickable-component.js');
var _clickablecomponentjs2 = _interoprequiredefault(_clickablecomponentjs);
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
/**
* the component for a menu item. `
`
*
* @param {player|object} player
* @param {object=} options
* @extends button
* @class menuitem
*/
var menuitem = (function (_clickablecomponent) {
_inherits(menuitem, _clickablecomponent);
function menuitem(player, options) {
_classcallcheck(this, menuitem);
_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');
}
}
/**
* create the component's dom element
*
* @param {string=} type desc
* @param {object=} props desc
* @return {element}
* @method createel
*/
menuitem.prototype.createel = function createel(type, props, attrs) {
return _clickablecomponent.prototype.createel.call(this, 'li', _objectassign2['default']({
classname: 'vjs-menu-item',
innerhtml: this.localize(this.options_['label']),
tabindex: -1
}, props), attrs);
};
/**
* handle a click on the menu item, and set it to selected
*
* @method handleclick
*/
menuitem.prototype.handleclick = function handleclick() {
this.selected(true);
};
/**
* set this menu item as selected or not
*
* @param {boolean} selected
* @method selected
*/
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;
})(_clickablecomponentjs2['default']);
_componentjs2['default'].registercomponent('menuitem', menuitem);
exports['default'] = menuitem;
module.exports = exports['default'];
},{"../clickable-component.js":65,"../component.js":67,"object.assign":45}],106:[function(_dereq_,module,exports){
/**
* @file menu.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilseventsjs = _dereq_('../utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
/**
* the menu component is used to build pop up menus, including subtitle and
* captions selection menus.
*
* @extends component
* @class menu
*/
var menu = (function (_component) {
_inherits(menu, _component);
function menu(player, options) {
_classcallcheck(this, menu);
_component.call(this, player, options);
this.focusedchild_ = -1;
this.on('keydown', this.handlekeypress);
}
/**
* add a menu item to the menu
*
* @param {object|string} component component or component type to add
* @method additem
*/
menu.prototype.additem = function additem(component) {
this.addchild(component);
component.on('click', fn.bind(this, function () {
this.unlockshowing();
//todo: need to set keyboard focus back to the menubutton
}));
};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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 key press for menu
*
* @param {object} event event object
* @method handlekeypress
*/
menu.prototype.handlekeypress = function handlekeypress(event) {
if (event.which === 37 || event.which === 40) {
// left and down arrows
event.preventdefault();
this.stepforward();
} else if (event.which === 38 || event.which === 39) {
// up and right arrows
event.preventdefault();
this.stepback();
}
};
/**
* move to next (lower) menu item for keyboard users
*
* @method stepforward
*/
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
*
* @method stepback
*/
menu.prototype.stepback = function stepback() {
var stepchild = 0;
if (this.focusedchild_ !== undefined) {
stepchild = this.focusedchild_ - 1;
}
this.focus(stepchild);
};
/**
* set focus on a menu item in the menu
*
* @param {object|string} item index of child item set focus on
* @method focus
*/
menu.prototype.focus = function focus() {
var item = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[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;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('menu', menu);
exports['default'] = menu;
module.exports = exports['default'];
},{"../component.js":67,"../utils/dom.js":132,"../utils/events.js":133,"../utils/fn.js":134}],107:[function(_dereq_,module,exports){
/**
* @file modal-dialog.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _utilsdom = _dereq_('./utils/dom');
var dom = _interoprequirewildcard(_utilsdom);
var _utilsfn = _dereq_('./utils/fn');
var fn = _interoprequirewildcard(_utilsfn);
var _utilslog = _dereq_('./utils/log');
var _utilslog2 = _interoprequiredefault(_utilslog);
var _component = _dereq_('./component');
var _component2 = _interoprequiredefault(_component);
var _closebutton = _dereq_('./close-button');
var _closebutton2 = _interoprequiredefault(_closebutton);
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
* @class modaldialog
*/
var modaldialog = (function (_component) {
_inherits(modaldialog, _component);
/**
* constructor for modals.
*
* @param {player} player
* @param {object} [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);
_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_);
}
/*
* modal dialog default options.
*
* @type {object}
* @private
*/
/**
* create the modal's dom element
*
* @method createel
* @return {element}
*/
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'
});
};
/**
* build the modal's css class.
*
* @method buildcssclass
* @return {string}
*/
modaldialog.prototype.buildcssclass = function buildcssclass() {
return modal_class_name + ' vjs-hidden ' + _component.prototype.buildcssclass.call(this);
};
/**
* handles key presses on the document, looking for esc, which closes
* the modal.
*
* @method handlekeypress
* @param {event} e
*/
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}
*/
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}
*/
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.
*
* @method open
* @return {modaldialog}
*/
modaldialog.prototype.open = function open() {
if (!this.opened_) {
var player = this.player();
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.wasplaying_) {
player.pause();
}
if (this.closeable()) {
this.on(_globaldocument2['default'], 'keydown', fn.bind(this, this.handlekeypress));
}
player.controls(false);
this.show();
this.el().setattribute('aria-hidden', 'false');
this.trigger('modalopen');
this.hasbeenopened_ = true;
}
return this;
};
/**
* whether or not the modal is opened currently.
*
* @method opened
* @param {boolean} [value]
* if given, it will open (`true`) or close (`false`) the modal.
*
* @return {boolean}
*/
modaldialog.prototype.opened = function opened(value) {
if (typeof value === 'boolean') {
this[value ? 'open' : 'close']();
}
return this.opened_;
};
/**
* closes the modal.
*
* @method close
* @return {modaldialog}
*/
modaldialog.prototype.close = function close() {
if (this.opened_) {
var player = this.player();
this.trigger('beforemodalclose');
this.opened_ = false;
if (this.wasplaying_) {
player.play();
}
if (this.closeable()) {
this.off(_globaldocument2['default'], 'keydown', fn.bind(this, this.handlekeypress));
}
player.controls(true);
this.hide();
this.el().setattribute('aria-hidden', 'true');
this.trigger('modalclose');
if (this.options_.temporary) {
this.dispose();
}
}
return this;
};
/**
* whether or not the modal is closeable via the ui.
*
* @method closeable
* @param {boolean} [value]
* if given as a boolean, it will set the `closeable` option.
*
* @return {boolean}
*/
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');
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.
*
* @method fill
* @return {modaldialog}
*/
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.
*
* @method fillwith
* @param {mixed} [content]
* the same rules apply to this as apply to the `content` option.
*
* @return {modaldialog}
*/
modaldialog.prototype.fillwith = function fillwith(content) {
var contentel = this.contentel();
var parentel = contentel.parentnode;
var nextsiblingel = contentel.nextsibling;
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);
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 automatically anytime the modal is filled.
*
* @method empty
* @return {modaldialog}
*/
modaldialog.prototype.empty = function empty() {
this.trigger('beforemodalempty');
dom.emptyel(this.contentel());
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.
*
* @method content
* @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}
*/
modaldialog.prototype.content = function content(value) {
if (typeof value !== 'undefined') {
this.content_ = value;
}
return this.content_;
};
return modaldialog;
})(_component2['default']);
modaldialog.prototype.options_ = {
temporary: true
};
_component2['default'].registercomponent('modaldialog', modaldialog);
exports['default'] = modaldialog;
module.exports = exports['default'];
},{"./close-button":66,"./component":67,"./utils/dom":132,"./utils/fn":134,"./utils/log":137,"global/document":1}],108:[function(_dereq_,module,exports){
/**
* @file player.js
*/
// subclasses component
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('./component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _utilseventsjs = _dereq_('./utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var _utilsdomjs = _dereq_('./utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('./utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsguidjs = _dereq_('./utils/guid.js');
var guid = _interoprequirewildcard(_utilsguidjs);
var _utilsbrowserjs = _dereq_('./utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _utilslogjs = _dereq_('./utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _utilstotitlecasejs = _dereq_('./utils/to-title-case.js');
var _utilstotitlecasejs2 = _interoprequiredefault(_utilstotitlecasejs);
var _utilstimerangesjs = _dereq_('./utils/time-ranges.js');
var _utilsbufferjs = _dereq_('./utils/buffer.js');
var _utilsstylesheetjs = _dereq_('./utils/stylesheet.js');
var stylesheet = _interoprequirewildcard(_utilsstylesheetjs);
var _fullscreenapijs = _dereq_('./fullscreen-api.js');
var _fullscreenapijs2 = _interoprequiredefault(_fullscreenapijs);
var _mediaerrorjs = _dereq_('./media-error.js');
var _mediaerrorjs2 = _interoprequiredefault(_mediaerrorjs);
var _safejsonparsetuple = _dereq_('safe-json-parse/tuple');
var _safejsonparsetuple2 = _interoprequiredefault(_safejsonparsetuple);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
var _utilsmergeoptionsjs = _dereq_('./utils/merge-options.js');
var _utilsmergeoptionsjs2 = _interoprequiredefault(_utilsmergeoptionsjs);
var _trackstexttracklistconverterjs = _dereq_('./tracks/text-track-list-converter.js');
var _trackstexttracklistconverterjs2 = _interoprequiredefault(_trackstexttracklistconverterjs);
// include required child components (importing also registers them)
var _techloaderjs = _dereq_('./tech/loader.js');
var _techloaderjs2 = _interoprequiredefault(_techloaderjs);
var _posterimagejs = _dereq_('./poster-image.js');
var _posterimagejs2 = _interoprequiredefault(_posterimagejs);
var _trackstexttrackdisplayjs = _dereq_('./tracks/text-track-display.js');
var _trackstexttrackdisplayjs2 = _interoprequiredefault(_trackstexttrackdisplayjs);
var _loadingspinnerjs = _dereq_('./loading-spinner.js');
var _loadingspinnerjs2 = _interoprequiredefault(_loadingspinnerjs);
var _bigplaybuttonjs = _dereq_('./big-play-button.js');
var _bigplaybuttonjs2 = _interoprequiredefault(_bigplaybuttonjs);
var _controlbarcontrolbarjs = _dereq_('./control-bar/control-bar.js');
var _controlbarcontrolbarjs2 = _interoprequiredefault(_controlbarcontrolbarjs);
var _errordisplayjs = _dereq_('./error-display.js');
var _errordisplayjs2 = _interoprequiredefault(_errordisplayjs);
var _trackstexttracksettingsjs = _dereq_('./tracks/text-track-settings.js');
var _trackstexttracksettingsjs2 = _interoprequiredefault(_trackstexttracksettingsjs);
var _modaldialog = _dereq_('./modal-dialog');
var _modaldialog2 = _interoprequiredefault(_modaldialog);
// require html5 tech, at least for disposing the original video tag
var _techtechjs = _dereq_('./tech/tech.js');
var _techtechjs2 = _interoprequiredefault(_techtechjs);
var _techhtml5js = _dereq_('./tech/html5.js');
var _techhtml5js2 = _interoprequiredefault(_techhtml5js);
/**
* an instance of the `player` class is created when any of the video.js setup methods are used to initialize a video.
* ```js
* var myplayer = videojs('example_video_1');
* ```
* in the following example, the `data-setup` attribute tells the video.js library to create a player instance when the library is ready.
* ```html
*
* ```
* after an instance has been created it can be accessed globally using `video('example_video_1')`.
*
* @param {element} tag the original video tag used for configuring options
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends component
* @class player
*/
var player = (function (_component) {
_inherits(player, _component);
/**
* player's constructor function
*
* @constructs
* @method init
* @param {element} tag the original video tag used for configuring options
* @param {object=} options player options
* @param {function=} ready ready callback function
*/
function player(tag, options, ready) {
var _this = this;
_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 = _objectassign2['default'](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;
// run base component initializing with new options
_component.call(this, null, options, ready);
// if the global option object was accidentally blown away by
// someone, bail early with an informative error
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?');
}
this.tag = tag; // store the original tag used to set options
// 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) {
(function () {
// 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 = _utilsmergeoptionsjs2['default'](this.options_);
// load plugins
if (options.plugins) {
(function () {
var plugins = options.plugins;
object.getownpropertynames(plugins).foreach(function (name) {
if (typeof this[name] === 'function') {
this[name](plugins[name]);
} else {
_utilslogjs2['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');
}
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_);
}
/*
* global player list
*
* @type {object}
*/
/**
* destroys the video player and does any necessary cleanup
* ```js
* myplayer.dispose();
* ```
* this is especially helpful if you are dynamically adding and removing videos
* to/from the dom.
*
* @method dispose
*/
player.prototype.dispose = function dispose() {
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 component's dom element
*
* @return {element}
* @method createel
*/
player.prototype.createel = function createel() {
var el = this.el_ = _component.prototype.createel.call(this, 'div');
var tag = this.tag;
// 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
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);
// 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) {
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
dom.insertelfirst(tag, el); // breaks iphone, fixed in html5 setup.
this.children_.unshift(tag);
this.el_ = el;
return el;
};
/**
* get/set player width
*
* @param {number=} value value for width
* @return {number} width when getting
* @method width
*/
player.prototype.width = function width(value) {
return this.dimension('width', value);
};
/**
* get/set player height
*
* @param {number=} value value for height
* @return {number} height when getting
* @method height
*/
player.prototype.height = function height(value) {
return this.dimension('height', value);
};
/**
* get/set dimension for player
*
* @param {string} dimension either width or height
* @param {number=} value value for dimension
* @return {component}
* @method dimension
*/
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)) {
_utilslogjs2['default'].error('improper value "' + value + '" supplied for for ' + _dimension);
return this;
}
this[privdimension] = parsedval;
}
this.updatestyleel_();
return this;
};
/**
* add/remove the vjs-fluid class
*
* @param {boolean} bool value of true adds the class, value of false removes the class
* @method fluid
*/
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');
}
};
/**
* get/set the aspect ratio
*
* @param {string=} ratio aspect ratio for player
* @return aspectratio
* @method aspectratio
*/
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)
*
* @method updatestyleel_
*/
player.prototype.updatestyleel_ = function updatestyleel_() {
var width = undefined;
var height = undefined;
var aspectratio = undefined;
var idclass = undefined;
// 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()) {
// 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 the media playback technology (tech)
* load/create an instance of playback technology including element and api methods
* and append playback element in player div.
*
* @param {string} techname name of the playback technology
* @param {string} source video source
* @method loadtech_
* @private
*/
player.prototype.loadtech_ = function loadtech_(techname, source) {
// 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) {
_techtechjs2['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 = _objectassign2['default']({
'nativecontrolsfortouch': this.options_.nativecontrolsfortouch,
'source': source,
'playerid': this.id(),
'techid': this.id() + '_' + techname + '_api',
'texttracks': this.texttracks_,
'autoplay': this.options_.autoplay,
'preload': this.options_.preload,
'loop': this.options_.loop,
'muted': this.options_.muted,
'poster': this.poster(),
'language': this.language(),
'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_.src = source.src;
}
// initialize tech instance
var techcomponent = _techtechjs2['default'].gettech(techname);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!techcomponent) {
techcomponent = _componentjs2['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);
_trackstexttracklistconverterjs2['default'].jsontotexttracks(this.texttracksjson_ || [], this.tech_);
// listen to all html5-defined events and trigger them on the player
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_, 'progress', this.handletechprogress_);
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_, 'suspend', this.handletechsuspend_);
this.on(this.tech_, 'abort', this.handletechabort_);
this.on(this.tech_, 'emptied', this.handletechemptied_);
this.on(this.tech_, 'stalled', this.handletechstalled_);
this.on(this.tech_, 'loadedmetadata', this.handletechloadedmetadata_);
this.on(this.tech_, 'loadeddata', this.handletechloadeddata_);
this.on(this.tech_, 'timeupdate', this.handletechtimeupdate_);
this.on(this.tech_, 'ratechange', this.handletechratechange_);
this.on(this.tech_, 'volumechange', this.handletechvolumechange_);
this.on(this.tech_, 'texttrackchange', this.handletechtexttrackchange_);
this.on(this.tech_, 'loadedmetadata', this.updatestyleel_);
this.on(this.tech_, 'posterchange', this.handletechposterchange_);
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 playback technology
*
* @method unloadtech_
* @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.texttracks_ = this.texttracks();
this.texttracksjson_ = _trackstexttracklistconverterjs2['default'].texttrackstojson(this.tech_);
this.isready_ = false;
this.tech_.dispose();
this.tech_ = false;
};
/**
* return a reference to the current tech.
* it will only return a reference to the tech if given an object with the
* `iwillnotusethisinplugins` property on it. this is try and prevent misuse
* of techs by plugins.
*
* @param {object}
* @return {object} the tech
* @method 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 ';
_globalwindow2['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 a mobile device a click on the video toggles controls.
* (toggling controls is done by toggling the user state between active and
* inactive)
* a tap can signal that a user has become active, or has become inactive
* e.g. a quick tap on an iphone movie should reveal the controls. another
* quick tap should hide them again (signaling the user is in an inactive
* viewing state)
* in addition to this, we still want the user to be considered inactive after
* a few seconds of inactivity.
* note: the only part of ios interaction we can't mimic with this setup
* is a touch and hold on the video element counting as activity in order to
* keep the controls showing, but that shouldn't be an issue. a touch and hold
* on any controls will still keep the user active
*
* @private
* @method addtechcontrolslisteners_
*/
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.
*
* @method removetechcontrolslisteners_
* @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
*
* @method handletechready_
* @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.tag && this.options_.autoplay && this.paused()) {
delete this.tag.poster; // chrome fix. fixed in chrome v16.
this.play();
}
};
/**
* fired when the user agent begins looking for media data
*
* @private
* @method handletechloadstart_
*/
player.prototype.handletechloadstart_ = function handletechloadstart_() {
// todo: update to use `emptied` event instead. see #1277.
this.removeclass('vjs-ended');
// 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()) {
this.trigger('loadstart');
this.trigger('firstplay');
} else {
// reset the hasstarted state
this.hasstarted(false);
this.trigger('loadstart');
}
};
/**
* add/remove the vjs-has-started class
*
* @param {boolean} hasstarted the value of true adds the class the value of false remove the class
* @return {boolean} boolean value if has started
* @private
* @method 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
*
* @private
* @method handletechplay_
*/
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
// https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play
this.hasstarted(true);
this.trigger('play');
};
/**
* fired whenever the media begins waiting
*
* @private
* @method handletechwaiting_
*/
player.prototype.handletechwaiting_ = function handletechwaiting_() {
var _this2 = this;
this.addclass('vjs-waiting');
this.trigger('waiting');
this.one('timeupdate', function () {
return _this2.removeclass('vjs-waiting');
});
};
/**
* a handler for events that signal that waiting has ended
* which is not consistent between browsers. see #1351
*
* @private
* @method handletechcanplay_
*/
player.prototype.handletechcanplay_ = function handletechcanplay_() {
this.removeclass('vjs-waiting');
this.trigger('canplay');
};
/**
* a handler for events that signal that waiting has ended
* which is not consistent between browsers. see #1351
*
* @private
* @method handletechcanplaythrough_
*/
player.prototype.handletechcanplaythrough_ = function handletechcanplaythrough_() {
this.removeclass('vjs-waiting');
this.trigger('canplaythrough');
};
/**
* a handler for events that signal that waiting has ended
* which is not consistent between browsers. see #1351
*
* @private
* @method handletechplaying_
*/
player.prototype.handletechplaying_ = function handletechplaying_() {
this.removeclass('vjs-waiting');
this.trigger('playing');
};
/**
* fired whenever the player is jumping to a new time
*
* @private
* @method handletechseeking_
*/
player.prototype.handletechseeking_ = function handletechseeking_() {
this.addclass('vjs-seeking');
this.trigger('seeking');
};
/**
* fired when the player has finished jumping to a new time
*
* @private
* @method handletechseeked_
*/
player.prototype.handletechseeked_ = function handletechseeked_() {
this.removeclass('vjs-seeking');
this.trigger('seeked');
};
/**
* fired the first time a video is played
* not part of the hls spec, and we're not sure if this is the best
* implementation yet, so use sparingly. if you don't have a reason to
* prevent playback, use `myplayer.one('play');` instead.
*
* @private
* @method handletechfirstplay_
*/
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) {
this.currenttime(this.options_.starttime);
}
this.addclass('vjs-has-started');
this.trigger('firstplay');
};
/**
* fired whenever the media has been paused
*
* @private
* @method handletechpause_
*/
player.prototype.handletechpause_ = function handletechpause_() {
this.removeclass('vjs-playing');
this.addclass('vjs-paused');
this.trigger('pause');
};
/**
* fired while the user agent is downloading media data
*
* @private
* @method handletechprogress_
*/
player.prototype.handletechprogress_ = function handletechprogress_() {
this.trigger('progress');
};
/**
* fired when the end of the media resource is reached (currenttime == duration)
*
* @private
* @method handletechended_
*/
player.prototype.handletechended_ = function handletechended_() {
this.addclass('vjs-ended');
if (this.options_.loop) {
this.currenttime(0);
this.play();
} else if (!this.paused()) {
this.pause();
}
this.trigger('ended');
};
/**
* fired when the duration of the media resource is first known or changed
*
* @private
* @method handletechdurationchange_
*/
player.prototype.handletechdurationchange_ = function handletechdurationchange_() {
this.duration(this.techget_('duration'));
};
/**
* handle a click on the media element to play/pause
*
* @param {object=} event event object
* @private
* @method handletechclick_
*/
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.
*
* @private
* @method handletechtap_
*/
player.prototype.handletechtap_ = function handletechtap_() {
this.useractive(!this.useractive());
};
/**
* handle touch to start
*
* @private
* @method handletechtouchstart_
*/
player.prototype.handletechtouchstart_ = function handletechtouchstart_() {
this.userwasactive = this.useractive();
};
/**
* handle touch to move
*
* @private
* @method handletechtouchmove_
*/
player.prototype.handletechtouchmove_ = function handletechtouchmove_() {
if (this.userwasactive) {
this.reportuseractivity();
}
};
/**
* handle touch to end
*
* @private
* @method handletechtouchend_
*/
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
* @method handlefullscreenchange_
*/
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
* @method handlestageclick_
*/
player.prototype.handlestageclick_ = function handlestageclick_() {
this.reportuseractivity();
};
/**
* handle tech fullscreen change
*
* @private
* @method handletechfullscreenchange_
*/
player.prototype.handletechfullscreenchange_ = function handletechfullscreenchange_(event, data) {
if (data) {
this.isfullscreen(data.isfullscreen);
}
this.trigger('fullscreenchange');
};
/**
* fires when an error occurred during the loading of an audio/video
*
* @private
* @method handletecherror_
*/
player.prototype.handletecherror_ = function handletecherror_() {
var error = this.tech_.error();
this.error(error && error.code);
};
/**
* fires when the browser is intentionally not getting media data
*
* @private
* @method handletechsuspend_
*/
player.prototype.handletechsuspend_ = function handletechsuspend_() {
this.trigger('suspend');
};
/**
* fires when the loading of an audio/video is aborted
*
* @private
* @method handletechabort_
*/
player.prototype.handletechabort_ = function handletechabort_() {
this.trigger('abort');
};
/**
* fires when the current playlist is empty
*
* @private
* @method handletechemptied_
*/
player.prototype.handletechemptied_ = function handletechemptied_() {
this.trigger('emptied');
};
/**
* fires when the browser is trying to get media data, but data is not available
*
* @private
* @method handletechstalled_
*/
player.prototype.handletechstalled_ = function handletechstalled_() {
this.trigger('stalled');
};
/**
* fires when the browser has loaded meta data for the audio/video
*
* @private
* @method handletechloadedmetadata_
*/
player.prototype.handletechloadedmetadata_ = function handletechloadedmetadata_() {
this.trigger('loadedmetadata');
};
/**
* fires when the browser has loaded the current frame of the audio/video
*
* @private
* @method handletechloadeddata_
*/
player.prototype.handletechloadeddata_ = function handletechloadeddata_() {
this.trigger('loadeddata');
};
/**
* fires when the current playback position has changed
*
* @private
* @method handletechtimeupdate_
*/
player.prototype.handletechtimeupdate_ = function handletechtimeupdate_() {
this.trigger('timeupdate');
};
/**
* fires when the playing speed of the audio/video is changed
*
* @private
* @method handletechratechange_
*/
player.prototype.handletechratechange_ = function handletechratechange_() {
this.trigger('ratechange');
};
/**
* fires when the volume has been changed
*
* @private
* @method handletechvolumechange_
*/
player.prototype.handletechvolumechange_ = function handletechvolumechange_() {
this.trigger('volumechange');
};
/**
* fires when the text track has been changed
*
* @private
* @method handletechtexttrackchange_
*/
player.prototype.handletechtexttrackchange_ = function handletechtexttrackchange_() {
this.trigger('texttrackchange');
};
/**
* get object for cached values.
*
* @return {object}
* @method getcache
*/
player.prototype.getcache = function getcache() {
return this.cache_;
};
/**
* pass values to the playback tech
*
* @param {string=} method method
* @param {object=} arg argument
* @private
* @method techcall_
*/
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 {
this.tech_[method](arg);
} catch (e) {
_utilslogjs2['default'](e);
throw e;
}
}
};
/**
* get calls can't wait for the tech, and sometimes don't need to.
*
* @param {string} method tech method
* @return {method}
* @private
* @method techget_
*/
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) {
_utilslogjs2['default']('video.js: ' + method + ' method not defined for ' + this.techname_ + ' playback technology.', e);
} else {
// when a method isn't available on the object it throws a typeerror
if (e.name === 'typeerror') {
_utilslogjs2['default']('video.js: ' + method + ' unavailable on ' + this.techname_ + ' playback technology element.', e);
this.tech_.isready_ = false;
} else {
_utilslogjs2['default'](e);
}
}
throw e;
}
}
return;
};
/**
* start media playback
* ```js
* myplayer.play();
* ```
*
* @return {player} self
* @method play
*/
player.prototype.play = function play() {
this.techcall_('play');
return this;
};
/**
* pause the video playback
* ```js
* myplayer.pause();
* ```
*
* @return {player} self
* @method pause
*/
player.prototype.pause = function pause() {
this.techcall_('pause');
return this;
};
/**
* check if the player is paused
* ```js
* var ispaused = myplayer.paused();
* var isplaying = !myplayer.paused();
* ```
*
* @return {boolean} false if the media is currently playing, or true otherwise
* @method paused
*/
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 true/false the user is scrubbing
* @return {boolean} the scrubbing status when getting
* @return {object} the player when setting
* @method scrubbing
*/
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)
* ```js
* // get
* var whereyouat = myplayer.currenttime();
* // set
* myplayer.currenttime(120); // 2 minutes into the video
* ```
*
* @param {number|string=} seconds the time to seek to
* @return {number} the time in seconds, when not setting
* @return {player} self, when the current time is set
* @method currenttime
*/
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.
return this.cache_.currenttime = this.techget_('currenttime') || 0;
};
/**
* get the length in time of the video in seconds
* ```js
* var lengthofvideo = myplayer.duration();
* ```
* **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.
*
* @param {number} seconds duration when setting
* @return {number} the duration of the video in seconds when getting
* @method duration
*/
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');
}
this.trigger('durationchange');
}
return this;
};
/**
* calculates how much time is left.
* ```js
* var timeleft = myplayer.remainingtime();
* ```
* not a native video element function, but useful
*
* @return {number} the time remaining in seconds
* @method remainingtime
*/
player.prototype.remainingtime = function remainingtime() {
return this.duration() - this.currenttime();
};
// http://dev.w3.org/html5/spec/video.html#dom-media-buffered
// buffered returns a timerange object.
// kind of like an array of portions of the video that have been downloaded.
/**
* get a timerange object with the times of the video that have been downloaded
* if you just want the percent of the video that's been downloaded,
* use bufferedpercent.
* ```js
* // number of different ranges of time have been buffered. usually 1.
* numberofranges = bufferedtimerange.length,
* // time in seconds when the first range starts. usually 0.
* firstrangestart = bufferedtimerange.start(0),
* // time in seconds when the first range ends
* firstrangeend = bufferedtimerange.end(0),
* // length in seconds of the first time range
* firstrangelength = firstrangeend - firstrangestart;
* ```
*
* @return {object} a mock timerange object (following html spec)
* @method buffered
*/
player.prototype.buffered = function buffered() {
var buffered = this.techget_('buffered');
if (!buffered || !buffered.length) {
buffered = _utilstimerangesjs.createtimerange(0, 0);
}
return buffered;
};
/**
* get the percent (as a decimal) of the video that's been downloaded
* ```js
* var howmuchisdownloaded = myplayer.bufferedpercent();
* ```
* 0 means none, 1 means all.
* (this method isn't in the html5 spec, but it's very convenient)
*
* @return {number} a decimal between 0 and 1 representing the percent
* @method bufferedpercent
*/
player.prototype.bufferedpercent = function bufferedpercent() {
return _utilsbufferjs.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
* @method bufferedend
*/
player.prototype.bufferedend = function bufferedend() {
var buffered = this.buffered(),
duration = this.duration(),
end = buffered.end(buffered.length - 1);
if (end > duration) {
end = duration;
}
return end;
};
/**
* get or set the current volume of the media
* ```js
* // get
* var howloudisit = myplayer.volume();
* // set
* myplayer.volume(0.5); // set volume to half
* ```
* 0 is off (muted), 1.0 is all the way up, 0.5 is half way.
*
* @param {number} percentasdecimal the new volume as a decimal percent
* @return {number} the current volume when getting
* @return {player} self when setting
* @method volume
*/
player.prototype.volume = function volume(percentasdecimal) {
var vol = undefined;
if (percentasdecimal !== undefined) {
vol = math.max(0, math.min(1, parsefloat(percentasdecimal))); // force value to between 0 and 1
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
* ```js
* // get
* var isvolumemuted = myplayer.muted();
* // set
* myplayer.muted(true); // mute the volume
* ```
*
* @param {boolean=} muted true to mute, false to unmute
* @return {boolean} true if mute is on, false if not when getting
* @return {player} self when setting mute
* @method muted
*/
player.prototype.muted = function muted(_muted) {
if (_muted !== undefined) {
this.techcall_('setmuted', _muted);
return this;
}
return this.techget_('muted') || false; // default to false
};
// check if current tech can support native fullscreen
// (e.g. with built in controls like ios, so not our flash swf)
/**
* check to see if fullscreen is supported
*
* @return {boolean}
* @method supportsfullscreen
*/
player.prototype.supportsfullscreen = function supportsfullscreen() {
return this.techget_('supportsfullscreen') || false;
};
/**
* check if the player is in fullscreen mode
* ```js
* // get
* var fullscreenornot = myplayer.isfullscreen();
* // set
* myplayer.isfullscreen(true); // tell the player it's in fullscreen
* ```
* 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 update the player's fullscreen state
* @return {boolean} true if fullscreen false if not when getting
* @return {player} self when setting
* @method isfullscreen
*/
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
* ```js
* myplayer.requestfullscreen();
* ```
* 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.
*
* @return {player} self
* @method requestfullscreen
*/
player.prototype.requestfullscreen = function requestfullscreen() {
var fsapi = _fullscreenapijs2['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(_globaldocument2['default'], fsapi.fullscreenchange, fn.bind(this, function documentfullscreenchange(e) {
this.isfullscreen(_globaldocument2['default'][fsapi.fullscreenelement]);
// if cancelling fullscreen, remove event listener.
if (this.isfullscreen() === false) {
events.off(_globaldocument2['default'], fsapi.fullscreenchange, documentfullscreenchange);
}
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();
this.trigger('fullscreenchange');
}
return this;
};
/**
* return the video to its normal size after having been in full screen mode
* ```js
* myplayer.exitfullscreen();
* ```
*
* @return {player} self
* @method exitfullscreen
*/
player.prototype.exitfullscreen = function exitfullscreen() {
var fsapi = _fullscreenapijs2['default'];
this.isfullscreen(false);
// check for browser element fullscreen support
if (fsapi.requestfullscreen) {
_globaldocument2['default'][fsapi.exitfullscreen]();
} else if (this.tech_.supportsfullscreen()) {
this.techcall_('exitfullscreen');
} else {
this.exitfullwindow();
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.
*
* @method enterfullwindow
*/
player.prototype.enterfullwindow = function enterfullwindow() {
this.isfullwindow = true;
// storing original doc overflow value to return to when fullscreen is off
this.docorigoverflow = _globaldocument2['default'].documentelement.style.overflow;
// add listener for esc key to exit fullscreen
events.on(_globaldocument2['default'], 'keydown', fn.bind(this, this.fullwindowonesckey));
// hide any scroll bars
_globaldocument2['default'].documentelement.style.overflow = 'hidden';
// apply fullscreen styles
dom.addelclass(_globaldocument2['default'].body, 'vjs-full-window');
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
* @method fullwindowonesckey
*/
player.prototype.fullwindowonesckey = function fullwindowonesckey(event) {
if (event.keycode === 27) {
if (this.isfullscreen() === true) {
this.exitfullscreen();
} else {
this.exitfullwindow();
}
}
};
/**
* exit full window
*
* @method exitfullwindow
*/
player.prototype.exitfullwindow = function exitfullwindow() {
this.isfullwindow = false;
events.off(_globaldocument2['default'], 'keydown', this.fullwindowonesckey);
// unhide scroll bars.
_globaldocument2['default'].documentelement.style.overflow = this.docorigoverflow;
// remove fullscreen styles
dom.removeelclass(_globaldocument2['default'].body, 'vjs-full-window');
// resize the box, controller, and poster to original sizes
// this.positionall();
this.trigger('exitfullwindow');
};
/**
* check whether the player can play a given mimetype
*
* @param {string} type the mimetype to check
* @return {string} 'probably', 'maybe', or '' (empty string)
* @method canplaytype
*/
player.prototype.canplaytype = function canplaytype(type) {
var can = undefined;
// loop through each playback technology in the options order
for (var i = 0, j = this.options_.techorder; i < j.length; i++) {
var techname = _utilstotitlecasejs2['default'](j[i]);
var tech = _techtechjs2['default'].gettech(techname);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!tech) {
tech = _componentjs2['default'].getcomponent(techname);
}
// check if the current tech is defined before continuing
if (!tech) {
_utilslogjs2['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, otherwise false
* @method selectsource
*/
player.prototype.selectsource = function selectsource(sources) {
// get only the techs specified in `techorder` that exist and are supported by the
// current platform
var techs = this.options_.techorder.map(_utilstotitlecasejs2['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, _techtechjs2['default'].gettech(techname) || _componentjs2['default'].getcomponent(techname)];
}).filter(function (_ref) {
var techname = _ref[0];
var tech = _ref[1];
// check if the current tech is defined before continuing
if (tech) {
// check if the browser supports this technology
return tech.issupported();
}
_utilslogjs2['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 = undefined;
outerarray.some(function (outerchoice) {
return innerarray.some(function (innerchoice) {
found = tester(outerchoice, innerchoice);
if (found) {
return true;
}
});
});
return found;
};
var foundsourceandtech = undefined;
var flip = function flip(fn) {
return function (a, b) {
return fn(b, a);
};
};
var finder = function finder(_ref2, source) {
var techname = _ref2[0];
var tech = _ref2[1];
if (tech.canplaysource(source)) {
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.
* ```js
* myplayer.src("http://www.example.com/path/to/video.mp4");
* ```
* **source object (or element):* * a javascript object containing information
* about the source file. use this method if you want the player to determine if
* it can support the file using the type information.
* ```js
* myplayer.src({ type: "video/mp4", src: "http://www.example.com/path/to/video.mp4" });
* ```
* **array of source objects:* * to provide multiple versions of the source so
* that it can be played using html5 across browsers you can use an array of
* source objects. video.js will detect which version is supported and load that
* file.
* ```js
* myplayer.src([
* { type: "video/mp4", src: "http://www.example.com/path/to/video.mp4" },
* { type: "video/webm", src: "http://www.example.com/path/to/video.webm" },
* { type: "video/ogg", src: "http://www.example.com/path/to/video.ogv" }
* ]);
* ```
*
* @param {string|object|array=} source the source url, object, or array of sources
* @return {string} the current video source when getting
* @return {string} the player when setting
* @method src
*/
player.prototype.src = function src(source) {
if (source === undefined) {
return this.techget_('src');
}
var currenttech = _techtechjs2['default'].gettech(this.techname_);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!currenttech) {
currenttech = _componentjs2['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)) {
// 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_.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 {array} sources array of source objects
* @private
* @method sourcelist_
*/
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);
}
} 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} returns the player
* @method load
*/
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} returns the player
* @method reset
*/
player.prototype.reset = function reset() {
this.loadtech_(_utilstotitlecasejs2['default'](this.options_.techorder[0]), null);
this.techcall_('reset');
return this;
};
/**
* 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
* @method currentsrc
*/
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
* @method currenttype
*/
player.prototype.currenttype = function currenttype() {
return this.currenttype_ || '';
};
/**
* get or set the preload attribute
*
* @param {boolean} value boolean to determine if preload should be used
* @return {string} the preload attribute value when getting
* @return {player} returns the player when setting
* @method preload
*/
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 boolean to determine if video should autoplay
* @return {string} the autoplay attribute value when getting
* @return {player} returns the player when setting
* @method autoplay
*/
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 boolean to determine if video should loop
* @return {string} the loop attribute value when getting
* @return {player} returns the player when setting
* @method loop
*/
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
*
* ##### example:
* ```js
* // get
* var currentposter = myplayer.poster();
* // set
* myplayer.poster('http://example.com/myimage.jpg');
* ```
*
* @param {string=} src poster image source url
* @return {string} poster url when getting
* @return {player} self when setting
* @method poster
*/
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.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.
*
* @private
* @method handletechposterchange_
*/
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.
*
* @param {boolean} bool set controls to showing or not
* @return {boolean} controls are showing
* @method controls
*/
player.prototype.controls = function controls(bool) {
if (bool !== undefined) {
bool = !!bool; // force boolean
// 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');
this.trigger('controlsenabled');
if (!this.usingnativecontrols()) {
this.addtechcontrolslisteners_();
}
} else {
this.removeclass('vjs-controls-enabled');
this.addclass('vjs-controls-disabled');
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**
*
* @param {boolean} bool true signals that native controls are on
* @return {player} returns the player
* @private
* @method usingnativecontrols
*/
player.prototype.usingnativecontrols = function usingnativecontrols(bool) {
if (bool !== undefined) {
bool = !!bool; // force boolean
// 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 usingnativecontrols
* @memberof player
* @instance
* @private
*/
this.trigger('usingnativecontrols');
} else {
this.removeclass('vjs-using-native-controls');
/**
* player is using the custom html controls
*
* @event usingcustomcontrols
* @memberof player
* @instance
* @private
*/
this.trigger('usingcustomcontrols');
}
}
return this;
}
return !!this.usingnativecontrols_;
};
/**
* set or get the current mediaerror
*
* @param {*} err a mediaerror or a string/number to be turned into a mediaerror
* @return {mediaerror|null} when getting
* @return {player} when setting
* @method error
*/
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');
this.errordisplay.close();
return this;
}
// error instance
if (err instanceof _mediaerrorjs2['default']) {
this.error_ = err;
} else {
this.error_ = new _mediaerrorjs2['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
_utilslogjs2['default'].error('(code:' + this.error_.code + ' ' + _mediaerrorjs2['default'].errortypes[this.error_.code] + ')', this.error_.message, this.error_);
// fire an error event on the player
this.trigger('error');
return this;
};
/**
* 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 ended
*/
player.prototype.ended = function ended() {
return this.techget_('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 seeking
*/
player.prototype.seeking = function seeking() {
return this.techget_('seeking');
};
/**
* returns the timeranges of the media that are currently available
* for seeking to.
*
* @return {timeranges} the seekable intervals of the media timeline
* @method seekable
*/
player.prototype.seekable = function seekable() {
return this.techget_('seekable');
};
/**
* report user activity
*
* @param {object} event event object
* @method reportuseractivity
*/
player.prototype.reportuseractivity = function reportuseractivity(event) {
this.useractivity_ = true;
};
/**
* get/set if user is active
*
* @param {boolean} bool value when setting
* @return {boolean} value if user is active user when getting
* @method useractive
*/
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');
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');
this.trigger('userinactive');
}
}
return this;
}
return this.useractive_;
};
/**
* listen for user activity based on timeout value
*
* @private
* @method listenforuseractivity_
*/
player.prototype.listenforuseractivity_ = function listenforuseractivity_() {
var mouseinprogress = undefined,
lastmovex = undefined,
lastmovey = undefined;
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 = undefined;
var activitycheck = 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 activitycheck 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} returns the new playback rate when setting
* @return {number} returns the current playback rate when getting
* @method playbackrate
*/
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');
} else {
return 1.0;
}
};
/**
* gets or sets the audio flag
*
* @param {boolean} bool true signals that this is an audio player.
* @return {boolean} returns true if player is audio, false if not when getting
* @return {player} returns the player if setting
* @private
* @method isaudio
*/
player.prototype.isaudio = function isaudio(bool) {
if (bool !== undefined) {
this.isaudio_ = !!bool;
return this;
}
return !!this.isaudio_;
};
/**
* 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 networkstate
*/
player.prototype.networkstate = function networkstate() {
return this.techget_('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 readystate
*/
player.prototype.readystate = function readystate() {
return this.techget_('readystate');
};
/*
* 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 supported yet) - audio descriptions that are read back to the user by a screen reading device
*/
/**
* get an array of associated text tracks. captions, subtitles, chapters, descriptions
* http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks
*
* @return {array} array of track objects
* @method texttracks
*/
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.
return this.tech_ && this.tech_['texttracks']();
};
/**
* get an array of remote text tracks
*
* @return {array}
* @method remotetexttracks
*/
player.prototype.remotetexttracks = function remotetexttracks() {
return this.tech_ && this.tech_['remotetexttracks']();
};
/**
* get an array of remote html track elements
*
* @return {htmltrackelement[]}
* @method remotetexttrackels
*/
player.prototype.remotetexttrackels = function remotetexttrackels() {
return this.tech_ && this.tech_['remotetexttrackels']();
};
/**
* add a text track
* in addition to the w3c settings we allow adding additional info through options.
* http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack
*
* @param {string} kind captions, subtitles, chapters, descriptions, or metadata
* @param {string=} label optional label
* @param {string=} language optional language
* @method addtexttrack
*/
player.prototype.addtexttrack = function addtexttrack(kind, label, language) {
return this.tech_ && this.tech_['addtexttrack'](kind, label, language);
};
/**
* add a remote text track
*
* @param {object} options options for remote text track
* @method addremotetexttrack
*/
player.prototype.addremotetexttrack = function addremotetexttrack(options) {
return this.tech_ && this.tech_['addremotetexttrack'](options);
};
/**
* remove a remote text track
*
* @param {object} track remote text track to remove
* @method removeremotetexttrack
*/
player.prototype.removeremotetexttrack = function removeremotetexttrack(track) {
this.tech_ && this.tech_['removeremotetexttrack'](track);
};
/**
* get video width
*
* @return {number} video width
* @method videowidth
*/
player.prototype.videowidth = function videowidth() {
return this.tech_ && this.tech_.videowidth && this.tech_.videowidth() || 0;
};
/**
* get video height
*
* @return {number} video height
* @method videoheight
*/
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'); },
// videotracks: function(){ return this.techcall_('videotracks'); },
// audiotracks: function(){ return this.techcall_('audiotracks'); },
// 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 locale string
* @return {string} the locale string when getting
* @return {player} self when setting
* @method language
*/
player.prototype.language = function language(code) {
if (code === undefined) {
return this.language_;
}
this.language_ = ('' + 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} array of languages
* @method languages
*/
player.prototype.languages = function languages() {
return _utilsmergeoptionsjs2['default'](player.prototype.options_.languages, this.languages_);
};
/**
* converts track info to json
*
* @return {object} json object of options
* @method tojson
*/
player.prototype.tojson = function tojson() {
var options = _utilsmergeoptionsjs2['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 = _utilsmergeoptionsjs2['default'](track);
track.player = undefined;
options.tracks[i] = track;
}
return options;
};
/**
* creates a simple modal dialog (an instance of the `modaldialog`
* component) that immediately overlays the player with arbitrary
* content and removes itself when closed.
*
* @param {string|function|element|array|null} content
* same as `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 `modaldialog`.
*
* @return {modaldialog}
*/
player.prototype.createmodal = function createmodal(content, options) {
var player = this;
options = options || {};
options.content = content || '';
var modal = new _modaldialog2['default'](player, options);
player.addchild(modal);
modal.on('dispose', function () {
player.removechild(modal);
});
return modal.open();
};
/**
* gets tag settings
*
* @param {element} tag the player tag
* @return {array} an array of sources and track objects
* @static
* @method gettagsettings
*/
player.gettagsettings = function gettagsettings(tag) {
var baseoptions = {
'sources': [],
'tracks': []
};
var tagoptions = dom.getelattributes(tag);
var datasetup = tagoptions['data-setup'];
// check if data-setup attr exists.
if (datasetup !== null) {
// parse options json
var _safeparsetuple = _safejsonparsetuple2['default'](datasetup || '{}');
var err = _safeparsetuple[0];
var data = _safeparsetuple[1];
if (err) {
_utilslogjs2['default'].error(err);
}
_objectassign2['default'](tagoptions, data);
}
_objectassign2['default'](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;
};
return player;
})(_componentjs2['default']);
player.players = {};
var navigator = _globalwindow2['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, // the freakin seaguls are driving me crazy!
// 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: _globaldocument2['default'].getelementsbytagname('html')[0].getattribute('lang') || 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.'
};
/**
* fired when the player has initial duration and dimension information
*
* @event loadedmetadata
*/
player.prototype.handleloadedmetadata_;
/**
* fired when the player has downloaded data at the current playback position
*
* @event loadeddata
*/
player.prototype.handleloadeddata_;
/**
* fired when the user is active, e.g. moves the mouse over the player
*
* @event useractive
*/
player.prototype.handleuseractive_;
/**
* fired when the user is inactive, e.g. a short delay after the last mouse move or control interaction
*
* @event userinactive
*/
player.prototype.handleuserinactive_;
/**
* 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 timeupdate
*/
player.prototype.handletimeupdate_;
/**
* fired when video playback ends
*
* @event ended
*/
player.prototype.handletechended_;
/**
* fired when the volume changes
*
* @event volumechange
*/
player.prototype.handlevolumechange_;
/**
* fired when an error occurs
*
* @event error
*/
player.prototype.handleerror_;
player.prototype.flexnotsupported_ = function () {
var elem = _globaldocument2['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 || 'msflexorder' in elem.style) /* ie10-specific (2012 flex spec) */;
};
_componentjs2['default'].registercomponent('player', player);
exports['default'] = player;
module.exports = exports['default'];
// if empty string, make it a parsable json object.
},{"./big-play-button.js":63,"./component.js":67,"./control-bar/control-bar.js":68,"./error-display.js":98,"./fullscreen-api.js":101,"./loading-spinner.js":102,"./media-error.js":103,"./modal-dialog":107,"./poster-image.js":112,"./tech/html5.js":117,"./tech/loader.js":118,"./tech/tech.js":119,"./tracks/text-track-display.js":123,"./tracks/text-track-list-converter.js":125,"./tracks/text-track-settings.js":127,"./utils/browser.js":129,"./utils/buffer.js":130,"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/guid.js":136,"./utils/log.js":137,"./utils/merge-options.js":138,"./utils/stylesheet.js":139,"./utils/time-ranges.js":140,"./utils/to-title-case.js":141,"global/document":1,"global/window":2,"object.assign":45,"safe-json-parse/tuple":54}],109:[function(_dereq_,module,exports){
/**
* @file plugins.js
*/
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _playerjs = _dereq_('./player.js');
var _playerjs2 = _interoprequiredefault(_playerjs);
/**
* the method for registering a video.js plugin
*
* @param {string} name the name of the plugin
* @param {function} init the function that is run when the player inits
* @method plugin
*/
var plugin = function plugin(name, init) {
_playerjs2['default'].prototype[name] = init;
};
exports['default'] = plugin;
module.exports = exports['default'];
},{"./player.js":108}],110:[function(_dereq_,module,exports){
/**
* @file popup-button.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _clickablecomponentjs = _dereq_('../clickable-component.js');
var _clickablecomponentjs2 = _interoprequiredefault(_clickablecomponentjs);
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _popupjs = _dereq_('./popup.js');
var _popupjs2 = _interoprequiredefault(_popupjs);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilstotitlecasejs = _dereq_('../utils/to-title-case.js');
var _utilstotitlecasejs2 = _interoprequiredefault(_utilstotitlecasejs);
/**
* a button class with a popup control
*
* @param {player|object} player
* @param {object=} options
* @extends clickablecomponent
* @class popupbutton
*/
var popupbutton = (function (_clickablecomponent) {
_inherits(popupbutton, _clickablecomponent);
function popupbutton(player) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
_classcallcheck(this, popupbutton);
_clickablecomponent.call(this, player, options);
this.update();
}
/**
* update popup
*
* @method update
*/
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 popup - override with specific functionality for component
*
* @return {popup} the constructed popup
* @method createpopup
*/
popupbutton.prototype.createpopup = function createpopup() {};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
popupbutton.prototype.createel = function createel() {
return _clickablecomponent.prototype.createel.call(this, 'div', {
classname: this.buildcssclass()
});
};
/**
* allow sub components to stack css class names
*
* @return {string} the constructed class name
* @method buildcssclass
*/
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;
})(_clickablecomponentjs2['default']);
_componentjs2['default'].registercomponent('popupbutton', popupbutton);
exports['default'] = popupbutton;
module.exports = exports['default'];
},{"../clickable-component.js":65,"../component.js":67,"../utils/dom.js":132,"../utils/fn.js":134,"../utils/to-title-case.js":141,"./popup.js":111}],111:[function(_dereq_,module,exports){
/**
* @file popup.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilseventsjs = _dereq_('../utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
/**
* the popup component is used to build pop up controls.
*
* @extends component
* @class popup
*/
var popup = (function (_component) {
_inherits(popup, _component);
function popup() {
_classcallcheck(this, popup);
_component.apply(this, arguments);
}
/**
* add a popup item to the popup
*
* @param {object|string} component component or component type to add
* @method additem
*/
popup.prototype.additem = function additem(component) {
this.addchild(component);
component.on('click', fn.bind(this, function () {
this.unlockshowing();
}));
};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('popup', popup);
exports['default'] = popup;
module.exports = exports['default'];
},{"../component.js":67,"../utils/dom.js":132,"../utils/events.js":133,"../utils/fn.js":134}],112:[function(_dereq_,module,exports){
/**
* @file poster-image.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _clickablecomponentjs = _dereq_('./clickable-component.js');
var _clickablecomponentjs2 = _interoprequiredefault(_clickablecomponentjs);
var _componentjs = _dereq_('./component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsfnjs = _dereq_('./utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsdomjs = _dereq_('./utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsbrowserjs = _dereq_('./utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
/**
* the component that handles showing the poster image.
*
* @param {player|object} player
* @param {object=} options
* @extends button
* @class posterimage
*/
var posterimage = (function (_clickablecomponent) {
_inherits(posterimage, _clickablecomponent);
function posterimage(player, options) {
_classcallcheck(this, posterimage);
_clickablecomponent.call(this, player, options);
this.update();
player.on('posterchange', fn.bind(this, this.update));
}
/**
* clean up the poster image
*
* @method dispose
*/
posterimage.prototype.dispose = function dispose() {
this.player().off('posterchange', this.update);
_clickablecomponent.prototype.dispose.call(this);
};
/**
* create the poster's image element
*
* @return {element}
* @method createel
*/
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;
};
/**
* event handler for updates to the player's poster source
*
* @method update
*/
posterimage.prototype.update = function update() {
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 poster source depending on the display method
*
* @param {string} url the url to the poster source
* @method setsrc
*/
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;
}
};
/**
* event handler for clicks on the poster image
*
* @method handleclick
*/
posterimage.prototype.handleclick = function handleclick() {
// we don't want a click to trigger playback when controls are disabled
// but css should be hiding the poster to prevent that from happening
if (this.player_.paused()) {
this.player_.play();
} else {
this.player_.pause();
}
};
return posterimage;
})(_clickablecomponentjs2['default']);
_componentjs2['default'].registercomponent('posterimage', posterimage);
exports['default'] = posterimage;
module.exports = exports['default'];
},{"./clickable-component.js":65,"./component.js":67,"./utils/browser.js":129,"./utils/dom.js":132,"./utils/fn.js":134}],113:[function(_dereq_,module,exports){
/**
* @file setup.js
*
* functions for automatically setting up a player
* based on the data-setup attribute of the video tag
*/
'use strict';
exports.__esmodule = true;
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; } }
var _utilseventsjs = _dereq_('./utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _windowloaded = false;
var videojs = undefined;
// automatically set up any tags that have a data-setup attribute
var autosetup = function autosetup() {
// 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 = _globaldocument2['default'].getelementsbytagname('video');
var audios = _globaldocument2['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 i = 0, e = mediaels.length; i < e; i++) {
var mediael = mediaels[i];
// 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.
var player = 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);
}
};
// pause to let the dom keep processing
var autosetuptimeout = function autosetuptimeout(wait, vjs) {
if (vjs) {
videojs = vjs;
}
settimeout(autosetup, wait);
};
if (_globaldocument2['default'].readystate === 'complete') {
_windowloaded = true;
} else {
events.one(_globalwindow2['default'], 'load', function () {
_windowloaded = true;
});
}
var hasloaded = function hasloaded() {
return _windowloaded;
};
exports.autosetup = autosetup;
exports.autosetuptimeout = autosetuptimeout;
exports.hasloaded = hasloaded;
},{"./utils/events.js":133,"global/document":1,"global/window":2}],114:[function(_dereq_,module,exports){
/**
* @file slider.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
/**
* the base functionality for sliders like the volume bar and seek bar
*
* @param {player|object} player
* @param {object=} options
* @extends component
* @class slider
*/
var slider = (function (_component) {
_inherits(slider, _component);
function slider(player, options) {
_classcallcheck(this, slider);
_component.call(this, player, options);
// set property names to bar to match with the child slider class is looking for
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);
}
/**
* create the component's dom element
*
* @param {string} type type of element to create
* @param {object=} props list of properties in object form
* @return {element}
* @method createel
*/
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 = _objectassign2['default']({
tabindex: 0
}, props);
attributes = _objectassign2['default']({
'role': 'slider',
'aria-valuenow': 0,
'aria-valuemin': 0,
'aria-valuemax': 100,
tabindex: 0
}, attributes);
return _component.prototype.createel.call(this, type, props, attributes);
};
/**
* handle mouse down on slider
*
* @param {object} event mouse down event object
* @method handlemousedown
*/
slider.prototype.handlemousedown = function handlemousedown(event) {
event.preventdefault();
dom.blocktextselection();
this.addclass('vjs-sliding');
this.trigger('slideractive');
this.on(_globaldocument2['default'], 'mousemove', this.handlemousemove);
this.on(_globaldocument2['default'], 'mouseup', this.handlemouseup);
this.on(_globaldocument2['default'], 'touchmove', this.handlemousemove);
this.on(_globaldocument2['default'], 'touchend', this.handlemouseup);
this.handlemousemove(event);
};
/**
* to be overridden by a subclass
*
* @method handlemousemove
*/
slider.prototype.handlemousemove = function handlemousemove() {};
/**
* handle mouse up on slider
*
* @method handlemouseup
*/
slider.prototype.handlemouseup = function handlemouseup() {
dom.unblocktextselection();
this.removeclass('vjs-sliding');
this.trigger('sliderinactive');
this.off(_globaldocument2['default'], 'mousemove', this.handlemousemove);
this.off(_globaldocument2['default'], 'mouseup', this.handlemouseup);
this.off(_globaldocument2['default'], 'touchmove', this.handlemousemove);
this.off(_globaldocument2['default'], 'touchend', this.handlemouseup);
this.update();
};
/**
* update slider
*
* @method update
*/
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 {object} event event object
* @method calculatedistance
*/
slider.prototype.calculatedistance = function calculatedistance(event) {
var position = dom.getpointerposition(this.el_, event);
if (this.vertical()) {
return position.y;
}
return position.x;
};
/**
* handle on focus for slider
*
* @method handlefocus
*/
slider.prototype.handlefocus = function handlefocus() {
this.on(_globaldocument2['default'], 'keydown', this.handlekeypress);
};
/**
* handle key press for slider
*
* @param {object} event event object
* @method handlekeypress
*/
slider.prototype.handlekeypress = function handlekeypress(event) {
if (event.which === 37 || event.which === 40) {
// left and down arrows
event.preventdefault();
this.stepback();
} else if (event.which === 38 || event.which === 39) {
// up and right arrows
event.preventdefault();
this.stepforward();
}
};
/**
* handle on blur for slider
*
* @method handleblur
*/
slider.prototype.handleblur = function handleblur() {
this.off(_globaldocument2['default'], '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 object
* @method handleclick
*/
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} true if slider is vertical, false is horizontal
* @method vertical
*/
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;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('slider', slider);
exports['default'] = slider;
module.exports = exports['default'];
},{"../component.js":67,"../utils/dom.js":132,"global/document":1,"object.assign":45}],115:[function(_dereq_,module,exports){
/**
* @file flash-rtmp.js
*/
'use strict';
exports.__esmodule = true;
function flashrtmpdecorator(flash) {
flash.streamingformats = {
'rtmp/mp4': 'mp4',
'rtmp/flv': 'flv'
};
flash.streamfromparts = function (connection, stream) {
return connection + '&' + 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 = undefined;
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;
};
flash.isstreamingtype = function (srctype) {
return srctype in flash.streamingformats;
};
// rtmp has four variations, any string starting
// with one of these protocols should be valid
flash.rtmp_re = /^rtmp[set]?:\/\//i;
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 videotype
* @param {string} type the mimetype to check
* @return {string} 'probably', '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
* @return {string} 'probably', 'maybe', or '' (empty string)
*/
flash.rtmpsourcehandler.canhandlesource = function (source) {
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
* adaptive source handlers will have more complicated workflows before passing
* video data to the video element
* @param {object} source the source object
* @param {flash} tech the instance of the flash tech
*/
flash.rtmpsourcehandler.handlesource = function (source, tech) {
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;
module.exports = exports['default'];
},{}],116:[function(_dereq_,module,exports){
/**
* @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
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _tech = _dereq_('./tech');
var _tech2 = _interoprequiredefault(_tech);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsurljs = _dereq_('../utils/url.js');
var url = _interoprequirewildcard(_utilsurljs);
var _utilstimerangesjs = _dereq_('../utils/time-ranges.js');
var _flashrtmp = _dereq_('./flash-rtmp');
var _flashrtmp2 = _interoprequiredefault(_flashrtmp);
var _component = _dereq_('../component');
var _component2 = _interoprequiredefault(_component);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
var navigator = _globalwindow2['default'].navigator;
/**
* flash media controller - wrapper for fallback swf api
*
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends tech
* @class flash
*/
var flash = (function (_tech) {
_inherits(flash, _tech);
function flash(options, ready) {
_classcallcheck(this, flash);
_tech.call(this, options, ready);
// set the source when 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
_globalwindow2['default'].videojs = _globalwindow2['default'].videojs || {};
_globalwindow2['default'].videojs.flash = _globalwindow2['default'].videojs.flash || {};
_globalwindow2['default'].videojs.flash.onready = flash.onready;
_globalwindow2['default'].videojs.flash.onevent = flash.onevent;
_globalwindow2['default'].videojs.flash.onerror = flash.onerror;
this.on('seeked', function () {
this.lastseektarget_ = undefined;
});
}
// create setters and getters for attributes
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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) {
options.swf = '//vjs.zencdn.net/swf/5.0.1/video-js.swf';
}
// generate id for swf object
var objid = options.techid;
// merge default flashvars with ones passed in to init
var flashvars = _objectassign2['default']({
// 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 = _objectassign2['default']({
'wmode': 'opaque', // opaque is needed to overlay controls, but can affect playback performance
'bgcolor': '#000000' // using bgcolor prevents a white flash when the object is loading
}, options.params);
// merge default attributes with ones passed in
var attributes = _objectassign2['default']({
'id': objid,
'name': objid, // both id and name needed or swf to identify itself
'class': 'vjs-tech'
}, options.attributes);
this.el_ = flash.embed(options.swf, flashvars, params, attributes);
this.el_.tech = this;
return this.el_;
};
/**
* play for flash tech
*
* @method play
*/
flash.prototype.play = function play() {
if (this.ended()) {
this.setcurrenttime(0);
}
this.el_.vjs_play();
};
/**
* pause for flash tech
*
* @method pause
*/
flash.prototype.pause = function pause() {
this.el_.vjs_pause();
};
/**
* get/set video
*
* @param {object=} src source object
* @return {object}
* @method src
*/
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);
};
/**
* set video
*
* @param {object=} src source object
* @deprecated
* @method setsrc
*/
flash.prototype.setsrc = function setsrc(src) {
// 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()) {
var tech = this;
this.settimeout(function () {
tech.play();
}, 0);
}
};
/**
* returns true if the tech is currently seeking.
* @return {boolean} true if seeking
*/
flash.prototype.seeking = function seeking() {
return this.lastseektarget_ !== undefined;
};
/**
* set current time
*
* @param {number} time current time of video
* @method setcurrenttime
*/
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 current time
*
* @param {number=} time current time of video
* @return {number} current time
* @method currenttime
*/
flash.prototype.currenttime = function currenttime(time) {
// 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 current source
*
* @method currentsrc
*/
flash.prototype.currentsrc = function currentsrc() {
if (this.currentsource_) {
return this.currentsource_.src;
} else {
return this.el_.vjs_getproperty('currentsrc');
}
};
/**
* load media into player
*
* @method load
*/
flash.prototype.load = function load() {
this.el_.vjs_load();
};
/**
* get poster
*
* @method poster
*/
flash.prototype.poster = function poster() {
this.el_.vjs_getproperty('poster');
};
/**
* poster images are not handled by the flash tech so make this a no-op
*
* @method setposter
*/
flash.prototype.setposter = function setposter() {};
/**
* determine if can seek in media
*
* @return {timerangeobject}
* @method seekable
*/
flash.prototype.seekable = function seekable() {
var duration = this.duration();
if (duration === 0) {
return _utilstimerangesjs.createtimerange();
}
return _utilstimerangesjs.createtimerange(0, duration);
};
/**
* get buffered time range
*
* @return {timerangeobject}
* @method buffered
*/
flash.prototype.buffered = function buffered() {
var ranges = this.el_.vjs_getproperty('buffered');
if (ranges.length === 0) {
return _utilstimerangesjs.createtimerange();
}
return _utilstimerangesjs.createtimerange(ranges[0][0], ranges[0][1]);
};
/**
* get fullscreen support -
* flash does not allow fullscreen through javascript
* so always returns false
*
* @return {boolean} false
* @method supportsfullscreen
*/
flash.prototype.supportsfullscreen = function supportsfullscreen() {
return false; // flash does not allow fullscreen through javascript
};
/**
* request to enter fullscreen
* flash does not allow fullscreen through javascript
* so always returns false
*
* @return {boolean} false
* @method enterfullscreen
*/
flash.prototype.enterfullscreen = function enterfullscreen() {
return false;
};
return flash;
})(_tech2['default']);
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,duration,startoffsettime,paused,ended,videotracks,audiotracks,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]);
}
/* flash support testing -------------------------------------------------------- */
flash.issupported = function () {
return flash.version()[0] >= 10;
// return swfobject.hasflashplayerversion('10');
};
// add source handler pattern functions to this tech
_tech2['default'].withsourcehandlers(flash);
/*
* the default native source handler.
* this simply passes the source to the video element. nothing fancy.
*
* @param {object} source the source object
* @param {flash} tech the instance of the flash tech
*/
flash.nativesourcehandler = {};
/**
* check if flash can play the given videotype
* @param {string} type the mimetype to check
* @return {string} 'probably', 'maybe', or '' (empty string)
*/
flash.nativesourcehandler.canplaytype = function (type) {
if (type in flash.formats) {
return 'maybe';
}
return '';
};
/*
* check flash can handle the source natively
*
* @param {object} source the source object
* @return {string} 'probably', 'maybe', or '' (empty string)
*/
flash.nativesourcehandler.canhandlesource = function (source) {
var type;
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 flash object
* adaptive source handlers will have more complicated workflows before passing
* video data to the video element
*
* @param {object} source the source object
* @param {flash} tech the instance of the flash tech
*/
flash.nativesourcehandler.handlesource = function (source, tech) {
tech.setsrc(source.src);
};
/*
* clean up the source handler when disposing the player or switching sources..
* (no cleanup is needed when supporting the format natively)
*/
flash.nativesourcehandler.dispose = function () {};
// register the native source handler
flash.registersourcehandler(flash.nativesourcehandler);
flash.formats = {
'video/flv': 'flv',
'video/x-flv': 'flv',
'video/mp4': 'mp4',
'video/m4v': 'mp4'
};
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.
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 player
flash.onevent = function (swfid, eventname) {
var tech = dom.getel(swfid).tech;
tech.trigger(eventname);
};
// log errors from the swf
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);
};
// flash version check
flash.version = function () {
var version = '0,0,0';
// ie
try {
version = new _globalwindow2['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) {}
}
return version.split(',');
};
// flash embedding method. only used in non-iframe mode
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;
};
flash.getembedcode = function (swf, flashvars, params, attributes) {
var objtag = '';
});
attributes = _objectassign2['default']({
// 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
_flashrtmp2['default'](flash);
_component2['default'].registercomponent('flash', flash);
_tech2['default'].registertech('flash', flash);
exports['default'] = flash;
module.exports = exports['default'];
},{"../component":67,"../utils/dom.js":132,"../utils/time-ranges.js":140,"../utils/url.js":142,"./flash-rtmp":115,"./tech":119,"global/window":2,"object.assign":45}],117:[function(_dereq_,module,exports){
/**
* @file html5.js
* html5 media controller - wrapper for html5 media api
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _techjs = _dereq_('./tech.js');
var _techjs2 = _interoprequiredefault(_techjs);
var _component = _dereq_('../component');
var _component2 = _interoprequiredefault(_component);
var _utilsdomjs = _dereq_('../utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsurljs = _dereq_('../utils/url.js');
var url = _interoprequirewildcard(_utilsurljs);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilslogjs = _dereq_('../utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _utilsbrowserjs = _dereq_('../utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
var _utilsmergeoptionsjs = _dereq_('../utils/merge-options.js');
var _utilsmergeoptionsjs2 = _interoprequiredefault(_utilsmergeoptionsjs);
/**
* html5 media controller - wrapper for html5 media api
*
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends tech
* @class html5
*/
var html5 = (function (_tech) {
_inherits(html5, _tech);
function html5(options, ready) {
_classcallcheck(this, html5);
_tech.call(this, options, ready);
var source = options.source;
// 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);
}
}
}
for (var i = 0; i < removenodes.length; i++) {
this.el_.removechild(removenodes[i]);
}
}
if (this.featuresnativetexttracks) {
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 && options.nativecontrolsfortouch === true || browser.is_iphone || browser.is_native_android) {
this.setcontrols(true);
}
this.triggerready();
}
/* html5 support testing ---------------------------------------------------- */
/*
* element for testing browser html5 video capabilities
*
* @type {element}
* @constant
* @private
*/
/**
* dispose of html5 media element
*
* @method dispose
*/
html5.prototype.dispose = function dispose() {
var tt = this.el().texttracks;
var emulatedtt = this.texttracks();
// remove native event listeners
if (tt && tt.removeeventlistener) {
tt.removeeventlistener('change', this.handletexttrackchange_);
tt.removeeventlistener('addtrack', this.handletexttrackadd_);
tt.removeeventlistener('removetrack', this.handletexttrackremove_);
}
// clearout the emulated text track list.
var i = emulatedtt.length;
while (i--) {
emulatedtt.removetrack_(emulatedtt[i]);
}
html5.disposemediaelement(this.el_);
_tech.prototype.dispose.call(this);
};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
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 (!el || this['movingmediaelementindom'] === false) {
// if the original tag is still there, clone and remove it.
if (el) {
var clone = el.clonenode(true);
el.parentnode.insertbefore(clone, el);
html5.disposemediaelement(el);
el = clone;
} else {
el = _globaldocument2['default'].createelement('video');
// determine if native controls should be used
var tagattributes = this.options_.tag && dom.getelattributes(this.options_.tag);
var attributes = _utilsmergeoptionsjs2['default']({}, tagattributes);
if (!browser.touch_enabled || this.options_.nativecontrolsfortouch !== true) {
delete attributes.controls;
}
dom.setelattributes(el, _objectassign2['default'](attributes, {
id: this.options_.techid,
'class': 'vjs-tech'
}));
}
}
// 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;
// jenniisawesome = true;
};
// if we're loading the playback object after it has started loading
// or playing the video (often with autoplay on) then the loadstart event
// has already fired and we need to fire it manually because many things
// rely on it.
html5.prototype.handlelateinit_ = function handlelateinit_(el) {
var _this = this;
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) {
var _ret = (function () {
// 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 {
v: undefined
};
})();
if (typeof _ret === 'object') return _ret.v;
}
// 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);
});
};
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_);
}
}
};
html5.prototype.handletexttrackchange = function handletexttrackchange(e) {
var tt = this.texttracks();
this.texttracks().trigger({
type: 'change',
target: tt,
currenttarget: tt,
srcelement: tt
});
};
html5.prototype.handletexttrackadd = function handletexttrackadd(e) {
this.texttracks().addtrack_(e.track);
};
html5.prototype.handletexttrackremove = function handletexttrackremove(e) {
this.texttracks().removetrack_(e.track);
};
/**
* play for html5 tech
*
* @method play
*/
html5.prototype.play = function play() {
this.el_.play();
};
/**
* pause for html5 tech
*
* @method pause
*/
html5.prototype.pause = function pause() {
this.el_.pause();
};
/**
* paused for html5 tech
*
* @return {boolean}
* @method paused
*/
html5.prototype.paused = function paused() {
return this.el_.paused;
};
/**
* get current time
*
* @return {number}
* @method currenttime
*/
html5.prototype.currenttime = function currenttime() {
return this.el_.currenttime;
};
/**
* set current time
*
* @param {number} seconds current time of video
* @method setcurrenttime
*/
html5.prototype.setcurrenttime = function setcurrenttime(seconds) {
try {
this.el_.currenttime = seconds;
} catch (e) {
_utilslogjs2['default'](e, 'video is not ready. (video.js)');
// this.warning(videojs.warnings.videonotready);
}
};
/**
* get duration
*
* @return {number}
* @method duration
*/
html5.prototype.duration = function duration() {
return this.el_.duration || 0;
};
/**
* get a timerange object that represents the intersection
* of the time ranges for which the user agent has all
* relevant media
*
* @return {timerangeobject}
* @method buffered
*/
html5.prototype.buffered = function buffered() {
return this.el_.buffered;
};
/**
* get volume level
*
* @return {number}
* @method volume
*/
html5.prototype.volume = function volume() {
return this.el_.volume;
};
/**
* set volume level
*
* @param {number} percentasdecimal volume percent as a decimal
* @method setvolume
*/
html5.prototype.setvolume = function setvolume(percentasdecimal) {
this.el_.volume = percentasdecimal;
};
/**
* get if muted
*
* @return {boolean}
* @method muted
*/
html5.prototype.muted = function muted() {
return this.el_.muted;
};
/**
* set muted
*
* @param {boolean} if player is to be muted or note
* @method setmuted
*/
html5.prototype.setmuted = function setmuted(muted) {
this.el_.muted = muted;
};
/**
* get player width
*
* @return {number}
* @method width
*/
html5.prototype.width = function width() {
return this.el_.offsetwidth;
};
/**
* get player height
*
* @return {number}
* @method height
*/
html5.prototype.height = function height() {
return this.el_.offsetheight;
};
/**
* get if there is fullscreen support
*
* @return {boolean}
* @method supportsfullscreen
*/
html5.prototype.supportsfullscreen = function supportsfullscreen() {
if (typeof this.el_.webkitenterfullscreen === 'function') {
var useragent = _globalwindow2['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 to enter fullscreen
*
* @method enterfullscreen
*/
html5.prototype.enterfullscreen = function enterfullscreen() {
var video = this.el_;
if ('webkitdisplayingfullscreen' in video) {
this.one('webkitbeginfullscreen', function () {
this.one('webkitendfullscreen', function () {
this.trigger('fullscreenchange', { isfullscreen: false });
});
this.trigger('fullscreenchange', { isfullscreen: true });
});
}
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 to exit fullscreen
*
* @method exitfullscreen
*/
html5.prototype.exitfullscreen = function exitfullscreen() {
this.el_.webkitexitfullscreen();
};
/**
* get/set video
*
* @param {object=} src source object
* @return {object}
* @method src
*/
html5.prototype.src = function src(_src) {
if (_src === undefined) {
return this.el_.src;
} else {
// setting src through `src` instead of `setsrc` will be deprecated
this.setsrc(_src);
}
};
/**
* set video
*
* @param {object} src source object
* @deprecated
* @method setsrc
*/
html5.prototype.setsrc = function setsrc(src) {
this.el_.src = src;
};
/**
* load media into player
*
* @method load
*/
html5.prototype.load = function load() {
this.el_.load();
};
/**
* reset the tech. removes all sources and calls `load`.
*
* @method reset
*/
html5.prototype.reset = function reset() {
html5.resetmediaelement(this.el_);
};
/**
* get current source
*
* @return {object}
* @method currentsrc
*/
html5.prototype.currentsrc = function currentsrc() {
if (this.currentsource_) {
return this.currentsource_.src;
} else {
return this.el_.currentsrc;
}
};
/**
* get poster
*
* @return {string}
* @method poster
*/
html5.prototype.poster = function poster() {
return this.el_.poster;
};
/**
* set poster
*
* @param {string} val url to poster image
* @method
*/
html5.prototype.setposter = function setposter(val) {
this.el_.poster = val;
};
/**
* get preload attribute
*
* @return {string}
* @method preload
*/
html5.prototype.preload = function preload() {
return this.el_.preload;
};
/**
* set preload attribute
*
* @param {string} val value for preload attribute
* @method setpreload
*/
html5.prototype.setpreload = function setpreload(val) {
this.el_.preload = val;
};
/**
* get autoplay attribute
*
* @return {string}
* @method autoplay
*/
html5.prototype.autoplay = function autoplay() {
return this.el_.autoplay;
};
/**
* set autoplay attribute
*
* @param {string} val value for preload attribute
* @method setautoplay
*/
html5.prototype.setautoplay = function setautoplay(val) {
this.el_.autoplay = val;
};
/**
* get controls attribute
*
* @return {string}
* @method controls
*/
html5.prototype.controls = function controls() {
return this.el_.controls;
};
/**
* set controls attribute
*
* @param {string} val value for controls attribute
* @method setcontrols
*/
html5.prototype.setcontrols = function setcontrols(val) {
this.el_.controls = !!val;
};
/**
* get loop attribute
*
* @return {string}
* @method loop
*/
html5.prototype.loop = function loop() {
return this.el_.loop;
};
/**
* set loop attribute
*
* @param {string} val value for loop attribute
* @method setloop
*/
html5.prototype.setloop = function setloop(val) {
this.el_.loop = val;
};
/**
* get error value
*
* @return {string}
* @method error
*/
html5.prototype.error = function error() {
return this.el_.error;
};
/**
* get whether or not the player is in the "seeking" state
*
* @return {boolean}
* @method seeking
*/
html5.prototype.seeking = function seeking() {
return this.el_.seeking;
};
/**
* get a timeranges object that represents the
* ranges of the media resource to which it is possible
* for the user agent to seek.
*
* @return {timerangeobject}
* @method seekable
*/
html5.prototype.seekable = function seekable() {
return this.el_.seekable;
};
/**
* get if video ended
*
* @return {boolean}
* @method ended
*/
html5.prototype.ended = function ended() {
return this.el_.ended;
};
/**
* get the value of the muted content attribute
* this attribute has no dynamic effect, it only
* controls the default state of the element
*
* @return {boolean}
* @method defaultmuted
*/
html5.prototype.defaultmuted = function defaultmuted() {
return this.el_.defaultmuted;
};
/**
* get desired speed at which the media resource is to play
*
* @return {number}
* @method playbackrate
*/
html5.prototype.playbackrate = function playbackrate() {
return this.el_.playbackrate;
};
/**
* returns a timeranges object that represents the ranges of the
* media resource that the user agent has played.
* @return {timerangeobject} the range of points on the media
* timeline that has been reached through normal playback
* @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-played
*/
html5.prototype.played = function played() {
return this.el_.played;
};
/**
* set desired speed at which the media resource is to play
*
* @param {number} val speed at which the media resource is to play
* @method setplaybackrate
*/
html5.prototype.setplaybackrate = function setplaybackrate(val) {
this.el_.playbackrate = val;
};
/**
* get the current state of network activity for the element, from
* the list below
* network_empty (numeric value 0)
* network_idle (numeric value 1)
* network_loading (numeric value 2)
* network_no_source (numeric value 3)
*
* @return {number}
* @method networkstate
*/
html5.prototype.networkstate = function networkstate() {
return this.el_.networkstate;
};
/**
* get a value that expresses the current state of the element
* with respect to rendering the current playback position, from
* the codes in the list below
* have_nothing (numeric value 0)
* have_metadata (numeric value 1)
* have_current_data (numeric value 2)
* have_future_data (numeric value 3)
* have_enough_data (numeric value 4)
*
* @return {number}
* @method readystate
*/
html5.prototype.readystate = function readystate() {
return this.el_.readystate;
};
/**
* get width of video
*
* @return {number}
* @method videowidth
*/
html5.prototype.videowidth = function videowidth() {
return this.el_.videowidth;
};
/**
* get height of video
*
* @return {number}
* @method videoheight
*/
html5.prototype.videoheight = function videoheight() {
return this.el_.videoheight;
};
/**
* get text tracks
*
* @return {texttracklist}
* @method texttracks
*/
html5.prototype.texttracks = function texttracks() {
return _tech.prototype.texttracks.call(this);
};
/**
* creates and returns a text track object
*
* @param {string} kind text track kind (subtitles, captions, descriptions
* chapters and metadata)
* @param {string=} label label to identify the text track
* @param {string=} language two letter language abbreviation
* @return {texttrackobject}
* @method addtexttrack
*/
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 a remote text track object and returns a html track element
*
* @param {object} options the object should contain values for
* kind, language, label and src (location of the webvtt file)
* @return {htmltrackelement}
* @method addremotetexttrack
*/
html5.prototype.addremotetexttrack = function addremotetexttrack() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
if (!this['featuresnativetexttracks']) {
return _tech.prototype.addremotetexttrack.call(this, options);
}
var htmltrackelement = _globaldocument2['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;
}
this.el().appendchild(htmltrackelement);
// store htmltrackelement and texttrack to remote list
this.remotetexttrackels().addtrackelement_(htmltrackelement);
this.remotetexttracks().addtrack_(htmltrackelement.track);
return htmltrackelement;
};
/**
* remove remote text track from texttracklist object
*
* @param {texttrackobject} track texttrack object to remove
* @method removeremotetexttrack
*/
html5.prototype.removeremotetexttrack = function removeremotetexttrack(track) {
if (!this['featuresnativetexttracks']) {
return _tech.prototype.removeremotetexttrack.call(this, track);
}
var tracks = undefined,
i = undefined;
var trackelement = this.remotetexttrackels().gettrackelementbytrack_(track);
// remove htmltrackelement and texttrack from remote list
this.remotetexttrackels().removetrackelement_(trackelement);
this.remotetexttracks().removetrack_(track);
tracks = this.$$('track');
i = tracks.length;
while (i--) {
if (track === tracks[i] || track === tracks[i].track) {
this.el().removechild(tracks[i]);
}
}
};
return html5;
})(_techjs2['default']);
html5.test_vid = _globaldocument2['default'].createelement('video');
var track = _globaldocument2['default'].createelement('track');
track.kind = 'captions';
track.srclang = 'en';
track.label = 'english';
html5.test_vid.appendchild(track);
/*
* check if html5 video is supported by this browser/device
*
* @return {boolean}
*/
html5.issupported = function () {
// ie9 with no media player is a liar! (#984)
try {
html5.test_vid['volume'] = 0.5;
} catch (e) {
return false;
}
return !!html5.test_vid.canplaytype;
};
// add source handler pattern functions to this tech
_techjs2['default'].withsourcehandlers(html5);
/*
* the default native source handler.
* this simply passes the source to the video element. nothing fancy.
*
* @param {object} source the source object
* @param {html5} tech the instance of the html5 tech
*/
html5.nativesourcehandler = {};
/*
* check if the video element can play the given videotype
*
* @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 video element can handle the source natively
*
* @param {object} source the source object
* @return {string} 'probably', 'maybe', or '' (empty string)
*/
html5.nativesourcehandler.canhandlesource = function (source) {
var match, ext;
// if a type was provided we should rely on that
if (source.type) {
return html5.nativesourcehandler.canplaytype(source.type);
} else if (source.src) {
// if no type, fall back to checking 'video/[extension]'
ext = url.getfileextension(source.src);
return html5.nativesourcehandler.canplaytype('video/' + ext);
}
return '';
};
/*
* pass the source to the video element
* adaptive source handlers will have more complicated workflows before passing
* video data to the video element
*
* @param {object} source the source object
* @param {html5} tech the instance of the html5 tech
*/
html5.nativesourcehandler.handlesource = function (source, tech) {
tech.setsrc(source.src);
};
/*
* clean up the source handler when disposing the player or switching sources..
* (no cleanup is needed when supporting the format natively)
*/
html5.nativesourcehandler.dispose = function () {};
// register the native source handler
html5.registersourcehandler(html5.nativesourcehandler);
/*
* check if the volume can be changed in this browser/device.
* volume cannot be changed in a lot of mobile devices.
* specifically, it can't be changed from 1 on ios.
*
* @return {boolean}
*/
html5.cancontrolvolume = function () {
var volume = html5.test_vid.volume;
html5.test_vid.volume = volume / 2 + 0.1;
return volume !== html5.test_vid.volume;
};
/*
* check if playbackrate is supported in this browser/device.
*
* @return {number} [description]
*/
html5.cancontrolplaybackrate = function () {
var playbackrate = html5.test_vid.playbackrate;
html5.test_vid.playbackrate = playbackrate / 2 + 0.1;
return playbackrate !== html5.test_vid.playbackrate;
};
/*
* check to see if native text tracks are supported by this browser/device
*
* @return {boolean}
*/
html5.supportsnativetexttracks = function () {
var supportstexttracks;
// figure out native text track support
// if mode is a number, we cannot change it because it'll disappear from view.
// browsers with numeric modes include ie10 and older (<=2013) samsung android models.
// firefox isn't playing nice either with modifying the mode
// todo: investigate firefox: https://github.com/videojs/video.js/issues/1862
supportstexttracks = !!html5.test_vid.texttracks;
if (supportstexttracks && html5.test_vid.texttracks.length > 0) {
supportstexttracks = typeof html5.test_vid.texttracks[0]['mode'] !== 'number';
}
if (supportstexttracks && browser.is_firefox) {
supportstexttracks = false;
}
if (supportstexttracks && !('onremovetrack' in html5.test_vid.texttracks)) {
supportstexttracks = false;
}
return supportstexttracks;
};
/**
* 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'];
/*
* set the tech's volume control support status
*
* @type {boolean}
*/
html5.prototype['featuresvolumecontrol'] = html5.cancontrolvolume();
/*
* set the tech's playbackrate support status
*
* @type {boolean}
*/
html5.prototype['featuresplaybackrate'] = html5.cancontrolplaybackrate();
/*
* set the tech's status on moving the video element.
* in ios, if you move a video element in the dom, it breaks video playback.
*
* @type {boolean}
*/
html5.prototype['movingmediaelementindom'] = !browser.is_ios;
/*
* set the the tech's fullscreen resize support status.
* html video is able to automatically resize when going to fullscreen.
* (no longer appears to be used. can probably be removed.)
*/
html5.prototype['featuresfullscreenresize'] = true;
/*
* set the tech's progress event support status
* (this disables the manual progress events of the tech)
*/
html5.prototype['featuresprogressevents'] = true;
/*
* sets the tech's status on native text track support
*
* @type {boolean}
*/
html5.prototype['featuresnativetexttracks'] = html5.supportsnativetexttracks();
// html5 feature detection and device fixes --------------------------------- //
var canplaytype = undefined;
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) {
if (!canplaytype) {
canplaytype = html5.test_vid.constructor.prototype.canplaytype;
}
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
if (browser.is_old_android) {
if (!canplaytype) {
canplaytype = html5.test_vid.constructor.prototype.canplaytype;
}
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;
canplaytype = null;
return r;
};
// by default, patch the video 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) {}
})();
}
};
_component2['default'].registercomponent('html5', html5);
_techjs2['default'].registertech('html5', html5);
exports['default'] = html5;
module.exports = exports['default'];
},{"../component":67,"../utils/browser.js":129,"../utils/dom.js":132,"../utils/fn.js":134,"../utils/log.js":137,"../utils/merge-options.js":138,"../utils/url.js":142,"./tech.js":119,"global/document":1,"global/window":2,"object.assign":45}],118:[function(_dereq_,module,exports){
/**
* @file loader.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _componentjs = _dereq_('../component.js');
var _componentjs2 = _interoprequiredefault(_componentjs);
var _techjs = _dereq_('./tech.js');
var _techjs2 = _interoprequiredefault(_techjs);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _utilstotitlecasejs = _dereq_('../utils/to-title-case.js');
var _utilstotitlecasejs2 = _interoprequiredefault(_utilstotitlecasejs);
/**
* the media loader is the component that decides which playback technology to load
* when the player is initialized.
*
* @param {object} player main player
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends component
* @class medialoader
*/
var medialoader = (function (_component) {
_inherits(medialoader, _component);
function medialoader(player, options, ready) {
_classcallcheck(this, medialoader);
_component.call(this, player, options, ready);
// if there are no sources when the player is initialized,
// load the first supported playback technology.
if (!options.playeroptions['sources'] || options.playeroptions['sources'].length === 0) {
for (var i = 0, j = options.playeroptions['techorder']; i < j.length; i++) {
var techname = _utilstotitlecasejs2['default'](j[i]);
var tech = _techjs2['default'].gettech(techname);
// support old behavior of techs being registered as components.
// remove once that deprecated behavior is removed.
if (!techname) {
tech = _componentjs2['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 medialoader;
})(_componentjs2['default']);
_componentjs2['default'].registercomponent('medialoader', medialoader);
exports['default'] = medialoader;
module.exports = exports['default'];
},{"../component.js":67,"../utils/to-title-case.js":141,"./tech.js":119,"global/window":2}],119:[function(_dereq_,module,exports){
/**
* @file tech.js
* media technology controller - base class for media playback
* technology controllers like flash and html5
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _component = _dereq_('../component');
var _component2 = _interoprequiredefault(_component);
var _trackshtmltrackelement = _dereq_('../tracks/html-track-element');
var _trackshtmltrackelement2 = _interoprequiredefault(_trackshtmltrackelement);
var _trackshtmltrackelementlist = _dereq_('../tracks/html-track-element-list');
var _trackshtmltrackelementlist2 = _interoprequiredefault(_trackshtmltrackelementlist);
var _utilsmergeoptionsjs = _dereq_('../utils/merge-options.js');
var _utilsmergeoptionsjs2 = _interoprequiredefault(_utilsmergeoptionsjs);
var _trackstexttrack = _dereq_('../tracks/text-track');
var _trackstexttrack2 = _interoprequiredefault(_trackstexttrack);
var _trackstexttracklist = _dereq_('../tracks/text-track-list');
var _trackstexttracklist2 = _interoprequiredefault(_trackstexttracklist);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilslogjs = _dereq_('../utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _utilstimerangesjs = _dereq_('../utils/time-ranges.js');
var _utilsbufferjs = _dereq_('../utils/buffer.js');
var _mediaerrorjs = _dereq_('../media-error.js');
var _mediaerrorjs2 = _interoprequiredefault(_mediaerrorjs);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
/**
* base class for media (html5 video, flash) controllers
*
* @param {object=} options options object
* @param {function=} ready ready callback function
* @extends component
* @class tech
*/
var tech = (function (_component) {
_inherits(tech, _component);
function tech() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var ready = arguments.length <= 1 || arguments[1] === undefined ? function () {} : arguments[1];
_classcallcheck(this, tech);
// we don't want the tech to report user activity automatically.
// this is done manually in addcontrolslisteners
options.reporttouchactivity = false;
_component.call(this, null, options, ready);
// keep track of whether the current source has played at all to
// implement a very limited played()
this.hasstarted_ = false;
this.on('playing', function () {
this.hasstarted_ = true;
});
this.on('loadstart', function () {
this.hasstarted_ = false;
});
this.texttracks_ = options.texttracks;
// 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();
}
if (options.nativecaptions === false || options.nativetexttracks === false) {
this.featuresnativetexttracks = false;
}
if (!this.featuresnativetexttracks) {
this.on('ready', this.emulatetexttracks);
}
this.inittexttracklisteners();
// turn on component tap events
this.emittapevents();
}
/*
* list of associated text tracks
*
* @type {array}
* @private
*/
/* fallbacks for unsupported event types
================================================================================ */
// manually trigger progress events based on changes to the buffered amount
// many flash players and older html5 browsers don't send progress or progress-like events
/**
* turn on progress events
*
* @method manualprogresson
*/
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 progress events
*
* @method manualprogressoff
*/
tech.prototype.manualprogressoff = function manualprogressoff() {
this.manualprogress = false;
this.stoptrackingprogress();
this.off('durationchange', this.ondurationchange);
};
/**
* track progress
*
* @method trackprogress
*/
tech.prototype.trackprogress = function trackprogress() {
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) {
this.trigger('progress');
}
this.bufferedpercent_ = numbufferedpercent;
if (numbufferedpercent === 1) {
this.stoptrackingprogress();
}
}), 500);
};
/**
* update duration
*
* @method ondurationchange
*/
tech.prototype.ondurationchange = function ondurationchange() {
this.duration_ = this.duration();
};
/**
* create and get timerange object for buffering
*
* @return {timerangeobject}
* @method buffered
*/
tech.prototype.buffered = function buffered() {
return _utilstimerangesjs.createtimerange(0, 0);
};
/**
* get buffered percent
*
* @return {number}
* @method bufferedpercent
*/
tech.prototype.bufferedpercent = function bufferedpercent() {
return _utilsbufferjs.bufferedpercent(this.buffered(), this.duration_);
};
/**
* stops tracking progress by clearing progress interval
*
* @method stoptrackingprogress
*/
tech.prototype.stoptrackingprogress = function stoptrackingprogress() {
this.clearinterval(this.progressinterval);
};
/*! time tracking -------------------------------------------------------------- */
/**
* set event listeners for on play and pause and tracking current time
*
* @method manualtimeupdateson
*/
tech.prototype.manualtimeupdateson = function manualtimeupdateson() {
this.manualtimeupdates = true;
this.on('play', this.trackcurrenttime);
this.on('pause', this.stoptrackingcurrenttime);
};
/**
* remove event listeners for on play and pause and tracking current time
*
* @method manualtimeupdatesoff
*/
tech.prototype.manualtimeupdatesoff = function manualtimeupdatesoff() {
this.manualtimeupdates = false;
this.stoptrackingcurrenttime();
this.off('play', this.trackcurrenttime);
this.off('pause', this.stoptrackingcurrenttime);
};
/**
* tracks current time
*
* @method trackcurrenttime
*/
tech.prototype.trackcurrenttime = function trackcurrenttime() {
if (this.currenttimeinterval) {
this.stoptrackingcurrenttime();
}
this.currenttimeinterval = this.setinterval(function () {
this.trigger({ type: 'timeupdate', target: this, manuallytriggered: true });
}, 250); // 42 = 24 fps // 250 is what webkit uses // ff uses 15
};
/**
* turn off play progress tracking (when paused or dragging)
*
* @method stoptrackingcurrenttime
*/
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 any manual progress or timeupdate tracking
*
* @method dispose
*/
tech.prototype.dispose = function dispose() {
// clear out text tracks because we can't reuse them between techs
var texttracks = this.texttracks();
if (texttracks) {
var i = texttracks.length;
while (i--) {
this.removeremotetexttrack(texttracks[i]);
}
}
// turn off any manual progress or timeupdate tracking
if (this.manualprogress) {
this.manualprogressoff();
}
if (this.manualtimeupdates) {
this.manualtimeupdatesoff();
}
_component.prototype.dispose.call(this);
};
/**
* reset the tech. removes all sources and resets readystate.
*
* @method reset
*/
tech.prototype.reset = function reset() {};
/**
* when invoked without an argument, returns a mediaerror object
* representing the current error state of the player or null if
* there is no error. when invoked with an argument, set the current
* error state of the player.
* @param {mediaerror=} err optional an error object
* @return {mediaerror} the current error object or null
* @method error
*/
tech.prototype.error = function error(err) {
if (err !== undefined) {
if (err instanceof _mediaerrorjs2['default']) {
this.error_ = err;
} else {
this.error_ = new _mediaerrorjs2['default'](err);
}
this.trigger('error');
}
return this.error_;
};
/**
* return the time ranges that have been played through for the
* current source. this implementation is incomplete. it does not
* track the played time ranges, only whether the source has played
* at all or not.
* @return {timerangeobject} a single time range if this video has
* played or an empty set of ranges if not.
* @method played
*/
tech.prototype.played = function played() {
if (this.hasstarted_) {
return _utilstimerangesjs.createtimerange(0, 0);
}
return _utilstimerangesjs.createtimerange();
};
/**
* set current time
*
* @method setcurrenttime
*/
tech.prototype.setcurrenttime = function setcurrenttime() {
// improve the accuracy of manual timeupdates
if (this.manualtimeupdates) {
this.trigger({ type: 'timeupdate', target: this, manuallytriggered: true });
}
};
/**
* initialize texttrack listeners
*
* @method inittexttracklisteners
*/
tech.prototype.inittexttracklisteners = function inittexttracklisteners() {
var texttracklistchanges = fn.bind(this, function () {
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);
}));
};
/**
* emulate texttracks
*
* @method emulatetexttracks
*/
tech.prototype.emulatetexttracks = function emulatetexttracks() {
var _this = this;
var tracks = this.texttracks();
if (!tracks) {
return;
}
if (!_globalwindow2['default']['webvtt'] && this.el().parentnode != null) {
(function () {
var script = _globaldocument2['default'].createelement('script');
script.src = _this.options_['vtt.js'] || 'https://cdn.rawgit.com/gkatsev/vtt.js/vjs-v0.12.1/dist/vtt.min.js';
script.onload = function () {
_this.trigger('vttjsloaded');
};
script.onerror = function () {
_this.trigger('vttjserror');
};
_this.on('dispose', function () {
script.onload = null;
script.onerror = null;
});
_this.el().parentnode.appendchild(script);
_globalwindow2['default']['webvtt'] = true;
})();
}
var updatedisplay = function updatedisplay() {
return _this.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);
this.on('dispose', function () {
tracks.removeeventlistener('change', texttrackschanges);
});
};
/*
* provide default methods for text tracks.
*
* html5 tech overrides these.
*/
/**
* get texttracks
*
* @returns {texttracklist}
* @method texttracks
*/
tech.prototype.texttracks = function texttracks() {
this.texttracks_ = this.texttracks_ || new _trackstexttracklist2['default']();
return this.texttracks_;
};
/**
* get remote texttracks
*
* @returns {texttracklist}
* @method remotetexttracks
*/
tech.prototype.remotetexttracks = function remotetexttracks() {
this.remotetexttracks_ = this.remotetexttracks_ || new _trackstexttracklist2['default']();
return this.remotetexttracks_;
};
/**
* get remote htmltrackelements
*
* @returns {htmltrackelementlist}
* @method remotetexttrackels
*/
tech.prototype.remotetexttrackels = function remotetexttrackels() {
this.remotetexttrackels_ = this.remotetexttrackels_ || new _trackshtmltrackelementlist2['default']();
return this.remotetexttrackels_;
};
/**
* creates and returns a remote text track object
*
* @param {string} kind text track kind (subtitles, captions, descriptions
* chapters and metadata)
* @param {string=} label label to identify the text track
* @param {string=} language two letter language abbreviation
* @return {texttrackobject}
* @method addtexttrack
*/
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);
};
/**
* creates a remote text track object and returns a emulated html track element
*
* @param {object} options the object should contain values for
* kind, language, label and src (location of the webvtt file)
* @return {htmltrackelement}
* @method addremotetexttrack
*/
tech.prototype.addremotetexttrack = function addremotetexttrack(options) {
var track = _utilsmergeoptionsjs2['default'](options, {
tech: this
});
var htmltrackelement = new _trackshtmltrackelement2['default'](track);
// store htmltrackelement and texttrack to remote list
this.remotetexttrackels().addtrackelement_(htmltrackelement);
this.remotetexttracks().addtrack_(htmltrackelement.track);
// must come after remotetexttracks()
this.texttracks().addtrack_(htmltrackelement.track);
return htmltrackelement;
};
/**
* remove remote texttrack
*
* @param {texttrackobject} track texttrack to remove
* @method removeremotetexttrack
*/
tech.prototype.removeremotetexttrack = function removeremotetexttrack(track) {
this.texttracks().removetrack_(track);
var trackelement = this.remotetexttrackels().gettrackelementbytrack_(track);
// remove htmltrackelement and texttrack from remote list
this.remotetexttrackels().removetrackelement_(trackelement);
this.remotetexttracks().removetrack_(track);
};
/**
* provide a default setposter method for techs
* poster support for techs should be optional, so we don't want techs to
* break if they don't have a way to set a poster.
*
* @method setposter
*/
tech.prototype.setposter = function setposter() {};
/*
* check if the tech can support the given type
*
* the base tech does not support any type, but source handlers might
* overwrite this.
*
* @param {string} type the mimetype to check
* @return {string} 'probably', 'maybe', or '' (empty string)
*/
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 an item to check
* @return {boolean} whether it is a tech or not
*/
tech.istech = function istech(component) {
return component.prototype instanceof tech || component instanceof tech || component === tech;
};
/**
* registers a tech
*
* @param {string} name name of the tech to register
* @param {object} tech the tech to register
* @static
* @method registercomponent
*/
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;
};
/**
* gets a component by name
*
* @param {string} name name of the component to get
* @return {component}
* @static
* @method getcomponent
*/
tech.gettech = function gettech(name) {
if (tech.techs_ && tech.techs_[name]) {
return tech.techs_[name];
}
if (_globalwindow2['default'] && _globalwindow2['default'].videojs && _globalwindow2['default'].videojs[name]) {
_utilslogjs2['default'].warn('the ' + name + ' tech was added to the videojs object when it should be registered using videojs.registertech(name, tech)');
return _globalwindow2['default'].videojs[name];
}
};
return tech;
})(_component2['default']);
tech.prototype.texttracks_;
var createtrackhelper = 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 _trackstexttrack2['default'](options);
tracks.addtrack_(track);
return track;
};
tech.prototype.featuresvolumecontrol = true;
// resizing plugins using request fullscreen reloads the plugin
tech.prototype.featuresfullscreenresize = false;
tech.prototype.featuresplaybackrate = false;
// optional events that we can manually mimic with timers
// currently not triggered by video-js-swf
tech.prototype.featuresprogressevents = false;
tech.prototype.featurestimeupdateevents = false;
tech.prototype.featuresnativetexttracks = false;
/*
* a functional mixin for techs that want to use the source handler pattern.
*
* ##### example:
*
* tech.withsourcehandlers.call(mytech);
*
*/
tech.withsourcehandlers = function (_tech) {
/*
* register a source handler
* source handlers are scripts for handling specific formats.
* the source handler pattern is used for adaptive formats (hls, dash) that
* manually load video data and feed it into a source buffer (media source extensions)
* @param {function} handler the source handler
* @param {boolean} first register it before any existing handlers
*/
_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
* @param {string} type the mimetype to check
* @return {string} 'probably', 'maybe', or '' (empty string)
*/
_tech.canplaytype = function (type) {
var handlers = _tech.sourcehandlers || [];
var can = undefined;
for (var i = 0; i < handlers.length; i++) {
can = handlers[i].canplaytype(type);
if (can) {
return can;
}
}
return '';
};
/*
* return the first source handler that supports the source
* todo: answer question: should 'probably' be prioritized over 'maybe'
* @param {object} source the source object
* @returns {object} the first source handler that supports the source
* @returns {null} null if no source handler is found
*/
_tech.selectsourcehandler = function (source) {
var handlers = _tech.sourcehandlers || [];
var can = undefined;
for (var i = 0; i < handlers.length; i++) {
can = handlers[i].canhandlesource(source);
if (can) {
return handlers[i];
}
}
return null;
};
/*
* check if the tech can support the given source
* @param {object} srcobj the source object
* @return {string} 'probably', 'maybe', or '' (empty string)
*/
_tech.canplaysource = function (srcobj) {
var sh = _tech.selectsourcehandler(srcobj);
if (sh) {
return sh.canhandlesource(srcobj);
}
return '';
};
/*
* when using a source handler, prefer its implementation of
* any function normally provided by the tech.
*/
var deferrable = ['seekable', '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 {object} source a source object with src and type keys
* @return {tech} self
*/
_tech.prototype.setsource = function (source) {
var sh = _tech.selectsourcehandler(source);
if (!sh) {
// fall back to a native source hander when unsupported sources are
// deliberately set
if (_tech.nativesourcehandler) {
sh = _tech.nativesourcehandler;
} else {
_utilslogjs2['default'].error('no source hander found for the current source.');
}
}
// dispose any existing source handler
this.disposesourcehandler();
this.off('dispose', this.disposesourcehandler);
this.currentsource_ = source;
this.sourcehandler_ = sh.handlesource(source, this);
this.on('dispose', this.disposesourcehandler);
return this;
};
/*
* clean up any existing source handler
*/
_tech.prototype.disposesourcehandler = function () {
if (this.sourcehandler_ && this.sourcehandler_.dispose) {
this.sourcehandler_.dispose();
}
};
};
_component2['default'].registercomponent('tech', tech);
// old name for tech
_component2['default'].registercomponent('mediatechcontroller', tech);
tech.registertech('tech', tech);
exports['default'] = tech;
module.exports = exports['default'];
},{"../component":67,"../media-error.js":103,"../tracks/html-track-element":121,"../tracks/html-track-element-list":120,"../tracks/text-track":128,"../tracks/text-track-list":126,"../utils/buffer.js":130,"../utils/fn.js":134,"../utils/log.js":137,"../utils/merge-options.js":138,"../utils/time-ranges.js":140,"global/document":1,"global/window":2}],120:[function(_dereq_,module,exports){
/**
* @file html-track-element-list.js
*/
'use strict';
exports.__esmodule = true;
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'); } }
var _utilsbrowserjs = _dereq_('../utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var htmltrackelementlist = (function () {
function htmltrackelementlist() {
var trackelements = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
_classcallcheck(this, htmltrackelementlist);
var list = this;
if (browser.is_ie8) {
list = _globaldocument2['default'].createelement('custom');
for (var prop in htmltrackelementlist.prototype) {
if (prop !== 'constructor') {
list[prop] = htmltrackelementlist.prototype[prop];
}
}
}
list.trackelements_ = [];
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;
}
}
htmltrackelementlist.prototype.addtrackelement_ = function addtrackelement_(trackelement) {
this.trackelements_.push(trackelement);
};
htmltrackelementlist.prototype.gettrackelementbytrack_ = function gettrackelementbytrack_(track) {
var trackelement_ = undefined;
for (var i = 0, _length2 = this.trackelements_.length; i < _length2; i++) {
if (track === this.trackelements_[i].track) {
trackelement_ = this.trackelements_[i];
break;
}
}
return trackelement_;
};
htmltrackelementlist.prototype.removetrackelement_ = function removetrackelement_(trackelement) {
for (var i = 0, _length3 = this.trackelements_.length; i < _length3; i++) {
if (trackelement === this.trackelements_[i]) {
this.trackelements_.splice(i, 1);
break;
}
}
};
return htmltrackelementlist;
})();
exports['default'] = htmltrackelementlist;
module.exports = exports['default'];
},{"../utils/browser.js":129,"global/document":1}],121:[function(_dereq_,module,exports){
/**
* @file html-track-element.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _utilsbrowserjs = _dereq_('../utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _eventtarget = _dereq_('../event-target');
var _eventtarget2 = _interoprequiredefault(_eventtarget);
var _trackstexttrack = _dereq_('../tracks/text-track');
var _trackstexttrack2 = _interoprequiredefault(_trackstexttrack);
var none = 0;
var loading = 1;
var loaded = 2;
var error = 3;
/**
* https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement
*
* interface htmltrackelement : htmlelement {
* attribute domstring kind;
* attribute domstring src;
* attribute domstring srclang;
* attribute domstring label;
* attribute boolean default;
*
* const unsigned short none = 0;
* const unsigned short loading = 1;
* const unsigned short loaded = 2;
* const unsigned short error = 3;
* readonly attribute unsigned short readystate;
*
* readonly attribute texttrack track;
* };
*
* @param {object} options texttrack configuration
* @class htmltrackelement
*/
var htmltrackelement = (function (_eventtarget) {
_inherits(htmltrackelement, _eventtarget);
function htmltrackelement() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
_classcallcheck(this, htmltrackelement);
_eventtarget.call(this);
var readystate = undefined,
trackelement = this;
if (browser.is_ie8) {
trackelement = _globaldocument2['default'].createelement('custom');
for (var prop in htmltrackelement.prototype) {
if (prop !== 'constructor') {
trackelement[prop] = htmltrackelement.prototype[prop];
}
}
}
var track = new _trackstexttrack2['default'](options);
trackelement.kind = track.kind;
trackelement.src = track.src;
trackelement.srclang = track.language;
trackelement.label = track.label;
trackelement['default'] = track['default'];
object.defineproperty(trackelement, 'readystate', {
get: function get() {
return readystate;
}
});
object.defineproperty(trackelement, 'track', {
get: function get() {
return track;
}
});
readystate = none;
track.addeventlistener('loadeddata', function () {
readystate = loaded;
trackelement.trigger({
type: 'load',
target: trackelement
});
});
if (browser.is_ie8) {
return trackelement;
}
}
return htmltrackelement;
})(_eventtarget2['default']);
htmltrackelement.prototype.allowedevents_ = {
load: 'load'
};
htmltrackelement.none = none;
htmltrackelement.loading = loading;
htmltrackelement.loaded = loaded;
htmltrackelement.error = error;
exports['default'] = htmltrackelement;
module.exports = exports['default'];
},{"../event-target":99,"../tracks/text-track":128,"../utils/browser.js":129,"global/document":1}],122:[function(_dereq_,module,exports){
/**
* @file text-track-cue-list.js
*/
'use strict';
exports.__esmodule = true;
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'); } }
var _utilsbrowserjs = _dereq_('../utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
/**
* a list of text track cues as defined in:
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist
*
* interface texttrackcuelist {
* readonly attribute unsigned long length;
* getter texttrackcue (unsigned long index);
* texttrackcue? getcuebyid(domstring id);
* };
*
* @param {array} cues a list of cues to be initialized with
* @class texttrackcuelist
*/
var texttrackcuelist = (function () {
function texttrackcuelist(cues) {
_classcallcheck(this, texttrackcuelist);
var list = this;
if (browser.is_ie8) {
list = _globaldocument2['default'].createelement('custom');
for (var prop in texttrackcuelist.prototype) {
if (prop !== 'constructor') {
list[prop] = texttrackcuelist.prototype[prop];
}
}
}
texttrackcuelist.prototype.setcues_.call(list, cues);
object.defineproperty(list, 'length', {
get: function get() {
return this.length_;
}
});
if (browser.is_ie8) {
return list;
}
}
/**
* a setter for cues in this list
*
* @param {array} cues an array of cues
* @method setcues_
* @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 cue that is currently in the cue list by id
*
* @param {string} id
* @method getcuebyid
* @return {object} a single cue
*/
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;
module.exports = exports['default'];
},{"../utils/browser.js":129,"global/document":1}],123:[function(_dereq_,module,exports){
/**
* @file text-track-display.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _component = _dereq_('../component');
var _component2 = _interoprequiredefault(_component);
var _menumenujs = _dereq_('../menu/menu.js');
var _menumenujs2 = _interoprequiredefault(_menumenujs);
var _menumenuitemjs = _dereq_('../menu/menu-item.js');
var _menumenuitemjs2 = _interoprequiredefault(_menumenuitemjs);
var _menumenubuttonjs = _dereq_('../menu/menu-button.js');
var _menumenubuttonjs2 = _interoprequiredefault(_menumenubuttonjs);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
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'
};
/**
* the component for displaying text track cues
*
* @param {object} player main player
* @param {object=} options object of option names and values
* @param {function=} ready ready callback function
* @extends component
* @class texttrackdisplay
*/
var texttrackdisplay = (function (_component) {
_inherits(texttrackdisplay, _component);
function texttrackdisplay(player, options, ready) {
_classcallcheck(this, texttrackdisplay);
_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++) {
var track = tracks[i];
this.player_.addremotetexttrack(track);
}
}));
}
/**
* add cue html to display
*
* @param {number} color hex number for color, like #f0e
* @param {number} opacity value for opacity,0.0 - 1.0
* @return {rgbacolor} in the form 'rgba(255, 0, 0, 0.3)'
* @method constructcolor
*/
/**
* toggle display texttracks
*
* @method toggledisplay
*/
texttrackdisplay.prototype.toggledisplay = function toggledisplay() {
if (this.player_.tech_ && this.player_.tech_['featuresnativetexttracks']) {
this.hide();
} else {
this.show();
}
};
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
texttrackdisplay.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-text-track-display'
});
};
/**
* clear display texttracks
*
* @method cleardisplay
*/
texttrackdisplay.prototype.cleardisplay = function cleardisplay() {
if (typeof _globalwindow2['default']['webvtt'] === 'function') {
_globalwindow2['default']['webvtt']['processcues'](_globalwindow2['default'], [], this.el_);
}
};
/**
* update display texttracks
*
* @method updatedisplay
*/
texttrackdisplay.prototype.updatedisplay = function updatedisplay() {
var tracks = this.player_.texttracks();
this.cleardisplay();
if (!tracks) {
return;
}
for (var i = 0; i < tracks.length; i++) {
var track = tracks[i];
if (track['mode'] === 'showing') {
this.updatefortrack(track);
}
}
};
/**
* add texttrack to texttrack list
*
* @param {texttrackobject} track texttrack object to be added to list
* @method updatefortrack
*/
texttrackdisplay.prototype.updatefortrack = function updatefortrack(track) {
if (typeof _globalwindow2['default']['webvtt'] !== 'function' || !track['activecues']) {
return;
}
var overrides = this.player_['texttracksettings'].getvalues();
var cues = [];
for (var _i = 0; _i < track['activecues'].length; _i++) {
cues.push(track['activecues'][_i]);
}
_globalwindow2['default']['webvtt']['processcues'](_globalwindow2['default'], track['activecues'], 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 = _globalwindow2['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']);
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 style
* some style changes will throw an error, particularly in ie8. those should be noops.
*
* @param {element} el the element to be styles
* @param {cssproperty} style the css property to be styled
* @param {cssstyle} rule the actual style to be applied to the property
* @method tryupdatestyle
*/
function tryupdatestyle(el, style, rule) {
//
try {
el.style[style] = rule;
} catch (e) {}
}
_component2['default'].registercomponent('texttrackdisplay', texttrackdisplay);
exports['default'] = texttrackdisplay;
module.exports = exports['default'];
},{"../component":67,"../menu/menu-button.js":104,"../menu/menu-item.js":105,"../menu/menu.js":106,"../utils/fn.js":134,"global/document":1,"global/window":2}],124:[function(_dereq_,module,exports){
/**
* @file text-track-enums.js
*/
/**
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode
*
* enum texttrackmode { "disabled", "hidden", "showing" };
*/
'use strict';
exports.__esmodule = true;
var texttrackmode = {
disabled: 'disabled',
hidden: 'hidden',
showing: 'showing'
};
/**
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackkind
*
* enum texttrackkind {
* "subtitles",
* "captions",
* "descriptions",
* "chapters",
* "metadata"
* };
*/
var texttrackkind = {
subtitles: 'subtitles',
captions: 'captions',
descriptions: 'descriptions',
chapters: 'chapters',
metadata: 'metadata'
};
/* jshint ignore:start */
// we ignore jshint here because it does not see
// texttrackmode or texttrackkind as defined here somehow...
exports.texttrackmode = texttrackmode;
exports.texttrackkind = texttrackkind;
/* jshint ignore:end */
},{}],125:[function(_dereq_,module,exports){
/**
* utilities for capturing text track state and re-creating tracks
* based on a capture.
*
* @file text-track-list-converter.js
*/
/**
* examine a single text track and return a json-compatible javascript
* object that represents the text track's state.
* @param track {texttrackobject} the text track to query
* @return {object} a serializable javascript representation of the
* @private
*/
'use strict';
exports.__esmodule = true;
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 tech and return a json-compatible javascript array that
* represents the state of all text tracks currently configured. the
* return array is compatible with `jsontotexttracks`.
* @param tech {tech} the tech object to query
* @return {array} a serializable javascript representation of the
* @function texttrackstojson
*/
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_));
};
/**
* creates a set of remote text tracks on a tech based on an array of
* javascript text track representations.
* @param json {array} an array of text track representation objects,
* like those that would be produced by `texttrackstojson`
* @param tech {tech} the tech to create text tracks on
* @function jsontotexttracks
*/
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_ };
module.exports = exports['default'];
},{}],126:[function(_dereq_,module,exports){
/**
* @file text-track-list.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _eventtarget = _dereq_('../event-target');
var _eventtarget2 = _interoprequiredefault(_eventtarget);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsbrowserjs = _dereq_('../utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
/**
* a text track list as defined in:
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist
*
* interface texttracklist : eventtarget {
* readonly attribute unsigned long length;
* getter texttrack (unsigned long index);
* texttrack? gettrackbyid(domstring id);
*
* attribute eventhandler onchange;
* attribute eventhandler onaddtrack;
* attribute eventhandler onremovetrack;
* };
*
* @param {track[]} tracks a list of tracks to initialize the list with
* @extends eventtarget
* @class texttracklist
*/
var texttracklist = (function (_eventtarget) {
_inherits(texttracklist, _eventtarget);
function texttracklist() {
var tracks = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
_classcallcheck(this, texttracklist);
_eventtarget.call(this);
var list = this;
if (browser.is_ie8) {
list = _globaldocument2['default'].createelement('custom');
for (var prop in texttracklist.prototype) {
if (prop !== 'constructor') {
list[prop] = texttracklist.prototype[prop];
}
}
}
list.tracks_ = [];
object.defineproperty(list, 'length', {
get: function get() {
return this.tracks_.length;
}
});
for (var i = 0; i < tracks.length; i++) {
list.addtrack_(tracks[i]);
}
if (browser.is_ie8) {
return list;
}
}
/**
* change - one or more tracks in the track list have been enabled or disabled.
* addtrack - a track has been added to the track list.
* removetrack - a track has been removed from the track list.
*/
/**
* add texttrack from texttracklist
*
* @param {texttrack} track
* @method addtrack_
* @private
*/
texttracklist.prototype.addtrack_ = function addtrack_(track) {
var index = this.tracks_.length;
if (!('' + index in this)) {
object.defineproperty(this, index, {
get: function get() {
return this.tracks_[index];
}
});
}
track.addeventlistener('modechange', fn.bind(this, function () {
this.trigger('change');
}));
// do not add duplicate tracks
if (this.tracks_.indexof(track) === -1) {
this.tracks_.push(track);
this.trigger({
track: track,
type: 'addtrack'
});
}
};
/**
* remove texttrack from texttracklist
* note: be mindful of what is passed in as it may be a htmltrackelement
*
* @param {texttrack} rtrack
* @method removetrack_
* @private
*/
texttracklist.prototype.removetrack_ = function removetrack_(rtrack) {
var track = undefined;
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === rtrack) {
track = this[i];
if (track.off) {
track.off();
}
this.tracks_.splice(i, 1);
break;
}
}
if (!track) {
return;
}
this.trigger({
track: track,
type: 'removetrack'
});
};
/**
* get a texttrack from texttracklist by a tracks id
*
* @param {string} id - the id of the track to get
* @method gettrackbyid
* @return {texttrack}
* @private
*/
texttracklist.prototype.gettrackbyid = function gettrackbyid(id) {
var result = null;
for (var i = 0, l = this.length; i < l; i++) {
var track = this[i];
if (track.id === id) {
result = track;
break;
}
}
return result;
};
return texttracklist;
})(_eventtarget2['default']);
texttracklist.prototype.allowedevents_ = {
change: 'change',
addtrack: 'addtrack',
removetrack: 'removetrack'
};
// emulate attribute eventhandler support to allow for feature detection
for (var _event in texttracklist.prototype.allowedevents_) {
texttracklist.prototype['on' + _event] = null;
}
exports['default'] = texttracklist;
module.exports = exports['default'];
},{"../event-target":99,"../utils/browser.js":129,"../utils/fn.js":134,"global/document":1}],127:[function(_dereq_,module,exports){
/**
* @file text-track-settings.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _component = _dereq_('../component');
var _component2 = _interoprequiredefault(_component);
var _utilseventsjs = _dereq_('../utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilslogjs = _dereq_('../utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _safejsonparsetuple = _dereq_('safe-json-parse/tuple');
var _safejsonparsetuple2 = _interoprequiredefault(_safejsonparsetuple);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
/**
* manipulate settings of texttracks
*
* @param {object} player main player
* @param {object=} options object of option names and values
* @extends component
* @class texttracksettings
*/
var texttracksettings = (function (_component) {
_inherits(texttracksettings, _component);
function texttracksettings(player, options) {
_classcallcheck(this, texttracksettings);
_component.call(this, player, options);
this.hide();
// grab `persisttexttracksettings` from the player options if not passed in child options
if (options.persisttexttracksettings === undefined) {
this.options_.persisttexttracksettings = this.options_.playeroptions.persisttexttracksettings;
}
events.on(this.$('.vjs-done-button'), 'click', fn.bind(this, function () {
this.savesettings();
this.hide();
}));
events.on(this.$('.vjs-default-button'), 'click', fn.bind(this, function () {
this.$('.vjs-fg-color > select').selectedindex = 0;
this.$('.vjs-bg-color > select').selectedindex = 0;
this.$('.window-color > select').selectedindex = 0;
this.$('.vjs-text-opacity > select').selectedindex = 0;
this.$('.vjs-bg-opacity > select').selectedindex = 0;
this.$('.vjs-window-opacity > select').selectedindex = 0;
this.$('.vjs-edge-style select').selectedindex = 0;
this.$('.vjs-font-family select').selectedindex = 0;
this.$('.vjs-font-percent select').selectedindex = 2;
this.updatedisplay();
}));
events.on(this.$('.vjs-fg-color > select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.vjs-bg-color > select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.window-color > select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.vjs-text-opacity > select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.vjs-bg-opacity > select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.vjs-window-opacity > select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.vjs-font-percent select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.vjs-edge-style select'), 'change', fn.bind(this, this.updatedisplay));
events.on(this.$('.vjs-font-family select'), 'change', fn.bind(this, this.updatedisplay));
if (this.options_.persisttexttracksettings) {
this.restoresettings();
}
}
/**
* create the component's dom element
*
* @return {element}
* @method createel
*/
texttracksettings.prototype.createel = function createel() {
return _component.prototype.createel.call(this, 'div', {
classname: 'vjs-caption-settings vjs-modal-overlay',
innerhtml: captionoptionsmenutemplate()
});
};
/**
* get texttrack settings
* settings are
* .vjs-edge-style
* .vjs-font-family
* .vjs-fg-color
* .vjs-text-opacity
* .vjs-bg-color
* .vjs-bg-opacity
* .window-color
* .vjs-window-opacity
*
* @return {object}
* @method getvalues
*/
texttracksettings.prototype.getvalues = function getvalues() {
var textedge = getselectedoptionvalue(this.$('.vjs-edge-style select'));
var fontfamily = getselectedoptionvalue(this.$('.vjs-font-family select'));
var fgcolor = getselectedoptionvalue(this.$('.vjs-fg-color > select'));
var textopacity = getselectedoptionvalue(this.$('.vjs-text-opacity > select'));
var bgcolor = getselectedoptionvalue(this.$('.vjs-bg-color > select'));
var bgopacity = getselectedoptionvalue(this.$('.vjs-bg-opacity > select'));
var windowcolor = getselectedoptionvalue(this.$('.window-color > select'));
var windowopacity = getselectedoptionvalue(this.$('.vjs-window-opacity > select'));
var fontpercent = _globalwindow2['default']['parsefloat'](getselectedoptionvalue(this.$('.vjs-font-percent > select')));
var result = {
'backgroundopacity': bgopacity,
'textopacity': textopacity,
'windowopacity': windowopacity,
'edgestyle': textedge,
'fontfamily': fontfamily,
'color': fgcolor,
'backgroundcolor': bgcolor,
'windowcolor': windowcolor,
'fontpercent': fontpercent
};
for (var _name in result) {
if (result[_name] === '' || result[_name] === 'none' || _name === 'fontpercent' && result[_name] === 1.00) {
delete result[_name];
}
}
return result;
};
/**
* set texttrack settings
* settings are
* .vjs-edge-style
* .vjs-font-family
* .vjs-fg-color
* .vjs-text-opacity
* .vjs-bg-color
* .vjs-bg-opacity
* .window-color
* .vjs-window-opacity
*
* @param {object} values object with texttrack setting values
* @method setvalues
*/
texttracksettings.prototype.setvalues = function setvalues(values) {
setselectedoption(this.$('.vjs-edge-style select'), values.edgestyle);
setselectedoption(this.$('.vjs-font-family select'), values.fontfamily);
setselectedoption(this.$('.vjs-fg-color > select'), values.color);
setselectedoption(this.$('.vjs-text-opacity > select'), values.textopacity);
setselectedoption(this.$('.vjs-bg-color > select'), values.backgroundcolor);
setselectedoption(this.$('.vjs-bg-opacity > select'), values.backgroundopacity);
setselectedoption(this.$('.window-color > select'), values.windowcolor);
setselectedoption(this.$('.vjs-window-opacity > select'), values.windowopacity);
var fontpercent = values.fontpercent;
if (fontpercent) {
fontpercent = fontpercent.tofixed(2);
}
setselectedoption(this.$('.vjs-font-percent > select'), fontpercent);
};
/**
* restore texttrack settings
*
* @method restoresettings
*/
texttracksettings.prototype.restoresettings = function restoresettings() {
var err = undefined,
values = undefined;
try {
var _safeparsetuple = _safejsonparsetuple2['default'](_globalwindow2['default'].localstorage.getitem('vjs-text-track-settings'));
err = _safeparsetuple[0];
values = _safeparsetuple[1];
if (err) {
_utilslogjs2['default'].error(err);
}
} catch (e) {
_utilslogjs2['default'].warn(e);
}
if (values) {
this.setvalues(values);
}
};
/**
* save texttrack settings to local storage
*
* @method savesettings
*/
texttracksettings.prototype.savesettings = function savesettings() {
if (!this.options_.persisttexttracksettings) {
return;
}
var values = this.getvalues();
try {
if (object.getownpropertynames(values).length > 0) {
_globalwindow2['default'].localstorage.setitem('vjs-text-track-settings', json.stringify(values));
} else {
_globalwindow2['default'].localstorage.removeitem('vjs-text-track-settings');
}
} catch (e) {
_utilslogjs2['default'].warn(e);
}
};
/**
* update display of texttrack settings
*
* @method updatedisplay
*/
texttracksettings.prototype.updatedisplay = function updatedisplay() {
var ttdisplay = this.player_.getchild('texttrackdisplay');
if (ttdisplay) {
ttdisplay.updatedisplay();
}
};
return texttracksettings;
})(_component2['default']);
_component2['default'].registercomponent('texttracksettings', texttracksettings);
function getselectedoptionvalue(target) {
var selectedoption = undefined;
// not all browsers support selectedoptions, so, fallback to options
if (target.selectedoptions) {
selectedoption = target.selectedoptions[0];
} else if (target.options) {
selectedoption = target.options[target.options.selectedindex];
}
return selectedoption.value;
}
function setselectedoption(target, value) {
if (!value) {
return;
}
var i = undefined;
for (i = 0; i < target.options.length; i++) {
var option = target.options[i];
if (option.value === value) {
break;
}
}
target.selectedindex = i;
}
function captionoptionsmenutemplate() {
var template = '
\n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n \n \n \n \n \n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n
\n \n \n
';
return template;
}
exports['default'] = texttracksettings;
module.exports = exports['default'];
},{"../component":67,"../utils/events.js":133,"../utils/fn.js":134,"../utils/log.js":137,"global/window":2,"safe-json-parse/tuple":54}],128:[function(_dereq_,module,exports){
/**
* @file text-track.js
*/
'use strict';
exports.__esmodule = true;
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 _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; }
var _texttrackcuelist = _dereq_('./text-track-cue-list');
var _texttrackcuelist2 = _interoprequiredefault(_texttrackcuelist);
var _utilsfnjs = _dereq_('../utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _utilsguidjs = _dereq_('../utils/guid.js');
var guid = _interoprequirewildcard(_utilsguidjs);
var _utilsbrowserjs = _dereq_('../utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _texttrackenums = _dereq_('./text-track-enums');
var texttrackenum = _interoprequirewildcard(_texttrackenums);
var _utilslogjs = _dereq_('../utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _eventtarget = _dereq_('../event-target');
var _eventtarget2 = _interoprequiredefault(_eventtarget);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _utilsurljs = _dereq_('../utils/url.js');
var _xhr = _dereq_('xhr');
var _xhr2 = _interoprequiredefault(_xhr);
/**
* takes a webvtt file contents and parses it into cues
*
* @param {string} srccontent webvtt file contents
* @param {track} track track to addcues to
*/
var parsecues = function parsecues(srccontent, track) {
var parser = new _globalwindow2['default'].webvtt.parser(_globalwindow2['default'], _globalwindow2['default'].vttjs, _globalwindow2['default'].webvtt.stringdecoder());
parser.oncue = function (cue) {
track.addcue(cue);
};
parser.onparsingerror = function (error) {
_utilslogjs2['default'].error(error);
};
parser.onflush = function () {
track.trigger({
type: 'loadeddata',
target: track
});
};
parser.parse(srccontent);
parser.flush();
};
/**
* load a track from a specifed url
*
* @param {string} src url to load track from
* @param {track} track track to addcues to
*/
var loadtrack = function loadtrack(src, track) {
var opts = {
uri: src
};
var crossorigin = _utilsurljs.iscrossorigin(src);
if (crossorigin) {
opts.cors = crossorigin;
}
_xhr2['default'](opts, fn.bind(this, function (err, response, responsebody) {
if (err) {
return _utilslogjs2['default'].error(err, response);
}
track.loaded_ = true;
// make sure that vttjs has loaded, otherwise, wait till it finished loading
// note: this is only used for the alt/video.novtt.js build
if (typeof _globalwindow2['default'].webvtt !== 'function') {
if (track.tech_) {
(function () {
var loadhandler = function loadhandler() {
return parsecues(responsebody, track);
};
track.tech_.on('vttjsloaded', loadhandler);
track.tech_.on('vttjserror', function () {
_utilslogjs2['default'].error('vttjs failed to load, stopping trying to process ' + track.src);
track.tech_.off('vttjsloaded', loadhandler);
});
})();
}
} else {
parsecues(responsebody, track);
}
}));
};
/**
* a single text track as defined in:
* https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack
*
* interface texttrack : eventtarget {
* readonly attribute texttrackkind kind;
* readonly attribute domstring label;
* readonly attribute domstring language;
*
* readonly attribute domstring id;
* readonly attribute domstring inbandmetadatatrackdispatchtype;
*
* attribute texttrackmode mode;
*
* readonly attribute texttrackcuelist? cues;
* readonly attribute texttrackcuelist? activecues;
*
* void addcue(texttrackcue cue);
* void removecue(texttrackcue cue);
*
* attribute eventhandler oncuechange;
* };
*
* @param {object=} options object of option names and values
* @extends eventtarget
* @class texttrack
*/
var texttrack = (function (_eventtarget) {
_inherits(texttrack, _eventtarget);
function texttrack() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
_classcallcheck(this, texttrack);
_eventtarget.call(this);
if (!options.tech) {
throw new error('a tech was not provided.');
}
var tt = this;
if (browser.is_ie8) {
tt = _globaldocument2['default'].createelement('custom');
for (var prop in texttrack.prototype) {
if (prop !== 'constructor') {
tt[prop] = texttrack.prototype[prop];
}
}
}
tt.tech_ = options.tech;
var mode = texttrackenum.texttrackmode[options.mode] || 'disabled';
var kind = texttrackenum.texttrackkind[options.kind] || 'subtitles';
var label = options.label || '';
var language = options.language || options.srclang || '';
var id = options.id || 'vjs_text_track_' + guid.newguid();
if (kind === 'metadata' || kind === 'chapters') {
mode = 'hidden';
}
tt.cues_ = [];
tt.activecues_ = [];
var cues = new _texttrackcuelist2['default'](tt.cues_);
var activecues = new _texttrackcuelist2['default'](tt.activecues_);
var changed = false;
var timeupdatehandler = fn.bind(tt, function () {
this.activecues;
if (changed) {
this.trigger('cuechange');
changed = false;
}
});
if (mode !== 'disabled') {
tt.tech_.on('timeupdate', timeupdatehandler);
}
object.defineproperty(tt, 'kind', {
get: function get() {
return kind;
},
set: function set() {}
});
object.defineproperty(tt, 'label', {
get: function get() {
return label;
},
set: function set() {}
});
object.defineproperty(tt, 'language', {
get: function get() {
return language;
},
set: function set() {}
});
object.defineproperty(tt, 'id', {
get: function get() {
return id;
},
set: function set() {}
});
object.defineproperty(tt, 'mode', {
get: function get() {
return mode;
},
set: function set(newmode) {
if (!texttrackenum.texttrackmode[newmode]) {
return;
}
mode = newmode;
if (mode === 'showing') {
this.tech_.on('timeupdate', timeupdatehandler);
}
this.trigger('modechange');
}
});
object.defineproperty(tt, 'cues', {
get: function get() {
if (!this.loaded_) {
return null;
}
return cues;
},
set: function set() {}
});
object.defineproperty(tt, 'activecues', {
get: function get() {
if (!this.loaded_) {
return null;
}
// nothing to do
if (this.cues.length === 0) {
return activecues;
}
var ct = this.tech_.currenttime();
var active = [];
for (var i = 0, l = this.cues.length; i < l; i++) {
var cue = this.cues[i];
if (cue.starttime <= ct && cue.endtime >= ct) {
active.push(cue);
} else if (cue.starttime === cue.endtime && cue.starttime <= ct && cue.starttime + 0.5 >= ct) {
active.push(cue);
}
}
changed = false;
if (active.length !== this.activecues_.length) {
changed = true;
} else {
for (var i = 0; i < active.length; i++) {
if (this.activecues_.indexof(active[i]) === -1) {
changed = true;
}
}
}
this.activecues_ = active;
activecues.setcues_(this.activecues_);
return activecues;
},
set: function set() {}
});
if (options.src) {
tt.src = options.src;
loadtrack(options.src, tt);
} else {
tt.loaded_ = true;
}
if (browser.is_ie8) {
return tt;
}
}
/**
* cuechange - one or more cues in the track have become active or stopped being active.
*/
/**
* add a cue to the internal list of cues
*
* @param {object} cue the cue to add to our internal list
* @method addcue
*/
texttrack.prototype.addcue = function addcue(cue) {
var tracks = this.tech_.texttracks();
if (tracks) {
for (var i = 0; i < tracks.length; i++) {
if (tracks[i] !== this) {
tracks[i].removecue(cue);
}
}
}
this.cues_.push(cue);
this.cues.setcues_(this.cues_);
};
/**
* remvoe a cue from our internal list
*
* @param {object} removecue the cue to remove from our internal list
* @method removecue
*/
texttrack.prototype.removecue = function removecue(_removecue) {
var removed = false;
for (var i = 0, l = this.cues_.length; i < l; i++) {
var cue = this.cues_[i];
if (cue === _removecue) {
this.cues_.splice(i, 1);
removed = true;
}
}
if (removed) {
this.cues.setcues_(this.cues_);
}
};
return texttrack;
})(_eventtarget2['default']);
texttrack.prototype.allowedevents_ = {
cuechange: 'cuechange'
};
exports['default'] = texttrack;
module.exports = exports['default'];
},{"../event-target":99,"../utils/browser.js":129,"../utils/fn.js":134,"../utils/guid.js":136,"../utils/log.js":137,"../utils/url.js":142,"./text-track-cue-list":122,"./text-track-enums":124,"global/document":1,"global/window":2,"xhr":56}],129:[function(_dereq_,module,exports){
/**
* @file browser.js
*/
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var user_agent = _globalwindow2['default'].navigator.useragent;
var webkitversionmap = /applewebkit\/([\d.]+)/i.exec(user_agent);
var applewebkitversion = webkitversionmap ? parsefloat(webkitversionmap.pop()) : null;
/*
* device is an iphone
*
* @type {boolean}
* @constant
* @private
*/
var is_ipad = /ipad/i.test(user_agent);
exports.is_ipad = is_ipad;
// the facebook app's uiwebview identifies as both an iphone and ipad, so
// to identify iphones, we need to exclude ipads.
// http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/
var is_iphone = /iphone/i.test(user_agent) && !is_ipad;
exports.is_iphone = is_iphone;
var is_ipod = /ipod/i.test(user_agent);
exports.is_ipod = is_ipod;
var is_ios = is_iphone || is_ipad || is_ipod;
exports.is_ios = is_ios;
var ios_version = (function () {
var match = user_agent.match(/os (\d+)_/i);
if (match && match[1]) {
return match[1];
}
})();
exports.ios_version = ios_version;
var is_android = /android/i.test(user_agent);
exports.is_android = is_android;
var android_version = (function () {
// this matches android major.minor.patch versions
// android_version is major.minor as a number, if minor isn't available, then only major is returned
var match = user_agent.match(/android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i),
major,
minor;
if (!match) {
return null;
}
major = match[1] && parsefloat(match[1]);
minor = match[2] && parsefloat(match[2]);
if (major && minor) {
return parsefloat(match[1] + '.' + match[2]);
} else if (major) {
return major;
} else {
return null;
}
})();
exports.android_version = android_version;
// old android is defined as version older than 2.3, and requiring a webkit version of the android browser
var is_old_android = is_android && /webkit/i.test(user_agent) && android_version < 2.3;
exports.is_old_android = is_old_android;
var is_native_android = is_android && android_version < 5 && applewebkitversion < 537;
exports.is_native_android = is_native_android;
var is_firefox = /firefox/i.test(user_agent);
exports.is_firefox = is_firefox;
var is_chrome = /chrome/i.test(user_agent);
exports.is_chrome = is_chrome;
var is_ie8 = /msie\s8\.0/.test(user_agent);
exports.is_ie8 = is_ie8;
var touch_enabled = !!('ontouchstart' in _globalwindow2['default'] || _globalwindow2['default'].documenttouch && _globaldocument2['default'] instanceof _globalwindow2['default'].documenttouch);
exports.touch_enabled = touch_enabled;
var background_size_supported = ('backgroundsize' in _globaldocument2['default'].createelement('video').style);
exports.background_size_supported = background_size_supported;
},{"global/document":1,"global/window":2}],130:[function(_dereq_,module,exports){
/**
* @file buffer.js
*/
'use strict';
exports.__esmodule = true;
exports.bufferedpercent = bufferedpercent;
var _timerangesjs = _dereq_('./time-ranges.js');
/**
* compute how much your video has been buffered
*
* @param {object} buffered object
* @param {number} total duration
* @return {number} percent buffered of the total duration
* @private
* @function bufferedpercent
*/
function bufferedpercent(buffered, duration) {
var bufferedduration = 0,
start,
end;
if (!duration) {
return 0;
}
if (!buffered || !buffered.length) {
buffered = _timerangesjs.createtimerange(0, 0);
}
for (var i = 0; i < buffered.length; i++) {
start = buffered.start(i);
end = buffered.end(i);
// buffered end can be bigger than duration by a very small fraction
if (end > duration) {
end = duration;
}
bufferedduration += end - start;
}
return bufferedduration / duration;
}
},{"./time-ranges.js":140}],131:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _logjs = _dereq_('./log.js');
var _logjs2 = _interoprequiredefault(_logjs);
/**
* object containing the default behaviors for available handler methods.
*
* @private
* @type {object}
*/
var defaultbehaviors = {
get: function get(obj, key) {
return obj[key];
},
set: function set(obj, key, value) {
obj[key] = value;
return true;
}
};
/**
* expose private objects publicly using a proxy to log deprecation warnings.
*
* browsers that do not support proxy objects will simply return the `target`
* object, so it can be directly exposed.
*
* @param {object} target the target object.
* @param {object} messages messages to display from a proxy. only operations
* with an associated message will be proxied.
* @param {string} [messages.get]
* @param {string} [messages.set]
* @return {object} a proxy if supported or the `target` argument.
*/
exports['default'] = function (target) {
var messages = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
if (typeof proxy === 'function') {
var _ret = (function () {
var handler = {};
// build a handler object based on those keys that have both messages
// and default behaviors.
object.keys(messages).foreach(function (key) {
if (defaultbehaviors.hasownproperty(key)) {
handler[key] = function () {
_logjs2['default'].warn(messages[key]);
return defaultbehaviors[key].apply(this, arguments);
};
}
});
return {
v: new proxy(target, handler)
};
})();
if (typeof _ret === 'object') return _ret.v;
}
return target;
};
module.exports = exports['default'];
},{"./log.js":137}],132:[function(_dereq_,module,exports){
/**
* @file dom.js
*/
'use strict';
exports.__esmodule = true;
exports.getel = getel;
exports.createel = createel;
exports.textcontent = textcontent;
exports.insertelfirst = insertelfirst;
exports.geteldata = geteldata;
exports.haseldata = haseldata;
exports.removeeldata = removeeldata;
exports.haselclass = haselclass;
exports.addelclass = addelclass;
exports.removeelclass = removeelclass;
exports.toggleelclass = toggleelclass;
exports.setelattributes = setelattributes;
exports.getelattributes = getelattributes;
exports.blocktextselection = blocktextselection;
exports.unblocktextselection = unblocktextselection;
exports.findelposition = findelposition;
exports.getpointerposition = getpointerposition;
exports.isel = isel;
exports.istextnode = istextnode;
exports.emptyel = emptyel;
exports.normalizecontent = normalizecontent;
exports.appendcontent = appendcontent;
exports.insertcontent = insertcontent;
var _templateobject = _taggedtemplateliteralloose(['setting attributes in the second argument of createel()\n has been deprecated. use the third argument instead.\n createel(type, properties, attributes). attempting to set ', ' to ', '.'], ['setting attributes in the second argument of createel()\n has been deprecated. use the third argument instead.\n createel(type, properties, attributes). attempting to set ', ' to ', '.']);
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; }
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _guidjs = _dereq_('./guid.js');
var guid = _interoprequirewildcard(_guidjs);
var _logjs = _dereq_('./log.js');
var _logjs2 = _interoprequiredefault(_logjs);
var _tsml = _dereq_('tsml');
var _tsml2 = _interoprequiredefault(_tsml);
/**
* detect if a value is a string with any non-whitespace characters.
*
* @param {string} str
* @return {boolean}
*/
function isnonblankstring(str) {
return typeof str === 'string' && /\s/.test(str);
}
/**
* throws an error if the passed string has whitespace. this is used by
* class methods to be relatively consistent with the classlist api.
*
* @param {string} str
* @return {boolean}
*/
function throwifwhitespace(str) {
if (/\s/.test(str)) {
throw new error('class has illegal whitespace characters');
}
}
/**
* produce a regular expression for matching a class name.
*
* @param {string} classname
* @return {regexp}
*/
function classregexp(classname) {
return new regexp('(^|\\s)' + classname + '($|\\s)');
}
/**
* creates functions to query the dom using a given method.
*
* @function createquerier
* @private
* @param {string} method
* @return {function}
*/
function createquerier(method) {
return function (selector, context) {
if (!isnonblankstring(selector)) {
return _globaldocument2['default'][method](null);
}
if (isnonblankstring(context)) {
context = _globaldocument2['default'].queryselector(context);
}
return (isel(context) ? context : _globaldocument2['default'])[method](selector);
};
}
/**
* shorthand for document.getelementbyid()
* also allows for css (jquery) id syntax. but nothing other than ids.
*
* @param {string} id element id
* @return {element} element with supplied id
* @function getel
*/
function getel(id) {
if (id.indexof('#') === 0) {
id = id.slice(1);
}
return _globaldocument2['default'].getelementbyid(id);
}
/**
* creates an element and applies properties.
*
* @param {string} [tagname='div'] name of tag to be created.
* @param {object} [properties={}] element properties to be applied.
* @param {object} [attributes={}] element attributes to be applied.
* @return {element}
* @function createel
*/
function createel() {
var tagname = arguments.length <= 0 || arguments[0] === undefined ? 'div' : arguments[0];
var properties = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
var el = _globaldocument2['default'].createelement(tagname);
object.getownpropertynames(properties).foreach(function (propname) {
var val = properties[propname];
// see #2176
// we originally were accepting both properties and attributes in the
// same object, but that doesn't work so well.
if (propname.indexof('aria-') !== -1 || propname === 'role' || propname === 'type') {
_logjs2['default'].warn(_tsml2['default'](_templateobject, propname, val));
el.setattribute(propname, val);
} else {
el[propname] = val;
}
});
object.getownpropertynames(attributes).foreach(function (attrname) {
var val = attributes[attrname];
el.setattribute(attrname, attributes[attrname]);
});
return el;
}
/**
* injects text into an element, replacing any existing contents entirely.
*
* @param {element} el
* @param {string} text
* @return {element}
* @function textcontent
*/
function textcontent(el, text) {
if (typeof el.textcontent === 'undefined') {
el.innertext = text;
} else {
el.textcontent = text;
}
}
/**
* insert an element as the first child node of another
*
* @param {element} child element to insert
* @param {element} parent element to insert child into
* @private
* @function insertelfirst
*/
function insertelfirst(child, parent) {
if (parent.firstchild) {
parent.insertbefore(child, parent.firstchild);
} else {
parent.appendchild(child);
}
}
/**
* element data store. allows for binding data to an element without putting it directly on the element.
* ex. event listeners are stored here.
* (also from jsninja.com, slightly modified and updated for closure compiler)
*
* @type {object}
* @private
*/
var eldata = {};
/*
* unique attribute name to store an element's guid in
*
* @type {string}
* @constant
* @private
*/
var elidattr = 'vdata' + new date().gettime();
/**
* returns the cache object where data for an element is stored
*
* @param {element} el element to store data for.
* @return {object}
* @function geteldata
*/
function geteldata(el) {
var id = el[elidattr];
if (!id) {
id = el[elidattr] = guid.newguid();
}
if (!eldata[id]) {
eldata[id] = {};
}
return eldata[id];
}
/**
* returns whether or not an element has cached data
*
* @param {element} el a dom element
* @return {boolean}
* @private
* @function haseldata
*/
function haseldata(el) {
var id = el[elidattr];
if (!id) {
return false;
}
return !!object.getownpropertynames(eldata[id]).length;
}
/**
* delete data for the element from the cache and the guid attr from getelementbyid
*
* @param {element} el remove data for an element
* @private
* @function removeeldata
*/
function removeeldata(el) {
var id = el[elidattr];
if (!id) {
return;
}
// remove all stored data
delete eldata[id];
// remove the elidattr property from the dom node
try {
delete el[elidattr];
} catch (e) {
if (el.removeattribute) {
el.removeattribute(elidattr);
} else {
// ie doesn't appear to support removeattribute on the document element
el[elidattr] = null;
}
}
}
/**
* check if an element has a css class
*
* @function haselclass
* @param {element} element element to check
* @param {string} classtocheck classname to check
*/
function haselclass(element, classtocheck) {
if (element.classlist) {
return element.classlist.contains(classtocheck);
} else {
throwifwhitespace(classtocheck);
return classregexp(classtocheck).test(element.classname);
}
}
/**
* add a css class name to an element
*
* @function addelclass
* @param {element} element element to add class name to
* @param {string} classtoadd classname to add
*/
function addelclass(element, classtoadd) {
if (element.classlist) {
element.classlist.add(classtoadd);
// don't need to `throwifwhitespace` here because `haselclass` will do it
// in the case of classlist not being supported.
} else if (!haselclass(element, classtoadd)) {
element.classname = (element.classname + ' ' + classtoadd).trim();
}
return element;
}
/**
* remove a css class name from an element
*
* @function removeelclass
* @param {element} element element to remove from class name
* @param {string} classtoremove classname to remove
*/
function removeelclass(element, classtoremove) {
if (element.classlist) {
element.classlist.remove(classtoremove);
} else {
throwifwhitespace(classtoremove);
element.classname = element.classname.split(/\s+/).filter(function (c) {
return c !== classtoremove;
}).join(' ');
}
return element;
}
/**
* adds or removes a css class name on an element depending on an optional
* condition or the presence/absence of the class name.
*
* @function toggleelclass
* @param {element} element
* @param {string} classtotoggle
* @param {boolean|function} [predicate]
* can be a function that returns a boolean. if `true`, the class
* will be added; if `false`, the class will be removed. if not
* given, the class will be added if not present and vice versa.
*/
function toggleelclass(element, classtotoggle, predicate) {
// this cannot use `classlist` internally because ie does not support the
// second parameter to the `classlist.toggle()` method! which is fine because
// `classlist` will be used by the add/remove functions.
var has = haselclass(element, classtotoggle);
if (typeof predicate === 'function') {
predicate = predicate(element, classtotoggle);
}
if (typeof predicate !== 'boolean') {
predicate = !has;
}
// if the necessary class operation matches the current state of the
// element, no action is required.
if (predicate === has) {
return;
}
if (predicate) {
addelclass(element, classtotoggle);
} else {
removeelclass(element, classtotoggle);
}
return element;
}
/**
* apply attributes to an html element.
*
* @param {element} el target element.
* @param {object=} attributes element attributes to be applied.
* @private
* @function setelattributes
*/
function setelattributes(el, attributes) {
object.getownpropertynames(attributes).foreach(function (attrname) {
var attrvalue = attributes[attrname];
if (attrvalue === null || typeof attrvalue === 'undefined' || attrvalue === false) {
el.removeattribute(attrname);
} else {
el.setattribute(attrname, attrvalue === true ? '' : attrvalue);
}
});
}
/**
* get an element's attribute values, as defined on the html tag
* attributes are not the same as properties. they're defined on the tag
* or with setattribute (which shouldn't be used with html)
* this will return true or false for boolean attributes.
*
* @param {element} tag element from which to get tag attributes
* @return {object}
* @private
* @function getelattributes
*/
function getelattributes(tag) {
var obj, knownbooleans, attrs, attrname, attrval;
obj = {};
// known boolean attributes
// we can check for matching boolean properties, but older browsers
// won't know about html5 boolean attributes that we still read from
knownbooleans = ',' + 'autoplay,controls,loop,muted,default' + ',';
if (tag && tag.attributes && tag.attributes.length > 0) {
attrs = tag.attributes;
for (var i = attrs.length - 1; i >= 0; i--) {
attrname = attrs[i].name;
attrval = attrs[i].value;
// check for known booleans
// the matching element property will return a value for typeof
if (typeof tag[attrname] === 'boolean' || knownbooleans.indexof(',' + attrname + ',') !== -1) {
// the value of an included boolean attribute is typically an empty
// string ('') which would equal false if we just check for a false value.
// we also don't want support bad code like autoplay='false'
attrval = attrval !== null ? true : false;
}
obj[attrname] = attrval;
}
}
return obj;
}
/**
* attempt to block the ability to select text while dragging controls
*
* @return {boolean}
* @function blocktextselection
*/
function blocktextselection() {
_globaldocument2['default'].body.focus();
_globaldocument2['default'].onselectstart = function () {
return false;
};
}
/**
* turn off text selection blocking
*
* @return {boolean}
* @function unblocktextselection
*/
function unblocktextselection() {
_globaldocument2['default'].onselectstart = function () {
return true;
};
}
/**
* offset left
* getboundingclientrect technique from
* john resig http://ejohn.org/blog/getboundingclientrect-is-awesome/
*
* @function findelposition
* @param {element} el element from which to get offset
* @return {object}
*/
function findelposition(el) {
var box = undefined;
if (el.getboundingclientrect && el.parentnode) {
box = el.getboundingclientrect();
}
if (!box) {
return {
left: 0,
top: 0
};
}
var docel = _globaldocument2['default'].documentelement;
var body = _globaldocument2['default'].body;
var clientleft = docel.clientleft || body.clientleft || 0;
var scrollleft = _globalwindow2['default'].pagexoffset || body.scrollleft;
var left = box.left + scrollleft - clientleft;
var clienttop = docel.clienttop || body.clienttop || 0;
var scrolltop = _globalwindow2['default'].pageyoffset || body.scrolltop;
var top = box.top + scrolltop - clienttop;
// android sometimes returns slightly off decimal values, so need to round
return {
left: math.round(left),
top: math.round(top)
};
}
/**
* get pointer position in element
* returns an object with x and y coordinates.
* the base on the coordinates are the bottom left of the element.
*
* @function getpointerposition
* @param {element} el element on which to get the pointer position on
* @param {event} event event object
* @return {object} this object will have x and y coordinates corresponding to the mouse position
*/
function getpointerposition(el, event) {
var position = {};
var box = findelposition(el);
var boxw = el.offsetwidth;
var boxh = el.offsetheight;
var boxy = box.top;
var boxx = box.left;
var pagey = event.pagey;
var pagex = event.pagex;
if (event.changedtouches) {
pagex = event.changedtouches[0].pagex;
pagey = event.changedtouches[0].pagey;
}
position.y = math.max(0, math.min(1, (boxy - pagey + boxh) / boxh));
position.x = math.max(0, math.min(1, (pagex - boxx) / boxw));
return position;
}
/**
* determines, via duck typing, whether or not a value is a dom element.
*
* @function isel
* @param {mixed} value
* @return {boolean}
*/
function isel(value) {
return !!value && typeof value === 'object' && value.nodetype === 1;
}
/**
* determines, via duck typing, whether or not a value is a text node.
*
* @param {mixed} value
* @return {boolean}
*/
function istextnode(value) {
return !!value && typeof value === 'object' && value.nodetype === 3;
}
/**
* empties the contents of an element.
*
* @function emptyel
* @param {element} el
* @return {element}
*/
function emptyel(el) {
while (el.firstchild) {
el.removechild(el.firstchild);
}
return el;
}
/**
* normalizes content for eventual insertion into the dom.
*
* this allows a wide range of content definition methods, but protects
* from falling into the trap of simply writing to `innerhtml`, which is
* an xss concern.
*
* the content for an element can be passed in multiple types and
* combinations, whose behavior is as follows:
*
* - string
* normalized into a text node.
*
* - element, textnode
* passed through.
*
* - array
* a one-dimensional array of strings, elements, nodes, or functions (which
* return single strings, elements, or nodes).
*
* - function
* if the sole argument, is expected to produce a string, element,
* node, or array.
*
* @function normalizecontent
* @param {string|element|textnode|array|function} content
* @return {array}
*/
function normalizecontent(content) {
// first, invoke content if it is a function. if it produces an array,
// that needs to happen before normalization.
if (typeof content === 'function') {
content = content();
}
// next up, normalize to an array, so one or many items can be normalized,
// filtered, and returned.
return (array.isarray(content) ? content : [content]).map(function (value) {
// first, invoke value if it is a function to produce a new value,
// which will be subsequently normalized to a node of some kind.
if (typeof value === 'function') {
value = value();
}
if (isel(value) || istextnode(value)) {
return value;
}
if (typeof value === 'string' && /\s/.test(value)) {
return _globaldocument2['default'].createtextnode(value);
}
}).filter(function (value) {
return value;
});
}
/**
* normalizes and appends content to an element.
*
* @function appendcontent
* @param {element} el
* @param {string|element|textnode|array|function} content
* see: `normalizecontent`
* @return {element}
*/
function appendcontent(el, content) {
normalizecontent(content).foreach(function (node) {
return el.appendchild(node);
});
return el;
}
/**
* normalizes and inserts content into an element; this is identical to
* `appendcontent()`, except it empties the element first.
*
* @function insertcontent
* @param {element} el
* @param {string|element|textnode|array|function} content
* see: `normalizecontent`
* @return {element}
*/
function insertcontent(el, content) {
return appendcontent(emptyel(el), content);
}
/**
* finds a single dom element matching `selector` within the optional
* `context` of another dom element (defaulting to `document`).
*
* @function $
* @param {string} selector
* a valid css selector, which will be passed to `queryselector`.
*
* @param {element|string} [context=document]
* a dom element within which to query. can also be a selector
* string in which case the first matching element will be used
* as context. if missing (or no element matches selector), falls
* back to `document`.
*
* @return {element|null}
*/
var $ = createquerier('queryselector');
exports.$ = $;
/**
* finds a all dom elements matching `selector` within the optional
* `context` of another dom element (defaulting to `document`).
*
* @function $$
* @param {string} selector
* a valid css selector, which will be passed to `queryselectorall`.
*
* @param {element|string} [context=document]
* a dom element within which to query. can also be a selector
* string in which case the first matching element will be used
* as context. if missing (or no element matches selector), falls
* back to `document`.
*
* @return {nodelist}
*/
var $$ = createquerier('queryselectorall');
exports.$$ = $$;
},{"./guid.js":136,"./log.js":137,"global/document":1,"global/window":2,"tsml":55}],133:[function(_dereq_,module,exports){
/**
* @file events.js
*
* event system (john resig - secrets of a js ninja http://jsninja.com/)
* (original book version wasn't completely usable, so fixed some things and made closure compiler compatible)
* this should work very similarly to jquery's events, however it's based off the book version which isn't as
* robust as jquery's, so there's probably some differences.
*/
'use strict';
exports.__esmodule = true;
exports.on = on;
exports.off = off;
exports.trigger = trigger;
exports.one = one;
exports.fixevent = fixevent;
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; } }
var _domjs = _dereq_('./dom.js');
var dom = _interoprequirewildcard(_domjs);
var _guidjs = _dereq_('./guid.js');
var guid = _interoprequirewildcard(_guidjs);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
/**
* add an event listener to element
* it stores the handler function in a separate cache object
* and adds a generic handler to the element's event,
* along with a unique id (guid) to the element.
*
* @param {element|object} elem element or object to bind listeners to
* @param {string|array} type type of event to bind to.
* @param {function} fn event listener.
* @method on
*/
function on(elem, type, fn) {
if (array.isarray(type)) {
return _handlemultipleevents(on, elem, type, fn);
}
var data = dom.geteldata(elem);
// we need a place to store all our handler data
if (!data.handlers) data.handlers = {};
if (!data.handlers[type]) data.handlers[type] = [];
if (!fn.guid) fn.guid = guid.newguid();
data.handlers[type].push(fn);
if (!data.dispatcher) {
data.disabled = false;
data.dispatcher = function (event, hash) {
if (data.disabled) return;
event = fixevent(event);
var handlers = data.handlers[event.type];
if (handlers) {
// copy handlers so if handlers are added/removed during the process it doesn't throw everything off.
var handlerscopy = handlers.slice(0);
for (var m = 0, n = handlerscopy.length; m < n; m++) {
if (event.isimmediatepropagationstopped()) {
break;
} else {
handlerscopy[m].call(elem, event, hash);
}
}
}
};
}
if (data.handlers[type].length === 1) {
if (elem.addeventlistener) {
elem.addeventlistener(type, data.dispatcher, false);
} else if (elem.attachevent) {
elem.attachevent('on' + type, data.dispatcher);
}
}
}
/**
* removes event listeners from an element
*
* @param {element|object} elem object to remove listeners from
* @param {string|array=} type type of listener to remove. don't include to remove all events from element.
* @param {function} fn specific listener to remove. don't include to remove listeners for an event type.
* @method off
*/
function off(elem, type, fn) {
// don't want to add a cache object through geteldata if not needed
if (!dom.haseldata(elem)) return;
var data = dom.geteldata(elem);
// if no events exist, nothing to unbind
if (!data.handlers) {
return;
}
if (array.isarray(type)) {
return _handlemultipleevents(off, elem, type, fn);
}
// utility function
var removetype = function removetype(t) {
data.handlers[t] = [];
_cleanupevents(elem, t);
};
// are we removing all bound events?
if (!type) {
for (var t in data.handlers) {
removetype(t);
}return;
}
var handlers = data.handlers[type];
// if no handlers exist, nothing to unbind
if (!handlers) return;
// if no listener was provided, remove all listeners for type
if (!fn) {
removetype(type);
return;
}
// we're only removing a single handler
if (fn.guid) {
for (var n = 0; n < handlers.length; n++) {
if (handlers[n].guid === fn.guid) {
handlers.splice(n--, 1);
}
}
}
_cleanupevents(elem, type);
}
/**
* trigger an event for an element
*
* @param {element|object} elem element to trigger an event on
* @param {event|object|string} event a string (the type) or an event object with a type attribute
* @param {object} [hash] data hash to pass along with the event
* @return {boolean=} returned only if default was prevented
* @method trigger
*/
function trigger(elem, event, hash) {
// fetches element data and a reference to the parent (for bubbling).
// don't want to add a data object to cache for every parent,
// so checking haseldata first.
var elemdata = dom.haseldata(elem) ? dom.geteldata(elem) : {};
var parent = elem.parentnode || elem.ownerdocument;
// type = event.type || event,
// handler;
// if an event name was passed as a string, creates an event out of it
if (typeof event === 'string') {
event = { type: event, target: elem };
}
// normalizes the event properties.
event = fixevent(event);
// if the passed element has a dispatcher, executes the established handlers.
if (elemdata.dispatcher) {
elemdata.dispatcher.call(elem, event, hash);
}
// unless explicitly stopped or the event does not bubble (e.g. media events)
// recursively calls this function to bubble the event up the dom.
if (parent && !event.ispropagationstopped() && event.bubbles === true) {
trigger.call(null, parent, event, hash);
// if at the top of the dom, triggers the default action unless disabled.
} else if (!parent && !event.defaultprevented) {
var targetdata = dom.geteldata(event.target);
// checks if the target has a default action for this event.
if (event.target[event.type]) {
// temporarily disables event dispatching on the target as we have already executed the handler.
targetdata.disabled = true;
// executes the default action.
if (typeof event.target[event.type] === 'function') {
event.target[event.type]();
}
// re-enables event dispatching.
targetdata.disabled = false;
}
}
// inform the triggerer if the default was prevented by returning false
return !event.defaultprevented;
}
/**
* trigger a listener only once for an event
*
* @param {element|object} elem element or object to
* @param {string|array} type name/type of event
* @param {function} fn event handler function
* @method one
*/
function one(elem, type, fn) {
if (array.isarray(type)) {
return _handlemultipleevents(one, elem, type, fn);
}
var func = function func() {
off(elem, type, func);
fn.apply(this, arguments);
};
// copy the guid to the new function so it can removed using the original function's id
func.guid = fn.guid = fn.guid || guid.newguid();
on(elem, type, func);
}
/**
* fix a native event to have standard property values
*
* @param {object} event event object to fix
* @return {object}
* @private
* @method fixevent
*/
function fixevent(event) {
function returntrue() {
return true;
}
function returnfalse() {
return false;
}
// test if fixing up is needed
// used to check if !event.stoppropagation instead of ispropagationstopped
// but native events return true for stoppropagation, but don't have
// other expected methods like ispropagationstopped. seems to be a problem
// with the javascript ninja code. so we're just overriding all events now.
if (!event || !event.ispropagationstopped) {
var old = event || _globalwindow2['default'].event;
event = {};
// clone the old object so that we can modify the values event = {};
// ie8 doesn't like when you mess with native event properties
// firefox returns false for event.hasownproperty('type') and other props
// which makes copying more difficult.
// todo: probably best to create a whitelist of event props
for (var key in old) {
// safari 6.0.3 warns you if you try to copy deprecated layerx/y
// chrome warns you if you try to copy deprecated keyboardevent.keylocation
// and webkitmovementx/y
if (key !== 'layerx' && key !== 'layery' && key !== 'keylocation' && key !== 'webkitmovementx' && key !== 'webkitmovementy') {
// chrome 32+ warns if you try to copy deprecated returnvalue, but
// we still want to if preventdefault isn't supported (ie8).
if (!(key === 'returnvalue' && old.preventdefault)) {
event[key] = old[key];
}
}
}
// the event occurred on this element
if (!event.target) {
event.target = event.srcelement || _globaldocument2['default'];
}
// handle which other element the event is related to
if (!event.relatedtarget) {
event.relatedtarget = event.fromelement === event.target ? event.toelement : event.fromelement;
}
// stop the default browser action
event.preventdefault = function () {
if (old.preventdefault) {
old.preventdefault();
}
event.returnvalue = false;
old.returnvalue = false;
event.defaultprevented = true;
};
event.defaultprevented = false;
// stop the event from bubbling
event.stoppropagation = function () {
if (old.stoppropagation) {
old.stoppropagation();
}
event.cancelbubble = true;
old.cancelbubble = true;
event.ispropagationstopped = returntrue;
};
event.ispropagationstopped = returnfalse;
// stop the event from bubbling and executing other handlers
event.stopimmediatepropagation = function () {
if (old.stopimmediatepropagation) {
old.stopimmediatepropagation();
}
event.isimmediatepropagationstopped = returntrue;
event.stoppropagation();
};
event.isimmediatepropagationstopped = returnfalse;
// handle mouse position
if (event.clientx != null) {
var doc = _globaldocument2['default'].documentelement,
body = _globaldocument2['default'].body;
event.pagex = event.clientx + (doc && doc.scrollleft || body && body.scrollleft || 0) - (doc && doc.clientleft || body && body.clientleft || 0);
event.pagey = event.clienty + (doc && doc.scrolltop || body && body.scrolltop || 0) - (doc && doc.clienttop || body && body.clienttop || 0);
}
// handle key presses
event.which = event.charcode || event.keycode;
// fix button for mouse clicks:
// 0 == left; 1 == middle; 2 == right
if (event.button != null) {
event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0;
}
}
// returns fixed-up instance
return event;
}
/**
* clean up the listener cache and dispatchers
*
* @param {element|object} elem element to clean up
* @param {string} type type of event to clean up
* @private
* @method _cleanupevents
*/
function _cleanupevents(elem, type) {
var data = dom.geteldata(elem);
// remove the events of a particular type if there are none left
if (data.handlers[type].length === 0) {
delete data.handlers[type];
// data.handlers[type] = null;
// setting to null was causing an error with data.handlers
// remove the meta-handler from the element
if (elem.removeeventlistener) {
elem.removeeventlistener(type, data.dispatcher, false);
} else if (elem.detachevent) {
elem.detachevent('on' + type, data.dispatcher);
}
}
// remove the events object if there are no types left
if (object.getownpropertynames(data.handlers).length <= 0) {
delete data.handlers;
delete data.dispatcher;
delete data.disabled;
}
// finally remove the element data if there is no data left
if (object.getownpropertynames(data).length === 0) {
dom.removeeldata(elem);
}
}
/**
* loops through an array of event types and calls the requested method for each type.
*
* @param {function} fn the event method we want to use.
* @param {element|object} elem element or object to bind listeners to
* @param {string} type type of event to bind to.
* @param {function} callback event listener.
* @private
* @function _handlemultipleevents
*/
function _handlemultipleevents(fn, elem, types, callback) {
types.foreach(function (type) {
//call the event method for each one of the types
fn(elem, type, callback);
});
}
},{"./dom.js":132,"./guid.js":136,"global/document":1,"global/window":2}],134:[function(_dereq_,module,exports){
/**
* @file fn.js
*/
'use strict';
exports.__esmodule = true;
var _guidjs = _dereq_('./guid.js');
/**
* bind (a.k.a proxy or context). a simple method for changing the context of a function
* it also stores a unique id on the function so it can be easily removed from events
*
* @param {*} context the object to bind as scope
* @param {function} fn the function to be bound to a scope
* @param {number=} uid an optional unique id for the function to be set
* @return {function}
* @private
* @method bind
*/
var bind = function bind(context, fn, uid) {
// make sure the function has a unique id
if (!fn.guid) {
fn.guid = _guidjs.newguid();
}
// create the new function that changes the context
var ret = function ret() {
return fn.apply(context, arguments);
};
// allow for the ability to individualize this function
// needed in the case where multiple objects might share the same prototype
// if both items add an event listener with the same function, then you try to remove just one
// it will remove both because they both have the same guid.
// when using this, you need to use the bind method when you remove the listener as well.
// currently used in text tracks
ret.guid = uid ? uid + '_' + fn.guid : fn.guid;
return ret;
};
exports.bind = bind;
},{"./guid.js":136}],135:[function(_dereq_,module,exports){
/**
* @file format-time.js
*
* format seconds as a time string, h:mm:ss or m:ss
* supplying a guide (in seconds) will force a number of leading zeros
* to cover the length of the guide
*
* @param {number} seconds number of seconds to be turned into a string
* @param {number} guide number (in seconds) to model the string after
* @return {string} time formatted as h:mm:ss or m:ss
* @private
* @function formattime
*/
'use strict';
exports.__esmodule = true;
function formattime(seconds) {
var guide = arguments.length <= 1 || arguments[1] === undefined ? seconds : arguments[1];
return (function () {
seconds = seconds < 0 ? 0 : seconds;
var s = math.floor(seconds % 60);
var m = math.floor(seconds / 60 % 60);
var h = math.floor(seconds / 3600);
var gm = math.floor(guide / 60 % 60);
var gh = math.floor(guide / 3600);
// handle invalid times
if (isnan(seconds) || seconds === infinity) {
// '-' is false for all relational operators (e.g. <, >=) so this setting
// will add the minimum number of fields specified by the guide
h = m = s = '-';
}
// check if we need to show hours
h = h > 0 || gh > 0 ? h + ':' : '';
// if hours are showing, we may need to add a leading zero.
// always show at least one digit of minutes.
m = ((h || gm >= 10) && m < 10 ? '0' + m : m) + ':';
// check if leading zero is need for seconds
s = s < 10 ? '0' + s : s;
return h + m + s;
})();
}
exports['default'] = formattime;
module.exports = exports['default'];
},{}],136:[function(_dereq_,module,exports){
/**
* @file guid.js
*
* unique id for an element or function
* @type {number}
* @private
*/
"use strict";
exports.__esmodule = true;
exports.newguid = newguid;
var _guid = 1;
/**
* get the next unique id
*
* @return {string}
* @function newguid
*/
function newguid() {
return _guid++;
}
},{}],137:[function(_dereq_,module,exports){
/**
* @file log.js
*/
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
/**
* log plain debug messages
*/
var log = function log() {
_logtype(null, arguments);
};
/**
* keep a history of log messages
* @type {array}
*/
log.history = [];
/**
* log error messages
*/
log.error = function () {
_logtype('error', arguments);
};
/**
* log warning messages
*/
log.warn = function () {
_logtype('warn', arguments);
};
/**
* log messages to the console and history based on the type of message
*
* @param {string} type the type of message, or `null` for `log`
* @param {object} args the args to be passed to the log
* @private
* @method _logtype
*/
function _logtype(type, args) {
// convert args to an array to get array functions
var argsarray = array.prototype.slice.call(args);
// if there's no console then don't try to output messages
// they will still be stored in log.history
// was setting these once outside of this function, but containing them
// in the function makes it easier to test cases where console doesn't exist
var noop = function noop() {};
var console = _globalwindow2['default']['console'] || {
'log': noop,
'warn': noop,
'error': noop
};
if (type) {
// add the type to the front of the message
argsarray.unshift(type.touppercase() + ':');
} else {
// default to log with no prefix
type = 'log';
}
// add to history
log.history.push(argsarray);
// add console prefix after adding to history
argsarray.unshift('videojs:');
// call appropriate log function
if (console[type].apply) {
console[type].apply(console, argsarray);
} else {
// ie8 doesn't allow error.apply, but it will just join() the array anyway
console[type](argsarray.join(' '));
}
}
exports['default'] = log;
module.exports = exports['default'];
},{"global/window":2}],138:[function(_dereq_,module,exports){
/**
* @file merge-options.js
*/
'use strict';
exports.__esmodule = true;
exports['default'] = mergeoptions;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _lodashcompatobjectmerge = _dereq_('lodash-compat/object/merge');
var _lodashcompatobjectmerge2 = _interoprequiredefault(_lodashcompatobjectmerge);
function isplain(obj) {
return !!obj && typeof obj === 'object' && obj.tostring() === '[object object]' && obj.constructor === object;
}
/**
* merge customizer. video.js simply overwrites non-simple objects
* (like arrays) instead of attempting to overlay them.
* @see https://lodash.com/docs#merge
*/
var customizer = function customizer(destination, source) {
// if we're not working with a plain object, copy the value as is
// if source is an array, for instance, it will replace destination
if (!isplain(source)) {
return source;
}
// if the new value is a plain object but the first object value is not
// we need to create a new object for the first object to merge with.
// this makes it consistent with how merge() works by default
// and also protects from later changes the to first object affecting
// the second object's values.
if (!isplain(destination)) {
return mergeoptions(source);
}
};
/**
* merge one or more options objects, recursively merging **only**
* plain object properties. previously `deepmerge`.
*
* @param {...object} source one or more objects to merge
* @returns {object} a new object that is the union of all
* provided objects
* @function mergeoptions
*/
function mergeoptions() {
// contruct the call dynamically to handle the variable number of
// objects to merge
var args = array.prototype.slice.call(arguments);
// unshift an empty object into the front of the call as the target
// of the merge
args.unshift({});
// customize conflict resolution to match our historical merge behavior
args.push(customizer);
_lodashcompatobjectmerge2['default'].apply(null, args);
// return the mutated result object
return args[0];
}
module.exports = exports['default'];
},{"lodash-compat/object/merge":40}],139:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var createstyleelement = function createstyleelement(classname) {
var style = _globaldocument2['default'].createelement('style');
style.classname = classname;
return style;
};
exports.createstyleelement = createstyleelement;
var settextcontent = function settextcontent(el, content) {
if (el.stylesheet) {
el.stylesheet.csstext = content;
} else {
el.textcontent = content;
}
};
exports.settextcontent = settextcontent;
},{"global/document":1}],140:[function(_dereq_,module,exports){
'use strict';
exports.__esmodule = true;
exports.createtimeranges = createtimeranges;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _logjs = _dereq_('./log.js');
var _logjs2 = _interoprequiredefault(_logjs);
/**
* @file time-ranges.js
*
* should create a fake timerange object
* mimics an html5 time range instance, which has functions that
* return the start and end times for a range
* timeranges are returned by the buffered() method
*
* @param {(number|array)} start of a single range or an array of ranges
* @param {number} end of a single range
* @private
* @method createtimeranges
*/
function createtimeranges(start, end) {
if (array.isarray(start)) {
return createtimerangesobj(start);
} else if (start === undefined || end === undefined) {
return createtimerangesobj();
}
return createtimerangesobj([[start, end]]);
}
exports.createtimerange = createtimeranges;
function createtimerangesobj(ranges) {
if (ranges === undefined || ranges.length === 0) {
return {
length: 0,
start: function start() {
throw new error('this timeranges object is empty');
},
end: function end() {
throw new error('this timeranges object is empty');
}
};
}
return {
length: ranges.length,
start: getrange.bind(null, 'start', 0, ranges),
end: getrange.bind(null, 'end', 1, ranges)
};
}
function getrange(fnname, valueindex, ranges, rangeindex) {
if (rangeindex === undefined) {
_logjs2['default'].warn('deprecated: function \'' + fnname + '\' on \'timeranges\' called without an index argument.');
rangeindex = 0;
}
rangecheck(fnname, rangeindex, ranges.length - 1);
return ranges[rangeindex][valueindex];
}
function rangecheck(fnname, index, maxindex) {
if (index < 0 || index > maxindex) {
throw new error('failed to execute \'' + fnname + '\' on \'timeranges\': the index provided (' + index + ') is greater than or equal to the maximum bound (' + maxindex + ').');
}
}
},{"./log.js":137}],141:[function(_dereq_,module,exports){
/**
* @file to-title-case.js
*
* uppercase the first letter of a string
*
* @param {string} string string to be uppercased
* @return {string}
* @private
* @method totitlecase
*/
"use strict";
exports.__esmodule = true;
function totitlecase(string) {
return string.charat(0).touppercase() + string.slice(1);
}
exports["default"] = totitlecase;
module.exports = exports["default"];
},{}],142:[function(_dereq_,module,exports){
/**
* @file url.js
*/
'use strict';
exports.__esmodule = true;
function _interoprequiredefault(obj) { return obj && obj.__esmodule ? obj : { 'default': obj }; }
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _globalwindow = _dereq_('global/window');
var _globalwindow2 = _interoprequiredefault(_globalwindow);
/**
* resolve and parse the elements of a url
*
* @param {string} url the url to parse
* @return {object} an object of url details
* @method parseurl
*/
var parseurl = function parseurl(url) {
var props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host'];
// add the url to an anchor and let the browser parse the url
var a = _globaldocument2['default'].createelement('a');
a.href = url;
// ie8 (and 9?) fix
// ie8 doesn't parse the url correctly until the anchor is actually
// added to the body, and an innerhtml is needed to trigger the parsing
var addtobody = a.host === '' && a.protocol !== 'file:';
var div = undefined;
if (addtobody) {
div = _globaldocument2['default'].createelement('div');
div.innerhtml = '';
a = div.firstchild;
// prevent the div from affecting layout
div.setattribute('style', 'display:none; position:absolute;');
_globaldocument2['default'].body.appendchild(div);
}
// copy the specific url properties to a new object
// this is also needed for ie8 because the anchor loses its
// properties when it's removed from the dom
var details = {};
for (var i = 0; i < props.length; i++) {
details[props[i]] = a[props[i]];
}
// ie9 adds the port to the host property unlike everyone else. if
// a port identifier is added for standard ports, strip it.
if (details.protocol === 'http:') {
details.host = details.host.replace(/:80$/, '');
}
if (details.protocol === 'https:') {
details.host = details.host.replace(/:443$/, '');
}
if (addtobody) {
_globaldocument2['default'].body.removechild(div);
}
return details;
};
exports.parseurl = parseurl;
/**
* get absolute version of relative url. used to tell flash correct url.
* http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue
*
* @param {string} url url to make absolute
* @return {string} absolute url
* @private
* @method getabsoluteurl
*/
var getabsoluteurl = function getabsoluteurl(url) {
// check if absolute url
if (!url.match(/^https?:\/\//)) {
// convert to absolute url. flash hosted off-site needs an absolute url.
var div = _globaldocument2['default'].createelement('div');
div.innerhtml = 'x';
url = div.firstchild.href;
}
return url;
};
exports.getabsoluteurl = getabsoluteurl;
/**
* returns the extension of the passed file name. it will return an empty string if you pass an invalid path
*
* @param {string} path the filename path like '/path/to/file.mp4'
* @returns {string} the extension in lower case or an empty string if no extension could be found.
* @method getfileextension
*/
var getfileextension = function getfileextension(path) {
if (typeof path === 'string') {
var splitpathre = /^(\/?)([\s\s]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
var pathparts = splitpathre.exec(path);
if (pathparts) {
return pathparts.pop().tolowercase();
}
}
return '';
};
exports.getfileextension = getfileextension;
/**
* returns whether the url passed is a cross domain request or not.
*
* @param {string} url the url to check
* @return {boolean} whether it is a cross domain request or not
* @method iscrossorigin
*/
var iscrossorigin = function iscrossorigin(url) {
var winloc = _globalwindow2['default'].location;
var urlinfo = parseurl(url);
// ie8 protocol relative urls will return ':' for protocol
var srcprotocol = urlinfo.protocol === ':' ? winloc.protocol : urlinfo.protocol;
// check if url is for another domain/origin
// ie8 doesn't know location.origin, so we won't rely on it here
var crossorigin = srcprotocol + urlinfo.host !== winloc.protocol + winloc.host;
return crossorigin;
};
exports.iscrossorigin = iscrossorigin;
},{"global/document":1,"global/window":2}],143:[function(_dereq_,module,exports){
/**
* @file video.js
*/
'use strict';
exports.__esmodule = true;
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 }; }
var _globaldocument = _dereq_('global/document');
var _globaldocument2 = _interoprequiredefault(_globaldocument);
var _setup = _dereq_('./setup');
var setup = _interoprequirewildcard(_setup);
var _utilsstylesheetjs = _dereq_('./utils/stylesheet.js');
var stylesheet = _interoprequirewildcard(_utilsstylesheetjs);
var _component = _dereq_('./component');
var _component2 = _interoprequiredefault(_component);
var _eventtarget = _dereq_('./event-target');
var _eventtarget2 = _interoprequiredefault(_eventtarget);
var _utilseventsjs = _dereq_('./utils/events.js');
var events = _interoprequirewildcard(_utilseventsjs);
var _player = _dereq_('./player');
var _player2 = _interoprequiredefault(_player);
var _pluginsjs = _dereq_('./plugins.js');
var _pluginsjs2 = _interoprequiredefault(_pluginsjs);
var _srcjsutilsmergeoptionsjs = _dereq_('../../src/js/utils/merge-options.js');
var _srcjsutilsmergeoptionsjs2 = _interoprequiredefault(_srcjsutilsmergeoptionsjs);
var _utilsfnjs = _dereq_('./utils/fn.js');
var fn = _interoprequirewildcard(_utilsfnjs);
var _trackstexttrackjs = _dereq_('./tracks/text-track.js');
var _trackstexttrackjs2 = _interoprequiredefault(_trackstexttrackjs);
var _objectassign = _dereq_('object.assign');
var _objectassign2 = _interoprequiredefault(_objectassign);
var _utilstimerangesjs = _dereq_('./utils/time-ranges.js');
var _utilsformattimejs = _dereq_('./utils/format-time.js');
var _utilsformattimejs2 = _interoprequiredefault(_utilsformattimejs);
var _utilslogjs = _dereq_('./utils/log.js');
var _utilslogjs2 = _interoprequiredefault(_utilslogjs);
var _utilsdomjs = _dereq_('./utils/dom.js');
var dom = _interoprequirewildcard(_utilsdomjs);
var _utilsbrowserjs = _dereq_('./utils/browser.js');
var browser = _interoprequirewildcard(_utilsbrowserjs);
var _utilsurljs = _dereq_('./utils/url.js');
var url = _interoprequirewildcard(_utilsurljs);
var _extendjs = _dereq_('./extend.js');
var _extendjs2 = _interoprequiredefault(_extendjs);
var _lodashcompatobjectmerge = _dereq_('lodash-compat/object/merge');
var _lodashcompatobjectmerge2 = _interoprequiredefault(_lodashcompatobjectmerge);
var _utilscreatedeprecationproxyjs = _dereq_('./utils/create-deprecation-proxy.js');
var _utilscreatedeprecationproxyjs2 = _interoprequiredefault(_utilscreatedeprecationproxyjs);
var _xhr = _dereq_('xhr');
var _xhr2 = _interoprequiredefault(_xhr);
// include the built-in techs
var _techtechjs = _dereq_('./tech/tech.js');
var _techtechjs2 = _interoprequiredefault(_techtechjs);
var _techhtml5js = _dereq_('./tech/html5.js');
var _techhtml5js2 = _interoprequiredefault(_techhtml5js);
var _techflashjs = _dereq_('./tech/flash.js');
var _techflashjs2 = _interoprequiredefault(_techflashjs);
// html5 element shim for ie8
if (typeof htmlvideoelement === 'undefined') {
_globaldocument2['default'].createelement('video');
_globaldocument2['default'].createelement('audio');
_globaldocument2['default'].createelement('track');
}
/**
* doubles as the main function for users to create a player instance and also
* the main library object.
* the `videojs` function can be used to initialize or retrieve a player.
* ```js
* var myplayer = videojs('my_video_id');
* ```
*
* @param {string|element} id video element or video element id
* @param {object=} options optional options object for config/settings
* @param {function=} ready optional ready callback
* @return {player} a player instance
* @mixes videojs
* @method videojs
*/
var videojs = function videojs(id, options, ready) {
var tag = undefined; // element of id
// allow for element or id to be passed in
// string id
if (typeof id === 'string') {
// adjust for jquery id syntax
if (id.indexof('#') === 0) {
id = id.slice(1);
}
// if a player instance has already been created for this id return it.
if (videojs.getplayers()[id]) {
// if options or ready funtion are passed, warn
if (options) {
_utilslogjs2['default'].warn('player "' + id + '" is already initialised. options will not be applied.');
}
if (ready) {
videojs.getplayers()[id].ready(ready);
}
return videojs.getplayers()[id];
// otherwise get element for id
} else {
tag = dom.getel(id);
}
// id is a media element
} else {
tag = id;
}
// check for a useable element
if (!tag || !tag.nodename) {
// re: nodename, could be a box div also
throw new typeerror('the element or id supplied is not valid. (videojs)'); // returns
}
// element may have a player attr referring to an already created player instance.
// if not, set up a new player and return the instance.
return tag['player'] || _player2['default'].players[tag.playerid] || new _player2['default'](tag, options, ready);
};
// add default styles
var style = dom.$('.vjs-styles-defaults');
if (!style) {
style = stylesheet.createstyleelement('vjs-styles-defaults');
var head = dom.$('head');
head.insertbefore(style, head.firstchild);
stylesheet.settextcontent(style, '\n .video-js {\n width: 518px;\n height: 288px;\n }\n\n .vjs-fluid {\n padding-top: 56.25%\n }\n ');
}
// run auto-load players
// you have to wait at least once in case this script is loaded after your video in the dom (weird behavior only with minified version)
setup.autosetuptimeout(1, videojs);
/*
* current software version (semver)
*
* @type {string}
*/
videojs.version = '5.8.8';
/**
* the global options object. these are the settings that take effect
* if no overrides are specified when the player is created.
*
* ```js
* videojs.options.autoplay = true
* // -> all players will autoplay by default
* ```
*
* @type {object}
*/
videojs.options = _player2['default'].prototype.options_;
/**
* get an object with the currently created players, keyed by player id
*
* @return {object} the created players
* @mixes videojs
* @method getplayers
*/
videojs.getplayers = function () {
return _player2['default'].players;
};
/**
* for backward compatibility, expose players object.
*
* @deprecated
* @memberof videojs
* @property {object|proxy} players
*/
videojs.players = _utilscreatedeprecationproxyjs2['default'](_player2['default'].players, {
get: 'access to videojs.players is deprecated; use videojs.getplayers instead',
set: 'modification of videojs.players is deprecated'
});
/**
* get a component class object by name
* ```js
* var vjsbutton = videojs.getcomponent('button');
* // create a new instance of the component
* var mybutton = new vjsbutton(myplayer);
* ```
*
* @return {component} component identified by name
* @mixes videojs
* @method getcomponent
*/
videojs.getcomponent = _component2['default'].getcomponent;
/**
* register a component so it can referred to by name
* used when adding to other
* components, either through addchild
* `component.addchild('mycomponent')`
* or through default children options
* `{ children: ['mycomponent'] }`.
* ```js
* // get a component to subclass
* var vjsbutton = videojs.getcomponent('button');
* // subclass the component (see 'extend' doc for more info)
* var myspecialbutton = videojs.extend(vjsbutton, {});
* // register the new component
* vjsbutton.registercomponent('mysepcialbutton', mysepcialbutton);
* // (optionally) add the new component as a default player child
* myplayer.addchild('mysepcialbutton');
* ```
* note: you could also just initialize the component before adding.
* `component.addchild(new mycomponent());`
*
* @param {string} the class name of the component
* @param {component} the component class
* @return {component} the newly registered component
* @mixes videojs
* @method registercomponent
*/
videojs.registercomponent = function (name, comp) {
if (_techtechjs2['default'].istech(comp)) {
_utilslogjs2['default'].warn('the ' + name + ' tech was registered as a component. it should instead be registered using videojs.registertech(name, tech)');
}
_component2['default'].registercomponent.call(_component2['default'], name, comp);
};
/**
* get a tech class object by name
* ```js
* var html5 = videojs.gettech('html5');
* // create a new instance of the component
* var html5 = new html5(options);
* ```
*
* @return {tech} tech identified by name
* @mixes videojs
* @method getcomponent
*/
videojs.gettech = _techtechjs2['default'].gettech;
/**
* register a tech so it can referred to by name.
* this is used in the tech order for the player.
*
* ```js
* // get the html5 tech
* var html5 = videojs.gettech('html5');
* var mytech = videojs.extend(html5, {});
* // register the new tech
* vjsbutton.registertech('tech', mytech);
* var player = videojs('myplayer', {
* techorder: ['mytech', 'html5']
* });
* ```
*
* @param {string} the class name of the tech
* @param {tech} the tech class
* @return {tech} the newly registered tech
* @mixes videojs
* @method registertech
*/
videojs.registertech = _techtechjs2['default'].registertech;
/**
* a suite of browser and device tests
*
* @type {object}
* @private
*/
videojs.browser = browser;
/**
* whether or not the browser supports touch events. included for backward
* compatibility with 4.x, but deprecated. use `videojs.browser.touch_enabled`
* instead going forward.
*
* @deprecated
* @type {boolean}
*/
videojs.touch_enabled = browser.touch_enabled;
/**
* subclass an existing class
* mimics es6 subclassing with the `extend` keyword
* ```js
* // create a basic javascript 'class'
* function myclass(name){
* // set a property at initialization
* this.myname = name;
* }
* // create an instance method
* myclass.prototype.saymyname = function(){
* alert(this.myname);
* };
* // subclass the exisitng class and change the name
* // when initializing
* var mysubclass = videojs.extend(myclass, {
* constructor: function(name) {
* // call the super class constructor for the subclass
* myclass.call(this, name)
* }
* });
* // create an instance of the new sub class
* var myinstance = new mysubclass('john');
* myinstance.saymyname(); // -> should alert "john"
* ```
*
* @param {function} the class to subclass
* @param {object} an object including instace methods for the new class
* optionally including a `constructor` function
* @return {function} the newly created subclass
* @mixes videojs
* @method extend
*/
videojs.extend = _extendjs2['default'];
/**
* merge two options objects recursively
* performs a deep merge like lodash.merge but **only merges plain objects**
* (not arrays, elements, anything else)
* other values will be copied directly from the second object.
* ```js
* var defaultoptions = {
* foo: true,
* bar: {
* a: true,
* b: [1,2,3]
* }
* };
* var newoptions = {
* foo: false,
* bar: {
* b: [4,5,6]
* }
* };
* var result = videojs.mergeoptions(defaultoptions, newoptions);
* // result.foo = false;
* // result.bar.a = true;
* // result.bar.b = [4,5,6];
* ```
*
* @param {object} defaults the options object whose values will be overriden
* @param {object} overrides the options object with values to override the first
* @param {object} etc any number of additional options objects
*
* @return {object} a new object with the merged values
* @mixes videojs
* @method mergeoptions
*/
videojs.mergeoptions = _srcjsutilsmergeoptionsjs2['default'];
/**
* change the context (this) of a function
*
* videojs.bind(newcontext, function(){
* this === newcontext
* });
*
* note: as of v5.0 we require an es5 shim, so you should use the native
* `function(){}.bind(newcontext);` instead of this.
*
* @param {*} context the object to bind as scope
* @param {function} fn the function to be bound to a scope
* @param {number=} uid an optional unique id for the function to be set
* @return {function}
*/
videojs.bind = fn.bind;
/**
* create a video.js player plugin
* plugins are only initialized when options for the plugin are included
* in the player options, or the plugin function on the player instance is
* called.
* **see the plugin guide in the docs for a more detailed example**
* ```js
* // make a plugin that alerts when the player plays
* videojs.plugin('myplugin', function(mypluginoptions) {
* mypluginoptions = mypluginoptions || {};
*
* var player = this;
* var alerttext = mypluginoptions.text || 'player is playing!'
*
* player.on('play', function(){
* alert(alerttext);
* });
* });
* // usage examples
* // example 1: new player with plugin options, call plugin immediately
* var player1 = videojs('idone', {
* myplugin: {
* text: 'custom text!'
* }
* });
* // click play
* // --> should alert 'custom text!'
* // example 3: new player, initialize plugin later
* var player3 = videojs('idthree');
* // click play
* // --> no alert
* // click pause
* // initialize plugin using the plugin function on the player instance
* player3.myplugin({
* text: 'plugin added later!'
* });
* // click play
* // --> should alert 'plugin added later!'
* ```
*
* @param {string} name the plugin name
* @param {function} fn the plugin function that will be called with options
* @mixes videojs
* @method plugin
*/
videojs.plugin = _pluginsjs2['default'];
/**
* adding languages so that they're available to all players.
* ```js
* videojs.addlanguage('es', { 'hello': 'hola' });
* ```
*
* @param {string} code the language code or dictionary property
* @param {object} data the data values to be translated
* @return {object} the resulting language dictionary object
* @mixes videojs
* @method addlanguage
*/
videojs.addlanguage = function (code, data) {
var _merge;
code = ('' + code).tolowercase();
return _lodashcompatobjectmerge2['default'](videojs.options.languages, (_merge = {}, _merge[code] = data, _merge))[code];
};
/**
* log debug messages.
*
* @param {...object} messages one or more messages to log
*/
videojs.log = _utilslogjs2['default'];
/**
* creates an emulated timerange object.
*
* @param {number|array} start start time in seconds or an array of ranges
* @param {number} end end time in seconds
* @return {object} fake timerange object
* @method createtimerange
*/
videojs.createtimerange = videojs.createtimeranges = _utilstimerangesjs.createtimeranges;
/**
* format seconds as a time string, h:mm:ss or m:ss
* supplying a guide (in seconds) will force a number of leading zeros
* to cover the length of the guide
*
* @param {number} seconds number of seconds to be turned into a string
* @param {number} guide number (in seconds) to model the string after
* @return {string} time formatted as h:mm:ss or m:ss
* @method formattime
*/
videojs.formattime = _utilsformattimejs2['default'];
/**
* resolve and parse the elements of a url
*
* @param {string} url the url to parse
* @return {object} an object of url details
* @method parseurl
*/
videojs.parseurl = url.parseurl;
/**
* returns whether the url passed is a cross domain request or not.
*
* @param {string} url the url to check
* @return {boolean} whether it is a cross domain request or not
* @method iscrossorigin
*/
videojs.iscrossorigin = url.iscrossorigin;
/**
* event target class.
*
* @type {function}
*/
videojs.eventtarget = _eventtarget2['default'];
/**
* add an event listener to element
* it stores the handler function in a separate cache object
* and adds a generic handler to the element's event,
* along with a unique id (guid) to the element.
*
* @param {element|object} elem element or object to bind listeners to
* @param {string|array} type type of event to bind to.
* @param {function} fn event listener.
* @method on
*/
videojs.on = events.on;
/**
* trigger a listener only once for an event
*
* @param {element|object} elem element or object to
* @param {string|array} type name/type of event
* @param {function} fn event handler function
* @method one
*/
videojs.one = events.one;
/**
* removes event listeners from an element
*
* @param {element|object} elem object to remove listeners from
* @param {string|array=} type type of listener to remove. don't include to remove all events from element.
* @param {function} fn specific listener to remove. don't include to remove listeners for an event type.
* @method off
*/
videojs.off = events.off;
/**
* trigger an event for an element
*
* @param {element|object} elem element to trigger an event on
* @param {event|object|string} event a string (the type) or an event object with a type attribute
* @param {object} [hash] data hash to pass along with the event
* @return {boolean=} returned only if default was prevented
* @method trigger
*/
videojs.trigger = events.trigger;
/**
* a cross-browser xmlhttprequest wrapper. here's a simple example:
*
* videojs.xhr({
* body: somejsonstring,
* uri: "/foo",
* headers: {
* "content-type": "application/json"
* }
* }, function (err, resp, body) {
* // check resp.statuscode
* });
*
* check out the [full
* documentation](https://github.com/raynos/xhr/blob/v2.1.0/readme.md)
* for more options.
*
* @param {object} options settings for the request.
* @return {xmlhttprequest|xdomainrequest} the request object.
* @see https://github.com/raynos/xhr
*/
videojs.xhr = _xhr2['default'];
/**
* texttrack class
*
* @type {function}
*/
videojs.texttrack = _trackstexttrackjs2['default'];
/**
* determines, via duck typing, whether or not a value is a dom element.
*
* @method isel
* @param {mixed} value
* @return {boolean}
*/
videojs.isel = dom.isel;
/**
* determines, via duck typing, whether or not a value is a text node.
*
* @method istextnode
* @param {mixed} value
* @return {boolean}
*/
videojs.istextnode = dom.istextnode;
/**
* creates an element and applies properties.
*
* @method createel
* @param {string} [tagname='div'] name of tag to be created.
* @param {object} [properties={}] element properties to be applied.
* @param {object} [attributes={}] element attributes to be applied.
* @return {element}
*/
videojs.createel = dom.createel;
/**
* check if an element has a css class
*
* @method hasclass
* @param {element} element element to check
* @param {string} classtocheck classname to check
*/
videojs.hasclass = dom.haselclass;
/**
* add a css class name to an element
*
* @method addclass
* @param {element} element element to add class name to
* @param {string} classtoadd classname to add
*/
videojs.addclass = dom.addelclass;
/**
* remove a css class name from an element
*
* @method removeclass
* @param {element} element element to remove from class name
* @param {string} classtoremove classname to remove
*/
videojs.removeclass = dom.removeelclass;
/**
* adds or removes a css class name on an element depending on an optional
* condition or the presence/absence of the class name.
*
* @method toggleelclass
* @param {element} element
* @param {string} classtotoggle
* @param {boolean|function} [predicate]
* can be a function that returns a boolean. if `true`, the class
* will be added; if `false`, the class will be removed. if not
* given, the class will be added if not present and vice versa.
*/
videojs.toggleclass = dom.toggleelclass;
/**
* apply attributes to an html element.
*
* @method setattributes
* @param {element} el target element.
* @param {object=} attributes element attributes to be applied.
*/
videojs.setattributes = dom.setelattributes;
/**
* get an element's attribute values, as defined on the html tag
* attributes are not the same as properties. they're defined on the tag
* or with setattribute (which shouldn't be used with html)
* this will return true or false for boolean attributes.
*
* @method getattributes
* @param {element} tag element from which to get tag attributes
* @return {object}
*/
videojs.getattributes = dom.getelattributes;
/**
* empties the contents of an element.
*
* @method emptyel
* @param {element} el
* @return {element}
*/
videojs.emptyel = dom.emptyel;
/**
* normalizes and appends content to an element.
*
* the content for an element can be passed in multiple types and
* combinations, whose behavior is as follows:
*
* - string
* normalized into a text node.
*
* - element, textnode
* passed through.
*
* - array
* a one-dimensional array of strings, elements, nodes, or functions (which
* return single strings, elements, or nodes).
*
* - function
* if the sole argument, is expected to produce a string, element,
* node, or array.
*
* @method appendcontent
* @param {element} el
* @param {string|element|textnode|array|function} content
* @return {element}
*/
videojs.appendcontent = dom.appendcontent;
/**
* normalizes and inserts content into an element; this is identical to
* `appendcontent()`, except it empties the element first.
*
* the content for an element can be passed in multiple types and
* combinations, whose behavior is as follows:
*
* - string
* normalized into a text node.
*
* - element, textnode
* passed through.
*
* - array
* a one-dimensional array of strings, elements, nodes, or functions (which
* return single strings, elements, or nodes).
*
* - function
* if the sole argument, is expected to produce a string, element,
* node, or array.
*
* @method insertcontent
* @param {element} el
* @param {string|element|textnode|array|function} content
* @return {element}
*/
videojs.insertcontent = dom.insertcontent;
/*
* custom universal module definition (umd)
*
* video.js will never be a non-browser lib so we can simplify umd a bunch and
* still support requirejs and browserify. this also needs to be closure
* compiler compatible, so string keys are used.
*/
if (typeof define === 'function' && define['amd']) {
define('videojs', [], function () {
return videojs;
});
// checking that module is an object too because of umdjs/umd#35
} else if (typeof exports === 'object' && typeof module === 'object') {
module['exports'] = videojs;
}
exports['default'] = videojs;
module.exports = exports['default'];
},{"../../src/js/utils/merge-options.js":138,"./component":67,"./event-target":99,"./extend.js":100,"./player":108,"./plugins.js":109,"./setup":113,"./tech/flash.js":116,"./tech/html5.js":117,"./tech/tech.js":119,"./tracks/text-track.js":128,"./utils/browser.js":129,"./utils/create-deprecation-proxy.js":131,"./utils/dom.js":132,"./utils/events.js":133,"./utils/fn.js":134,"./utils/format-time.js":135,"./utils/log.js":137,"./utils/stylesheet.js":139,"./utils/time-ranges.js":140,"./utils/url.js":142,"global/document":1,"lodash-compat/object/merge":40,"object.assign":45,"xhr":56}]},{},[143])(143)
});
//# sourcemappingurl=video.js.map
/* vtt.js - v0.12.1 (https://github.com/mozilla/vtt.js) built on 08-07-2015 */
(function(root) {
var vttjs = root.vttjs = {};
var cueshim = vttjs.vttcue;
var regionshim = vttjs.vttregion;
var oldvttcue = root.vttcue;
var oldvttregion = root.vttregion;
vttjs.shim = function() {
vttjs.vttcue = cueshim;
vttjs.vttregion = regionshim;
};
vttjs.restore = function() {
vttjs.vttcue = oldvttcue;
vttjs.vttregion = oldvttregion;
};
}(this));
/**
* copyright 2013 vtt.js contributors
*
* licensed under the apache license, version 2.0 (the "license");
* you may not use this file except in compliance with the license.
* you may obtain a copy of the license at
*
* http://www.apache.org/licenses/license-2.0
*
* unless required by applicable law or agreed to in writing, software
* distributed under the license is distributed on an "as is" basis,
* without warranties or conditions of any kind, either express or implied.
* see the license for the specific language governing permissions and
* limitations under the license.
*/
(function(root, vttjs) {
var autokeyword = "auto";
var directionsetting = {
"": true,
"lr": true,
"rl": true
};
var alignsetting = {
"start": true,
"middle": true,
"end": true,
"left": true,
"right": true
};
function finddirectionsetting(value) {
if (typeof value !== "string") {
return false;
}
var dir = directionsetting[value.tolowercase()];
return dir ? value.tolowercase() : false;
}
function findalignsetting(value) {
if (typeof value !== "string") {
return false;
}
var align = alignsetting[value.tolowercase()];
return align ? value.tolowercase() : false;
}
function extend(obj) {
var i = 1;
for (; i < arguments.length; i++) {
var cobj = arguments[i];
for (var p in cobj) {
obj[p] = cobj[p];
}
}
return obj;
}
function vttcue(starttime, endtime, text) {
var cue = this;
var isie8 = (/msie\s8\.0/).test(navigator.useragent);
var baseobj = {};
if (isie8) {
cue = document.createelement('custom');
} else {
baseobj.enumerable = true;
}
/**
* shim implementation specific properties. these properties are not in
* the spec.
*/
// lets us know when the vttcue's data has changed in such a way that we need
// to recompute its display state. this lets us compute its display state
// lazily.
cue.hasbeenreset = false;
/**
* vttcue and texttrackcue properties
* http://dev.w3.org/html5/webvtt/#vttcue-interface
*/
var _id = "";
var _pauseonexit = false;
var _starttime = starttime;
var _endtime = endtime;
var _text = text;
var _region = null;
var _vertical = "";
var _snaptolines = true;
var _line = "auto";
var _linealign = "start";
var _position = 50;
var _positionalign = "middle";
var _size = 50;
var _align = "middle";
object.defineproperty(cue,
"id", extend({}, baseobj, {
get: function() {
return _id;
},
set: function(value) {
_id = "" + value;
}
}));
object.defineproperty(cue,
"pauseonexit", extend({}, baseobj, {
get: function() {
return _pauseonexit;
},
set: function(value) {
_pauseonexit = !!value;
}
}));
object.defineproperty(cue,
"starttime", extend({}, baseobj, {
get: function() {
return _starttime;
},
set: function(value) {
if (typeof value !== "number") {
throw new typeerror("start time must be set to a number.");
}
_starttime = value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"endtime", extend({}, baseobj, {
get: function() {
return _endtime;
},
set: function(value) {
if (typeof value !== "number") {
throw new typeerror("end time must be set to a number.");
}
_endtime = value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"text", extend({}, baseobj, {
get: function() {
return _text;
},
set: function(value) {
_text = "" + value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"region", extend({}, baseobj, {
get: function() {
return _region;
},
set: function(value) {
_region = value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"vertical", extend({}, baseobj, {
get: function() {
return _vertical;
},
set: function(value) {
var setting = finddirectionsetting(value);
// have to check for false because the setting an be an empty string.
if (setting === false) {
throw new syntaxerror("an invalid or illegal string was specified.");
}
_vertical = setting;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"snaptolines", extend({}, baseobj, {
get: function() {
return _snaptolines;
},
set: function(value) {
_snaptolines = !!value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"line", extend({}, baseobj, {
get: function() {
return _line;
},
set: function(value) {
if (typeof value !== "number" && value !== autokeyword) {
throw new syntaxerror("an invalid number or illegal string was specified.");
}
_line = value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"linealign", extend({}, baseobj, {
get: function() {
return _linealign;
},
set: function(value) {
var setting = findalignsetting(value);
if (!setting) {
throw new syntaxerror("an invalid or illegal string was specified.");
}
_linealign = setting;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"position", extend({}, baseobj, {
get: function() {
return _position;
},
set: function(value) {
if (value < 0 || value > 100) {
throw new error("position must be between 0 and 100.");
}
_position = value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"positionalign", extend({}, baseobj, {
get: function() {
return _positionalign;
},
set: function(value) {
var setting = findalignsetting(value);
if (!setting) {
throw new syntaxerror("an invalid or illegal string was specified.");
}
_positionalign = setting;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"size", extend({}, baseobj, {
get: function() {
return _size;
},
set: function(value) {
if (value < 0 || value > 100) {
throw new error("size must be between 0 and 100.");
}
_size = value;
this.hasbeenreset = true;
}
}));
object.defineproperty(cue,
"align", extend({}, baseobj, {
get: function() {
return _align;
},
set: function(value) {
var setting = findalignsetting(value);
if (!setting) {
throw new syntaxerror("an invalid or illegal string was specified.");
}
_align = setting;
this.hasbeenreset = true;
}
}));
/**
* other