github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/video-js-5.9.0/alt/video.novtt.js (about) 1 /** 2 * @license 3 * Video.js 5.9.0 <http://videojs.com/> 4 * Copyright Brightcove, Inc. <https://www.brightcove.com/> 5 * Available under Apache License Version 2.0 6 * <https://github.com/videojs/video.js/blob/master/LICENSE> 7 */ 8 9 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.videojs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){ 10 (function (global){ 11 var topLevel = typeof global !== 'undefined' ? global : 12 typeof window !== 'undefined' ? window : {} 13 var minDoc = _dereq_('min-document'); 14 15 if (typeof document !== 'undefined') { 16 module.exports = document; 17 } else { 18 var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; 19 20 if (!doccy) { 21 doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; 22 } 23 24 module.exports = doccy; 25 } 26 27 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 28 //# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9nbG9iYWwvZG9jdW1lbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6XG4gICAgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fVxudmFyIG1pbkRvYyA9IHJlcXVpcmUoJ21pbi1kb2N1bWVudCcpO1xuXG5pZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG59IGVsc2Uge1xuICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbJ19fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDQnXSA9IG1pbkRvYztcbiAgICB9XG5cbiAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xufVxuIl19 29 },{"min-document":3}],2:[function(_dereq_,module,exports){ 30 (function (global){ 31 if (typeof window !== "undefined") { 32 module.exports = window; 33 } else if (typeof global !== "undefined") { 34 module.exports = global; 35 } else if (typeof self !== "undefined"){ 36 module.exports = self; 37 } else { 38 module.exports = {}; 39 } 40 41 }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 42 //# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9nbG9iYWwvd2luZG93LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IHdpbmRvdztcbn0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsO1xufSBlbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIil7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBzZWxmO1xufSBlbHNlIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IHt9O1xufVxuIl19 43 },{}],3:[function(_dereq_,module,exports){ 44 45 },{}],4:[function(_dereq_,module,exports){ 46 var getNative = _dereq_('../internal/getNative'); 47 48 /* Native method references for those with the same name as other `lodash` methods. */ 49 var nativeNow = getNative(Date, 'now'); 50 51 /** 52 * Gets the number of milliseconds that have elapsed since the Unix epoch 53 * (1 January 1970 00:00:00 UTC). 54 * 55 * @static 56 * @memberOf _ 57 * @category Date 58 * @example 59 * 60 * _.defer(function(stamp) { 61 * console.log(_.now() - stamp); 62 * }, _.now()); 63 * // => logs the number of milliseconds it took for the deferred function to be invoked 64 */ 65 var now = nativeNow || function() { 66 return new Date().getTime(); 67 }; 68 69 module.exports = now; 70 71 },{"../internal/getNative":20}],5:[function(_dereq_,module,exports){ 72 var isObject = _dereq_('../lang/isObject'), 73 now = _dereq_('../date/now'); 74 75 /** Used as the `TypeError` message for "Functions" methods. */ 76 var FUNC_ERROR_TEXT = 'Expected a function'; 77 78 /* Native method references for those with the same name as other `lodash` methods. */ 79 var nativeMax = Math.max; 80 81 /** 82 * Creates a debounced function that delays invoking `func` until after `wait` 83 * milliseconds have elapsed since the last time the debounced function was 84 * invoked. The debounced function comes with a `cancel` method to cancel 85 * delayed invocations. Provide an options object to indicate that `func` 86 * should be invoked on the leading and/or trailing edge of the `wait` timeout. 87 * Subsequent calls to the debounced function return the result of the last 88 * `func` invocation. 89 * 90 * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked 91 * on the trailing edge of the timeout only if the the debounced function is 92 * invoked more than once during the `wait` timeout. 93 * 94 * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) 95 * for details over the differences between `_.debounce` and `_.throttle`. 96 * 97 * @static 98 * @memberOf _ 99 * @category Function 100 * @param {Function} func The function to debounce. 101 * @param {number} [wait=0] The number of milliseconds to delay. 102 * @param {Object} [options] The options object. 103 * @param {boolean} [options.leading=false] Specify invoking on the leading 104 * edge of the timeout. 105 * @param {number} [options.maxWait] The maximum time `func` is allowed to be 106 * delayed before it's invoked. 107 * @param {boolean} [options.trailing=true] Specify invoking on the trailing 108 * edge of the timeout. 109 * @returns {Function} Returns the new debounced function. 110 * @example 111 * 112 * // avoid costly calculations while the window size is in flux 113 * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); 114 * 115 * // invoke `sendMail` when the click event is fired, debouncing subsequent calls 116 * jQuery('#postbox').on('click', _.debounce(sendMail, 300, { 117 * 'leading': true, 118 * 'trailing': false 119 * })); 120 * 121 * // ensure `batchLog` is invoked once after 1 second of debounced calls 122 * var source = new EventSource('/stream'); 123 * jQuery(source).on('message', _.debounce(batchLog, 250, { 124 * 'maxWait': 1000 125 * })); 126 * 127 * // cancel a debounced call 128 * var todoChanges = _.debounce(batchLog, 1000); 129 * Object.observe(models.todo, todoChanges); 130 * 131 * Object.observe(models, function(changes) { 132 * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) { 133 * todoChanges.cancel(); 134 * } 135 * }, ['delete']); 136 * 137 * // ...at some point `models.todo` is changed 138 * models.todo.completed = true; 139 * 140 * // ...before 1 second has passed `models.todo` is deleted 141 * // which cancels the debounced `todoChanges` call 142 * delete models.todo; 143 */ 144 function debounce(func, wait, options) { 145 var args, 146 maxTimeoutId, 147 result, 148 stamp, 149 thisArg, 150 timeoutId, 151 trailingCall, 152 lastCalled = 0, 153 maxWait = false, 154 trailing = true; 155 156 if (typeof func != 'function') { 157 throw new TypeError(FUNC_ERROR_TEXT); 158 } 159 wait = wait < 0 ? 0 : (+wait || 0); 160 if (options === true) { 161 var leading = true; 162 trailing = false; 163 } else if (isObject(options)) { 164 leading = !!options.leading; 165 maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait); 166 trailing = 'trailing' in options ? !!options.trailing : trailing; 167 } 168 169 function cancel() { 170 if (timeoutId) { 171 clearTimeout(timeoutId); 172 } 173 if (maxTimeoutId) { 174 clearTimeout(maxTimeoutId); 175 } 176 lastCalled = 0; 177 maxTimeoutId = timeoutId = trailingCall = undefined; 178 } 179 180 function complete(isCalled, id) { 181 if (id) { 182 clearTimeout(id); 183 } 184 maxTimeoutId = timeoutId = trailingCall = undefined; 185 if (isCalled) { 186 lastCalled = now(); 187 result = func.apply(thisArg, args); 188 if (!timeoutId && !maxTimeoutId) { 189 args = thisArg = undefined; 190 } 191 } 192 } 193 194 function delayed() { 195 var remaining = wait - (now() - stamp); 196 if (remaining <= 0 || remaining > wait) { 197 complete(trailingCall, maxTimeoutId); 198 } else { 199 timeoutId = setTimeout(delayed, remaining); 200 } 201 } 202 203 function maxDelayed() { 204 complete(trailing, timeoutId); 205 } 206 207 function debounced() { 208 args = arguments; 209 stamp = now(); 210 thisArg = this; 211 trailingCall = trailing && (timeoutId || !leading); 212 213 if (maxWait === false) { 214 var leadingCall = leading && !timeoutId; 215 } else { 216 if (!maxTimeoutId && !leading) { 217 lastCalled = stamp; 218 } 219 var remaining = maxWait - (stamp - lastCalled), 220 isCalled = remaining <= 0 || remaining > maxWait; 221 222 if (isCalled) { 223 if (maxTimeoutId) { 224 maxTimeoutId = clearTimeout(maxTimeoutId); 225 } 226 lastCalled = stamp; 227 result = func.apply(thisArg, args); 228 } 229 else if (!maxTimeoutId) { 230 maxTimeoutId = setTimeout(maxDelayed, remaining); 231 } 232 } 233 if (isCalled && timeoutId) { 234 timeoutId = clearTimeout(timeoutId); 235 } 236 else if (!timeoutId && wait !== maxWait) { 237 timeoutId = setTimeout(delayed, wait); 238 } 239 if (leadingCall) { 240 isCalled = true; 241 result = func.apply(thisArg, args); 242 } 243 if (isCalled && !timeoutId && !maxTimeoutId) { 244 args = thisArg = undefined; 245 } 246 return result; 247 } 248 debounced.cancel = cancel; 249 return debounced; 250 } 251 252 module.exports = debounce; 253 254 },{"../date/now":4,"../lang/isObject":33}],6:[function(_dereq_,module,exports){ 255 /** Used as the `TypeError` message for "Functions" methods. */ 256 var FUNC_ERROR_TEXT = 'Expected a function'; 257 258 /* Native method references for those with the same name as other `lodash` methods. */ 259 var nativeMax = Math.max; 260 261 /** 262 * Creates a function that invokes `func` with the `this` binding of the 263 * created function and arguments from `start` and beyond provided as an array. 264 * 265 * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/Web/JavaScript/Reference/Functions/rest_parameters). 266 * 267 * @static 268 * @memberOf _ 269 * @category Function 270 * @param {Function} func The function to apply a rest parameter to. 271 * @param {number} [start=func.length-1] The start position of the rest parameter. 272 * @returns {Function} Returns the new function. 273 * @example 274 * 275 * var say = _.restParam(function(what, names) { 276 * return what + ' ' + _.initial(names).join(', ') + 277 * (_.size(names) > 1 ? ', & ' : '') + _.last(names); 278 * }); 279 * 280 * say('hello', 'fred', 'barney', 'pebbles'); 281 * // => 'hello fred, barney, & pebbles' 282 */ 283 function restParam(func, start) { 284 if (typeof func != 'function') { 285 throw new TypeError(FUNC_ERROR_TEXT); 286 } 287 start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0); 288 return function() { 289 var args = arguments, 290 index = -1, 291 length = nativeMax(args.length - start, 0), 292 rest = Array(length); 293 294 while (++index < length) { 295 rest[index] = args[start + index]; 296 } 297 switch (start) { 298 case 0: return func.call(this, rest); 299 case 1: return func.call(this, args[0], rest); 300 case 2: return func.call(this, args[0], args[1], rest); 301 } 302 var otherArgs = Array(start + 1); 303 index = -1; 304 while (++index < start) { 305 otherArgs[index] = args[index]; 306 } 307 otherArgs[start] = rest; 308 return func.apply(this, otherArgs); 309 }; 310 } 311 312 module.exports = restParam; 313 314 },{}],7:[function(_dereq_,module,exports){ 315 var debounce = _dereq_('./debounce'), 316 isObject = _dereq_('../lang/isObject'); 317 318 /** Used as the `TypeError` message for "Functions" methods. */ 319 var FUNC_ERROR_TEXT = 'Expected a function'; 320 321 /** 322 * Creates a throttled function that only invokes `func` at most once per 323 * every `wait` milliseconds. The throttled function comes with a `cancel` 324 * method to cancel delayed invocations. Provide an options object to indicate 325 * that `func` should be invoked on the leading and/or trailing edge of the 326 * `wait` timeout. Subsequent calls to the throttled function return the 327 * result of the last `func` call. 328 * 329 * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked 330 * on the trailing edge of the timeout only if the the throttled function is 331 * invoked more than once during the `wait` timeout. 332 * 333 * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation) 334 * for details over the differences between `_.throttle` and `_.debounce`. 335 * 336 * @static 337 * @memberOf _ 338 * @category Function 339 * @param {Function} func The function to throttle. 340 * @param {number} [wait=0] The number of milliseconds to throttle invocations to. 341 * @param {Object} [options] The options object. 342 * @param {boolean} [options.leading=true] Specify invoking on the leading 343 * edge of the timeout. 344 * @param {boolean} [options.trailing=true] Specify invoking on the trailing 345 * edge of the timeout. 346 * @returns {Function} Returns the new throttled function. 347 * @example 348 * 349 * // avoid excessively updating the position while scrolling 350 * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); 351 * 352 * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes 353 * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, { 354 * 'trailing': false 355 * })); 356 * 357 * // cancel a trailing throttled call 358 * jQuery(window).on('popstate', throttled.cancel); 359 */ 360 function throttle(func, wait, options) { 361 var leading = true, 362 trailing = true; 363 364 if (typeof func != 'function') { 365 throw new TypeError(FUNC_ERROR_TEXT); 366 } 367 if (options === false) { 368 leading = false; 369 } else if (isObject(options)) { 370 leading = 'leading' in options ? !!options.leading : leading; 371 trailing = 'trailing' in options ? !!options.trailing : trailing; 372 } 373 return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing }); 374 } 375 376 module.exports = throttle; 377 378 },{"../lang/isObject":33,"./debounce":5}],8:[function(_dereq_,module,exports){ 379 /** 380 * Copies the values of `source` to `array`. 381 * 382 * @private 383 * @param {Array} source The array to copy values from. 384 * @param {Array} [array=[]] The array to copy values to. 385 * @returns {Array} Returns `array`. 386 */ 387 function arrayCopy(source, array) { 388 var index = -1, 389 length = source.length; 390 391 array || (array = Array(length)); 392 while (++index < length) { 393 array[index] = source[index]; 394 } 395 return array; 396 } 397 398 module.exports = arrayCopy; 399 400 },{}],9:[function(_dereq_,module,exports){ 401 /** 402 * A specialized version of `_.forEach` for arrays without support for callback 403 * shorthands and `this` binding. 404 * 405 * @private 406 * @param {Array} array The array to iterate over. 407 * @param {Function} iteratee The function invoked per iteration. 408 * @returns {Array} Returns `array`. 409 */ 410 function arrayEach(array, iteratee) { 411 var index = -1, 412 length = array.length; 413 414 while (++index < length) { 415 if (iteratee(array[index], index, array) === false) { 416 break; 417 } 418 } 419 return array; 420 } 421 422 module.exports = arrayEach; 423 424 },{}],10:[function(_dereq_,module,exports){ 425 /** 426 * Copies properties of `source` to `object`. 427 * 428 * @private 429 * @param {Object} source The object to copy properties from. 430 * @param {Array} props The property names to copy. 431 * @param {Object} [object={}] The object to copy properties to. 432 * @returns {Object} Returns `object`. 433 */ 434 function baseCopy(source, props, object) { 435 object || (object = {}); 436 437 var index = -1, 438 length = props.length; 439 440 while (++index < length) { 441 var key = props[index]; 442 object[key] = source[key]; 443 } 444 return object; 445 } 446 447 module.exports = baseCopy; 448 449 },{}],11:[function(_dereq_,module,exports){ 450 var createBaseFor = _dereq_('./createBaseFor'); 451 452 /** 453 * The base implementation of `baseForIn` and `baseForOwn` which iterates 454 * over `object` properties returned by `keysFunc` invoking `iteratee` for 455 * each property. Iteratee functions may exit iteration early by explicitly 456 * returning `false`. 457 * 458 * @private 459 * @param {Object} object The object to iterate over. 460 * @param {Function} iteratee The function invoked per iteration. 461 * @param {Function} keysFunc The function to get the keys of `object`. 462 * @returns {Object} Returns `object`. 463 */ 464 var baseFor = createBaseFor(); 465 466 module.exports = baseFor; 467 468 },{"./createBaseFor":18}],12:[function(_dereq_,module,exports){ 469 var baseFor = _dereq_('./baseFor'), 470 keysIn = _dereq_('../object/keysIn'); 471 472 /** 473 * The base implementation of `_.forIn` without support for callback 474 * shorthands and `this` binding. 475 * 476 * @private 477 * @param {Object} object The object to iterate over. 478 * @param {Function} iteratee The function invoked per iteration. 479 * @returns {Object} Returns `object`. 480 */ 481 function baseForIn(object, iteratee) { 482 return baseFor(object, iteratee, keysIn); 483 } 484 485 module.exports = baseForIn; 486 487 },{"../object/keysIn":39,"./baseFor":11}],13:[function(_dereq_,module,exports){ 488 var arrayEach = _dereq_('./arrayEach'), 489 baseMergeDeep = _dereq_('./baseMergeDeep'), 490 isArray = _dereq_('../lang/isArray'), 491 isArrayLike = _dereq_('./isArrayLike'), 492 isObject = _dereq_('../lang/isObject'), 493 isObjectLike = _dereq_('./isObjectLike'), 494 isTypedArray = _dereq_('../lang/isTypedArray'), 495 keys = _dereq_('../object/keys'); 496 497 /** 498 * The base implementation of `_.merge` without support for argument juggling, 499 * multiple sources, and `this` binding `customizer` functions. 500 * 501 * @private 502 * @param {Object} object The destination object. 503 * @param {Object} source The source object. 504 * @param {Function} [customizer] The function to customize merged values. 505 * @param {Array} [stackA=[]] Tracks traversed source objects. 506 * @param {Array} [stackB=[]] Associates values with source counterparts. 507 * @returns {Object} Returns `object`. 508 */ 509 function baseMerge(object, source, customizer, stackA, stackB) { 510 if (!isObject(object)) { 511 return object; 512 } 513 var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)), 514 props = isSrcArr ? undefined : keys(source); 515 516 arrayEach(props || source, function(srcValue, key) { 517 if (props) { 518 key = srcValue; 519 srcValue = source[key]; 520 } 521 if (isObjectLike(srcValue)) { 522 stackA || (stackA = []); 523 stackB || (stackB = []); 524 baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB); 525 } 526 else { 527 var value = object[key], 528 result = customizer ? customizer(value, srcValue, key, object, source) : undefined, 529 isCommon = result === undefined; 530 531 if (isCommon) { 532 result = srcValue; 533 } 534 if ((result !== undefined || (isSrcArr && !(key in object))) && 535 (isCommon || (result === result ? (result !== value) : (value === value)))) { 536 object[key] = result; 537 } 538 } 539 }); 540 return object; 541 } 542 543 module.exports = baseMerge; 544 545 },{"../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){ 546 var arrayCopy = _dereq_('./arrayCopy'), 547 isArguments = _dereq_('../lang/isArguments'), 548 isArray = _dereq_('../lang/isArray'), 549 isArrayLike = _dereq_('./isArrayLike'), 550 isPlainObject = _dereq_('../lang/isPlainObject'), 551 isTypedArray = _dereq_('../lang/isTypedArray'), 552 toPlainObject = _dereq_('../lang/toPlainObject'); 553 554 /** 555 * A specialized version of `baseMerge` for arrays and objects which performs 556 * deep merges and tracks traversed objects enabling objects with circular 557 * references to be merged. 558 * 559 * @private 560 * @param {Object} object The destination object. 561 * @param {Object} source The source object. 562 * @param {string} key The key of the value to merge. 563 * @param {Function} mergeFunc The function to merge values. 564 * @param {Function} [customizer] The function to customize merged values. 565 * @param {Array} [stackA=[]] Tracks traversed source objects. 566 * @param {Array} [stackB=[]] Associates values with source counterparts. 567 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. 568 */ 569 function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) { 570 var length = stackA.length, 571 srcValue = source[key]; 572 573 while (length--) { 574 if (stackA[length] == srcValue) { 575 object[key] = stackB[length]; 576 return; 577 } 578 } 579 var value = object[key], 580 result = customizer ? customizer(value, srcValue, key, object, source) : undefined, 581 isCommon = result === undefined; 582 583 if (isCommon) { 584 result = srcValue; 585 if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) { 586 result = isArray(value) 587 ? value 588 : (isArrayLike(value) ? arrayCopy(value) : []); 589 } 590 else if (isPlainObject(srcValue) || isArguments(srcValue)) { 591 result = isArguments(value) 592 ? toPlainObject(value) 593 : (isPlainObject(value) ? value : {}); 594 } 595 else { 596 isCommon = false; 597 } 598 } 599 // Add the source value to the stack of traversed objects and associate 600 // it with its merged value. 601 stackA.push(srcValue); 602 stackB.push(result); 603 604 if (isCommon) { 605 // Recursively merge objects and arrays (susceptible to call stack limits). 606 object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB); 607 } else if (result === result ? (result !== value) : (value === value)) { 608 object[key] = result; 609 } 610 } 611 612 module.exports = baseMergeDeep; 613 614 },{"../lang/isArguments":29,"../lang/isArray":30,"../lang/isPlainObject":34,"../lang/isTypedArray":36,"../lang/toPlainObject":37,"./arrayCopy":8,"./isArrayLike":21}],15:[function(_dereq_,module,exports){ 615 var toObject = _dereq_('./toObject'); 616 617 /** 618 * The base implementation of `_.property` without support for deep paths. 619 * 620 * @private 621 * @param {string} key The key of the property to get. 622 * @returns {Function} Returns the new function. 623 */ 624 function baseProperty(key) { 625 return function(object) { 626 return object == null ? undefined : toObject(object)[key]; 627 }; 628 } 629 630 module.exports = baseProperty; 631 632 },{"./toObject":28}],16:[function(_dereq_,module,exports){ 633 var identity = _dereq_('../utility/identity'); 634 635 /** 636 * A specialized version of `baseCallback` which only supports `this` binding 637 * and specifying the number of arguments to provide to `func`. 638 * 639 * @private 640 * @param {Function} func The function to bind. 641 * @param {*} thisArg The `this` binding of `func`. 642 * @param {number} [argCount] The number of arguments to provide to `func`. 643 * @returns {Function} Returns the callback. 644 */ 645 function bindCallback(func, thisArg, argCount) { 646 if (typeof func != 'function') { 647 return identity; 648 } 649 if (thisArg === undefined) { 650 return func; 651 } 652 switch (argCount) { 653 case 1: return function(value) { 654 return func.call(thisArg, value); 655 }; 656 case 3: return function(value, index, collection) { 657 return func.call(thisArg, value, index, collection); 658 }; 659 case 4: return function(accumulator, value, index, collection) { 660 return func.call(thisArg, accumulator, value, index, collection); 661 }; 662 case 5: return function(value, other, key, object, source) { 663 return func.call(thisArg, value, other, key, object, source); 664 }; 665 } 666 return function() { 667 return func.apply(thisArg, arguments); 668 }; 669 } 670 671 module.exports = bindCallback; 672 673 },{"../utility/identity":42}],17:[function(_dereq_,module,exports){ 674 var bindCallback = _dereq_('./bindCallback'), 675 isIterateeCall = _dereq_('./isIterateeCall'), 676 restParam = _dereq_('../function/restParam'); 677 678 /** 679 * Creates a `_.assign`, `_.defaults`, or `_.merge` function. 680 * 681 * @private 682 * @param {Function} assigner The function to assign values. 683 * @returns {Function} Returns the new assigner function. 684 */ 685 function createAssigner(assigner) { 686 return restParam(function(object, sources) { 687 var index = -1, 688 length = object == null ? 0 : sources.length, 689 customizer = length > 2 ? sources[length - 2] : undefined, 690 guard = length > 2 ? sources[2] : undefined, 691 thisArg = length > 1 ? sources[length - 1] : undefined; 692 693 if (typeof customizer == 'function') { 694 customizer = bindCallback(customizer, thisArg, 5); 695 length -= 2; 696 } else { 697 customizer = typeof thisArg == 'function' ? thisArg : undefined; 698 length -= (customizer ? 1 : 0); 699 } 700 if (guard && isIterateeCall(sources[0], sources[1], guard)) { 701 customizer = length < 3 ? undefined : customizer; 702 length = 1; 703 } 704 while (++index < length) { 705 var source = sources[index]; 706 if (source) { 707 assigner(object, source, customizer); 708 } 709 } 710 return object; 711 }); 712 } 713 714 module.exports = createAssigner; 715 716 },{"../function/restParam":6,"./bindCallback":16,"./isIterateeCall":24}],18:[function(_dereq_,module,exports){ 717 var toObject = _dereq_('./toObject'); 718 719 /** 720 * Creates a base function for `_.forIn` or `_.forInRight`. 721 * 722 * @private 723 * @param {boolean} [fromRight] Specify iterating from right to left. 724 * @returns {Function} Returns the new base function. 725 */ 726 function createBaseFor(fromRight) { 727 return function(object, iteratee, keysFunc) { 728 var iterable = toObject(object), 729 props = keysFunc(object), 730 length = props.length, 731 index = fromRight ? length : -1; 732 733 while ((fromRight ? index-- : ++index < length)) { 734 var key = props[index]; 735 if (iteratee(iterable[key], key, iterable) === false) { 736 break; 737 } 738 } 739 return object; 740 }; 741 } 742 743 module.exports = createBaseFor; 744 745 },{"./toObject":28}],19:[function(_dereq_,module,exports){ 746 var baseProperty = _dereq_('./baseProperty'); 747 748 /** 749 * Gets the "length" property value of `object`. 750 * 751 * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) 752 * that affects Safari on at least iOS 8.1-8.3 ARM64. 753 * 754 * @private 755 * @param {Object} object The object to query. 756 * @returns {*} Returns the "length" value. 757 */ 758 var getLength = baseProperty('length'); 759 760 module.exports = getLength; 761 762 },{"./baseProperty":15}],20:[function(_dereq_,module,exports){ 763 var isNative = _dereq_('../lang/isNative'); 764 765 /** 766 * Gets the native function at `key` of `object`. 767 * 768 * @private 769 * @param {Object} object The object to query. 770 * @param {string} key The key of the method to get. 771 * @returns {*} Returns the function if it's native, else `undefined`. 772 */ 773 function getNative(object, key) { 774 var value = object == null ? undefined : object[key]; 775 return isNative(value) ? value : undefined; 776 } 777 778 module.exports = getNative; 779 780 },{"../lang/isNative":32}],21:[function(_dereq_,module,exports){ 781 var getLength = _dereq_('./getLength'), 782 isLength = _dereq_('./isLength'); 783 784 /** 785 * Checks if `value` is array-like. 786 * 787 * @private 788 * @param {*} value The value to check. 789 * @returns {boolean} Returns `true` if `value` is array-like, else `false`. 790 */ 791 function isArrayLike(value) { 792 return value != null && isLength(getLength(value)); 793 } 794 795 module.exports = isArrayLike; 796 797 },{"./getLength":19,"./isLength":25}],22:[function(_dereq_,module,exports){ 798 /** 799 * Checks if `value` is a host object in IE < 9. 800 * 801 * @private 802 * @param {*} value The value to check. 803 * @returns {boolean} Returns `true` if `value` is a host object, else `false`. 804 */ 805 var isHostObject = (function() { 806 try { 807 Object({ 'toString': 0 } + ''); 808 } catch(e) { 809 return function() { return false; }; 810 } 811 return function(value) { 812 // IE < 9 presents many host objects as `Object` objects that can coerce 813 // to strings despite having improperly defined `toString` methods. 814 return typeof value.toString != 'function' && typeof (value + '') == 'string'; 815 }; 816 }()); 817 818 module.exports = isHostObject; 819 820 },{}],23:[function(_dereq_,module,exports){ 821 /** Used to detect unsigned integer values. */ 822 var reIsUint = /^\d+$/; 823 824 /** 825 * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) 826 * of an array-like value. 827 */ 828 var MAX_SAFE_INTEGER = 9007199254740991; 829 830 /** 831 * Checks if `value` is a valid array-like index. 832 * 833 * @private 834 * @param {*} value The value to check. 835 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. 836 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. 837 */ 838 function isIndex(value, length) { 839 value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; 840 length = length == null ? MAX_SAFE_INTEGER : length; 841 return value > -1 && value % 1 == 0 && value < length; 842 } 843 844 module.exports = isIndex; 845 846 },{}],24:[function(_dereq_,module,exports){ 847 var isArrayLike = _dereq_('./isArrayLike'), 848 isIndex = _dereq_('./isIndex'), 849 isObject = _dereq_('../lang/isObject'); 850 851 /** 852 * Checks if the provided arguments are from an iteratee call. 853 * 854 * @private 855 * @param {*} value The potential iteratee value argument. 856 * @param {*} index The potential iteratee index or key argument. 857 * @param {*} object The potential iteratee object argument. 858 * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`. 859 */ 860 function isIterateeCall(value, index, object) { 861 if (!isObject(object)) { 862 return false; 863 } 864 var type = typeof index; 865 if (type == 'number' 866 ? (isArrayLike(object) && isIndex(index, object.length)) 867 : (type == 'string' && index in object)) { 868 var other = object[index]; 869 return value === value ? (value === other) : (other !== other); 870 } 871 return false; 872 } 873 874 module.exports = isIterateeCall; 875 876 },{"../lang/isObject":33,"./isArrayLike":21,"./isIndex":23}],25:[function(_dereq_,module,exports){ 877 /** 878 * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) 879 * of an array-like value. 880 */ 881 var MAX_SAFE_INTEGER = 9007199254740991; 882 883 /** 884 * Checks if `value` is a valid array-like length. 885 * 886 * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). 887 * 888 * @private 889 * @param {*} value The value to check. 890 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. 891 */ 892 function isLength(value) { 893 return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; 894 } 895 896 module.exports = isLength; 897 898 },{}],26:[function(_dereq_,module,exports){ 899 /** 900 * Checks if `value` is object-like. 901 * 902 * @private 903 * @param {*} value The value to check. 904 * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 905 */ 906 function isObjectLike(value) { 907 return !!value && typeof value == 'object'; 908 } 909 910 module.exports = isObjectLike; 911 912 },{}],27:[function(_dereq_,module,exports){ 913 var isArguments = _dereq_('../lang/isArguments'), 914 isArray = _dereq_('../lang/isArray'), 915 isIndex = _dereq_('./isIndex'), 916 isLength = _dereq_('./isLength'), 917 isString = _dereq_('../lang/isString'), 918 keysIn = _dereq_('../object/keysIn'); 919 920 /** Used for native method references. */ 921 var objectProto = Object.prototype; 922 923 /** Used to check objects for own properties. */ 924 var hasOwnProperty = objectProto.hasOwnProperty; 925 926 /** 927 * A fallback implementation of `Object.keys` which creates an array of the 928 * own enumerable property names of `object`. 929 * 930 * @private 931 * @param {Object} object The object to query. 932 * @returns {Array} Returns the array of property names. 933 */ 934 function shimKeys(object) { 935 var props = keysIn(object), 936 propsLength = props.length, 937 length = propsLength && object.length; 938 939 var allowIndexes = !!length && isLength(length) && 940 (isArray(object) || isArguments(object) || isString(object)); 941 942 var index = -1, 943 result = []; 944 945 while (++index < propsLength) { 946 var key = props[index]; 947 if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { 948 result.push(key); 949 } 950 } 951 return result; 952 } 953 954 module.exports = shimKeys; 955 956 },{"../lang/isArguments":29,"../lang/isArray":30,"../lang/isString":35,"../object/keysIn":39,"./isIndex":23,"./isLength":25}],28:[function(_dereq_,module,exports){ 957 var isObject = _dereq_('../lang/isObject'), 958 isString = _dereq_('../lang/isString'), 959 support = _dereq_('../support'); 960 961 /** 962 * Converts `value` to an object if it's not one. 963 * 964 * @private 965 * @param {*} value The value to process. 966 * @returns {Object} Returns the object. 967 */ 968 function toObject(value) { 969 if (support.unindexedChars && isString(value)) { 970 var index = -1, 971 length = value.length, 972 result = Object(value); 973 974 while (++index < length) { 975 result[index] = value.charAt(index); 976 } 977 return result; 978 } 979 return isObject(value) ? value : Object(value); 980 } 981 982 module.exports = toObject; 983 984 },{"../lang/isObject":33,"../lang/isString":35,"../support":41}],29:[function(_dereq_,module,exports){ 985 var isArrayLike = _dereq_('../internal/isArrayLike'), 986 isObjectLike = _dereq_('../internal/isObjectLike'); 987 988 /** Used for native method references. */ 989 var objectProto = Object.prototype; 990 991 /** Used to check objects for own properties. */ 992 var hasOwnProperty = objectProto.hasOwnProperty; 993 994 /** Native method references. */ 995 var propertyIsEnumerable = objectProto.propertyIsEnumerable; 996 997 /** 998 * Checks if `value` is classified as an `arguments` object. 999 * 1000 * @static 1001 * @memberOf _ 1002 * @category Lang 1003 * @param {*} value The value to check. 1004 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. 1005 * @example 1006 * 1007 * _.isArguments(function() { return arguments; }()); 1008 * // => true 1009 * 1010 * _.isArguments([1, 2, 3]); 1011 * // => false 1012 */ 1013 function isArguments(value) { 1014 return isObjectLike(value) && isArrayLike(value) && 1015 hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); 1016 } 1017 1018 module.exports = isArguments; 1019 1020 },{"../internal/isArrayLike":21,"../internal/isObjectLike":26}],30:[function(_dereq_,module,exports){ 1021 var getNative = _dereq_('../internal/getNative'), 1022 isLength = _dereq_('../internal/isLength'), 1023 isObjectLike = _dereq_('../internal/isObjectLike'); 1024 1025 /** `Object#toString` result references. */ 1026 var arrayTag = '[object Array]'; 1027 1028 /** Used for native method references. */ 1029 var objectProto = Object.prototype; 1030 1031 /** 1032 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 1033 * of values. 1034 */ 1035 var objToString = objectProto.toString; 1036 1037 /* Native method references for those with the same name as other `lodash` methods. */ 1038 var nativeIsArray = getNative(Array, 'isArray'); 1039 1040 /** 1041 * Checks if `value` is classified as an `Array` object. 1042 * 1043 * @static 1044 * @memberOf _ 1045 * @category Lang 1046 * @param {*} value The value to check. 1047 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. 1048 * @example 1049 * 1050 * _.isArray([1, 2, 3]); 1051 * // => true 1052 * 1053 * _.isArray(function() { return arguments; }()); 1054 * // => false 1055 */ 1056 var isArray = nativeIsArray || function(value) { 1057 return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; 1058 }; 1059 1060 module.exports = isArray; 1061 1062 },{"../internal/getNative":20,"../internal/isLength":25,"../internal/isObjectLike":26}],31:[function(_dereq_,module,exports){ 1063 var isObject = _dereq_('./isObject'); 1064 1065 /** `Object#toString` result references. */ 1066 var funcTag = '[object Function]'; 1067 1068 /** Used for native method references. */ 1069 var objectProto = Object.prototype; 1070 1071 /** 1072 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 1073 * of values. 1074 */ 1075 var objToString = objectProto.toString; 1076 1077 /** 1078 * Checks if `value` is classified as a `Function` object. 1079 * 1080 * @static 1081 * @memberOf _ 1082 * @category Lang 1083 * @param {*} value The value to check. 1084 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. 1085 * @example 1086 * 1087 * _.isFunction(_); 1088 * // => true 1089 * 1090 * _.isFunction(/abc/); 1091 * // => false 1092 */ 1093 function isFunction(value) { 1094 // The use of `Object#toString` avoids issues with the `typeof` operator 1095 // in older versions of Chrome and Safari which return 'function' for regexes 1096 // and Safari 8 which returns 'object' for typed array constructors. 1097 return isObject(value) && objToString.call(value) == funcTag; 1098 } 1099 1100 module.exports = isFunction; 1101 1102 },{"./isObject":33}],32:[function(_dereq_,module,exports){ 1103 var isFunction = _dereq_('./isFunction'), 1104 isHostObject = _dereq_('../internal/isHostObject'), 1105 isObjectLike = _dereq_('../internal/isObjectLike'); 1106 1107 /** Used to detect host constructors (Safari > 5). */ 1108 var reIsHostCtor = /^\[object .+?Constructor\]$/; 1109 1110 /** Used for native method references. */ 1111 var objectProto = Object.prototype; 1112 1113 /** Used to resolve the decompiled source of functions. */ 1114 var fnToString = Function.prototype.toString; 1115 1116 /** Used to check objects for own properties. */ 1117 var hasOwnProperty = objectProto.hasOwnProperty; 1118 1119 /** Used to detect if a method is native. */ 1120 var reIsNative = RegExp('^' + 1121 fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') 1122 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' 1123 ); 1124 1125 /** 1126 * Checks if `value` is a native function. 1127 * 1128 * @static 1129 * @memberOf _ 1130 * @category Lang 1131 * @param {*} value The value to check. 1132 * @returns {boolean} Returns `true` if `value` is a native function, else `false`. 1133 * @example 1134 * 1135 * _.isNative(Array.prototype.push); 1136 * // => true 1137 * 1138 * _.isNative(_); 1139 * // => false 1140 */ 1141 function isNative(value) { 1142 if (value == null) { 1143 return false; 1144 } 1145 if (isFunction(value)) { 1146 return reIsNative.test(fnToString.call(value)); 1147 } 1148 return isObjectLike(value) && (isHostObject(value) ? reIsNative : reIsHostCtor).test(value); 1149 } 1150 1151 module.exports = isNative; 1152 1153 },{"../internal/isHostObject":22,"../internal/isObjectLike":26,"./isFunction":31}],33:[function(_dereq_,module,exports){ 1154 /** 1155 * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. 1156 * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) 1157 * 1158 * @static 1159 * @memberOf _ 1160 * @category Lang 1161 * @param {*} value The value to check. 1162 * @returns {boolean} Returns `true` if `value` is an object, else `false`. 1163 * @example 1164 * 1165 * _.isObject({}); 1166 * // => true 1167 * 1168 * _.isObject([1, 2, 3]); 1169 * // => true 1170 * 1171 * _.isObject(1); 1172 * // => false 1173 */ 1174 function isObject(value) { 1175 // Avoid a V8 JIT bug in Chrome 19-20. 1176 // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. 1177 var type = typeof value; 1178 return !!value && (type == 'object' || type == 'function'); 1179 } 1180 1181 module.exports = isObject; 1182 1183 },{}],34:[function(_dereq_,module,exports){ 1184 var baseForIn = _dereq_('../internal/baseForIn'), 1185 isArguments = _dereq_('./isArguments'), 1186 isHostObject = _dereq_('../internal/isHostObject'), 1187 isObjectLike = _dereq_('../internal/isObjectLike'), 1188 support = _dereq_('../support'); 1189 1190 /** `Object#toString` result references. */ 1191 var objectTag = '[object Object]'; 1192 1193 /** Used for native method references. */ 1194 var objectProto = Object.prototype; 1195 1196 /** Used to check objects for own properties. */ 1197 var hasOwnProperty = objectProto.hasOwnProperty; 1198 1199 /** 1200 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 1201 * of values. 1202 */ 1203 var objToString = objectProto.toString; 1204 1205 /** 1206 * Checks if `value` is a plain object, that is, an object created by the 1207 * `Object` constructor or one with a `[[Prototype]]` of `null`. 1208 * 1209 * **Note:** This method assumes objects created by the `Object` constructor 1210 * have no inherited enumerable properties. 1211 * 1212 * @static 1213 * @memberOf _ 1214 * @category Lang 1215 * @param {*} value The value to check. 1216 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. 1217 * @example 1218 * 1219 * function Foo() { 1220 * this.a = 1; 1221 * } 1222 * 1223 * _.isPlainObject(new Foo); 1224 * // => false 1225 * 1226 * _.isPlainObject([1, 2, 3]); 1227 * // => false 1228 * 1229 * _.isPlainObject({ 'x': 0, 'y': 0 }); 1230 * // => true 1231 * 1232 * _.isPlainObject(Object.create(null)); 1233 * // => true 1234 */ 1235 function isPlainObject(value) { 1236 var Ctor; 1237 1238 // Exit early for non `Object` objects. 1239 if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) || 1240 (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { 1241 return false; 1242 } 1243 // IE < 9 iterates inherited properties before own properties. If the first 1244 // iterated property is an object's own property then there are no inherited 1245 // enumerable properties. 1246 var result; 1247 if (support.ownLast) { 1248 baseForIn(value, function(subValue, key, object) { 1249 result = hasOwnProperty.call(object, key); 1250 return false; 1251 }); 1252 return result !== false; 1253 } 1254 // In most environments an object's own properties are iterated before 1255 // its inherited properties. If the last iterated property is an object's 1256 // own property then there are no inherited enumerable properties. 1257 baseForIn(value, function(subValue, key) { 1258 result = key; 1259 }); 1260 return result === undefined || hasOwnProperty.call(value, result); 1261 } 1262 1263 module.exports = isPlainObject; 1264 1265 },{"../internal/baseForIn":12,"../internal/isHostObject":22,"../internal/isObjectLike":26,"../support":41,"./isArguments":29}],35:[function(_dereq_,module,exports){ 1266 var isObjectLike = _dereq_('../internal/isObjectLike'); 1267 1268 /** `Object#toString` result references. */ 1269 var stringTag = '[object String]'; 1270 1271 /** Used for native method references. */ 1272 var objectProto = Object.prototype; 1273 1274 /** 1275 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 1276 * of values. 1277 */ 1278 var objToString = objectProto.toString; 1279 1280 /** 1281 * Checks if `value` is classified as a `String` primitive or object. 1282 * 1283 * @static 1284 * @memberOf _ 1285 * @category Lang 1286 * @param {*} value The value to check. 1287 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. 1288 * @example 1289 * 1290 * _.isString('abc'); 1291 * // => true 1292 * 1293 * _.isString(1); 1294 * // => false 1295 */ 1296 function isString(value) { 1297 return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag); 1298 } 1299 1300 module.exports = isString; 1301 1302 },{"../internal/isObjectLike":26}],36:[function(_dereq_,module,exports){ 1303 var isLength = _dereq_('../internal/isLength'), 1304 isObjectLike = _dereq_('../internal/isObjectLike'); 1305 1306 /** `Object#toString` result references. */ 1307 var argsTag = '[object Arguments]', 1308 arrayTag = '[object Array]', 1309 boolTag = '[object Boolean]', 1310 dateTag = '[object Date]', 1311 errorTag = '[object Error]', 1312 funcTag = '[object Function]', 1313 mapTag = '[object Map]', 1314 numberTag = '[object Number]', 1315 objectTag = '[object Object]', 1316 regexpTag = '[object RegExp]', 1317 setTag = '[object Set]', 1318 stringTag = '[object String]', 1319 weakMapTag = '[object WeakMap]'; 1320 1321 var arrayBufferTag = '[object ArrayBuffer]', 1322 float32Tag = '[object Float32Array]', 1323 float64Tag = '[object Float64Array]', 1324 int8Tag = '[object Int8Array]', 1325 int16Tag = '[object Int16Array]', 1326 int32Tag = '[object Int32Array]', 1327 uint8Tag = '[object Uint8Array]', 1328 uint8ClampedTag = '[object Uint8ClampedArray]', 1329 uint16Tag = '[object Uint16Array]', 1330 uint32Tag = '[object Uint32Array]'; 1331 1332 /** Used to identify `toStringTag` values of typed arrays. */ 1333 var typedArrayTags = {}; 1334 typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = 1335 typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = 1336 typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = 1337 typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = 1338 typedArrayTags[uint32Tag] = true; 1339 typedArrayTags[argsTag] = typedArrayTags[arrayTag] = 1340 typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = 1341 typedArrayTags[dateTag] = typedArrayTags[errorTag] = 1342 typedArrayTags[funcTag] = typedArrayTags[mapTag] = 1343 typedArrayTags[numberTag] = typedArrayTags[objectTag] = 1344 typedArrayTags[regexpTag] = typedArrayTags[setTag] = 1345 typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; 1346 1347 /** Used for native method references. */ 1348 var objectProto = Object.prototype; 1349 1350 /** 1351 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 1352 * of values. 1353 */ 1354 var objToString = objectProto.toString; 1355 1356 /** 1357 * Checks if `value` is classified as a typed array. 1358 * 1359 * @static 1360 * @memberOf _ 1361 * @category Lang 1362 * @param {*} value The value to check. 1363 * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. 1364 * @example 1365 * 1366 * _.isTypedArray(new Uint8Array); 1367 * // => true 1368 * 1369 * _.isTypedArray([]); 1370 * // => false 1371 */ 1372 function isTypedArray(value) { 1373 return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; 1374 } 1375 1376 module.exports = isTypedArray; 1377 1378 },{"../internal/isLength":25,"../internal/isObjectLike":26}],37:[function(_dereq_,module,exports){ 1379 var baseCopy = _dereq_('../internal/baseCopy'), 1380 keysIn = _dereq_('../object/keysIn'); 1381 1382 /** 1383 * Converts `value` to a plain object flattening inherited enumerable 1384 * properties of `value` to own properties of the plain object. 1385 * 1386 * @static 1387 * @memberOf _ 1388 * @category Lang 1389 * @param {*} value The value to convert. 1390 * @returns {Object} Returns the converted plain object. 1391 * @example 1392 * 1393 * function Foo() { 1394 * this.b = 2; 1395 * } 1396 * 1397 * Foo.prototype.c = 3; 1398 * 1399 * _.assign({ 'a': 1 }, new Foo); 1400 * // => { 'a': 1, 'b': 2 } 1401 * 1402 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); 1403 * // => { 'a': 1, 'b': 2, 'c': 3 } 1404 */ 1405 function toPlainObject(value) { 1406 return baseCopy(value, keysIn(value)); 1407 } 1408 1409 module.exports = toPlainObject; 1410 1411 },{"../internal/baseCopy":10,"../object/keysIn":39}],38:[function(_dereq_,module,exports){ 1412 var getNative = _dereq_('../internal/getNative'), 1413 isArrayLike = _dereq_('../internal/isArrayLike'), 1414 isObject = _dereq_('../lang/isObject'), 1415 shimKeys = _dereq_('../internal/shimKeys'), 1416 support = _dereq_('../support'); 1417 1418 /* Native method references for those with the same name as other `lodash` methods. */ 1419 var nativeKeys = getNative(Object, 'keys'); 1420 1421 /** 1422 * Creates an array of the own enumerable property names of `object`. 1423 * 1424 * **Note:** Non-object values are coerced to objects. See the 1425 * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) 1426 * for more details. 1427 * 1428 * @static 1429 * @memberOf _ 1430 * @category Object 1431 * @param {Object} object The object to query. 1432 * @returns {Array} Returns the array of property names. 1433 * @example 1434 * 1435 * function Foo() { 1436 * this.a = 1; 1437 * this.b = 2; 1438 * } 1439 * 1440 * Foo.prototype.c = 3; 1441 * 1442 * _.keys(new Foo); 1443 * // => ['a', 'b'] (iteration order is not guaranteed) 1444 * 1445 * _.keys('hi'); 1446 * // => ['0', '1'] 1447 */ 1448 var keys = !nativeKeys ? shimKeys : function(object) { 1449 var Ctor = object == null ? undefined : object.constructor; 1450 if ((typeof Ctor == 'function' && Ctor.prototype === object) || 1451 (typeof object == 'function' ? support.enumPrototypes : isArrayLike(object))) { 1452 return shimKeys(object); 1453 } 1454 return isObject(object) ? nativeKeys(object) : []; 1455 }; 1456 1457 module.exports = keys; 1458 1459 },{"../internal/getNative":20,"../internal/isArrayLike":21,"../internal/shimKeys":27,"../lang/isObject":33,"../support":41}],39:[function(_dereq_,module,exports){ 1460 var arrayEach = _dereq_('../internal/arrayEach'), 1461 isArguments = _dereq_('../lang/isArguments'), 1462 isArray = _dereq_('../lang/isArray'), 1463 isFunction = _dereq_('../lang/isFunction'), 1464 isIndex = _dereq_('../internal/isIndex'), 1465 isLength = _dereq_('../internal/isLength'), 1466 isObject = _dereq_('../lang/isObject'), 1467 isString = _dereq_('../lang/isString'), 1468 support = _dereq_('../support'); 1469 1470 /** `Object#toString` result references. */ 1471 var arrayTag = '[object Array]', 1472 boolTag = '[object Boolean]', 1473 dateTag = '[object Date]', 1474 errorTag = '[object Error]', 1475 funcTag = '[object Function]', 1476 numberTag = '[object Number]', 1477 objectTag = '[object Object]', 1478 regexpTag = '[object RegExp]', 1479 stringTag = '[object String]'; 1480 1481 /** Used to fix the JScript `[[DontEnum]]` bug. */ 1482 var shadowProps = [ 1483 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 1484 'toLocaleString', 'toString', 'valueOf' 1485 ]; 1486 1487 /** Used for native method references. */ 1488 var errorProto = Error.prototype, 1489 objectProto = Object.prototype, 1490 stringProto = String.prototype; 1491 1492 /** Used to check objects for own properties. */ 1493 var hasOwnProperty = objectProto.hasOwnProperty; 1494 1495 /** 1496 * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) 1497 * of values. 1498 */ 1499 var objToString = objectProto.toString; 1500 1501 /** Used to avoid iterating over non-enumerable properties in IE < 9. */ 1502 var nonEnumProps = {}; 1503 nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; 1504 nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true }; 1505 nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true }; 1506 nonEnumProps[objectTag] = { 'constructor': true }; 1507 1508 arrayEach(shadowProps, function(key) { 1509 for (var tag in nonEnumProps) { 1510 if (hasOwnProperty.call(nonEnumProps, tag)) { 1511 var props = nonEnumProps[tag]; 1512 props[key] = hasOwnProperty.call(props, key); 1513 } 1514 } 1515 }); 1516 1517 /** 1518 * Creates an array of the own and inherited enumerable property names of `object`. 1519 * 1520 * **Note:** Non-object values are coerced to objects. 1521 * 1522 * @static 1523 * @memberOf _ 1524 * @category Object 1525 * @param {Object} object The object to query. 1526 * @returns {Array} Returns the array of property names. 1527 * @example 1528 * 1529 * function Foo() { 1530 * this.a = 1; 1531 * this.b = 2; 1532 * } 1533 * 1534 * Foo.prototype.c = 3; 1535 * 1536 * _.keysIn(new Foo); 1537 * // => ['a', 'b', 'c'] (iteration order is not guaranteed) 1538 */ 1539 function keysIn(object) { 1540 if (object == null) { 1541 return []; 1542 } 1543 if (!isObject(object)) { 1544 object = Object(object); 1545 } 1546 var length = object.length; 1547 1548 length = (length && isLength(length) && 1549 (isArray(object) || isArguments(object) || isString(object)) && length) || 0; 1550 1551 var Ctor = object.constructor, 1552 index = -1, 1553 proto = (isFunction(Ctor) && Ctor.prototype) || objectProto, 1554 isProto = proto === object, 1555 result = Array(length), 1556 skipIndexes = length > 0, 1557 skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), 1558 skipProto = support.enumPrototypes && isFunction(object); 1559 1560 while (++index < length) { 1561 result[index] = (index + ''); 1562 } 1563 // lodash skips the `constructor` property when it infers it's iterating 1564 // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` 1565 // attribute of an existing property and the `constructor` property of a 1566 // prototype defaults to non-enumerable. 1567 for (var key in object) { 1568 if (!(skipProto && key == 'prototype') && 1569 !(skipErrorProps && (key == 'message' || key == 'name')) && 1570 !(skipIndexes && isIndex(key, length)) && 1571 !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { 1572 result.push(key); 1573 } 1574 } 1575 if (support.nonEnumShadows && object !== objectProto) { 1576 var tag = object === stringProto ? stringTag : (object === errorProto ? errorTag : objToString.call(object)), 1577 nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag]; 1578 1579 if (tag == objectTag) { 1580 proto = objectProto; 1581 } 1582 length = shadowProps.length; 1583 while (length--) { 1584 key = shadowProps[length]; 1585 var nonEnum = nonEnums[key]; 1586 if (!(isProto && nonEnum) && 1587 (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) { 1588 result.push(key); 1589 } 1590 } 1591 } 1592 return result; 1593 } 1594 1595 module.exports = keysIn; 1596 1597 },{"../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){ 1598 var baseMerge = _dereq_('../internal/baseMerge'), 1599 createAssigner = _dereq_('../internal/createAssigner'); 1600 1601 /** 1602 * Recursively merges own enumerable properties of the source object(s), that 1603 * don't resolve to `undefined` into the destination object. Subsequent sources 1604 * overwrite property assignments of previous sources. If `customizer` is 1605 * provided it's invoked to produce the merged values of the destination and 1606 * source properties. If `customizer` returns `undefined` merging is handled 1607 * by the method instead. The `customizer` is bound to `thisArg` and invoked 1608 * with five arguments: (objectValue, sourceValue, key, object, source). 1609 * 1610 * @static 1611 * @memberOf _ 1612 * @category Object 1613 * @param {Object} object The destination object. 1614 * @param {...Object} [sources] The source objects. 1615 * @param {Function} [customizer] The function to customize assigned values. 1616 * @param {*} [thisArg] The `this` binding of `customizer`. 1617 * @returns {Object} Returns `object`. 1618 * @example 1619 * 1620 * var users = { 1621 * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] 1622 * }; 1623 * 1624 * var ages = { 1625 * 'data': [{ 'age': 36 }, { 'age': 40 }] 1626 * }; 1627 * 1628 * _.merge(users, ages); 1629 * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } 1630 * 1631 * // using a customizer callback 1632 * var object = { 1633 * 'fruits': ['apple'], 1634 * 'vegetables': ['beet'] 1635 * }; 1636 * 1637 * var other = { 1638 * 'fruits': ['banana'], 1639 * 'vegetables': ['carrot'] 1640 * }; 1641 * 1642 * _.merge(object, other, function(a, b) { 1643 * if (_.isArray(a)) { 1644 * return a.concat(b); 1645 * } 1646 * }); 1647 * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } 1648 */ 1649 var merge = createAssigner(baseMerge); 1650 1651 module.exports = merge; 1652 1653 },{"../internal/baseMerge":13,"../internal/createAssigner":17}],41:[function(_dereq_,module,exports){ 1654 /** Used for native method references. */ 1655 var arrayProto = Array.prototype, 1656 errorProto = Error.prototype, 1657 objectProto = Object.prototype; 1658 1659 /** Native method references. */ 1660 var propertyIsEnumerable = objectProto.propertyIsEnumerable, 1661 splice = arrayProto.splice; 1662 1663 /** 1664 * An object environment feature flags. 1665 * 1666 * @static 1667 * @memberOf _ 1668 * @type Object 1669 */ 1670 var support = {}; 1671 1672 (function(x) { 1673 var Ctor = function() { this.x = x; }, 1674 object = { '0': x, 'length': x }, 1675 props = []; 1676 1677 Ctor.prototype = { 'valueOf': x, 'y': x }; 1678 for (var key in new Ctor) { props.push(key); } 1679 1680 /** 1681 * Detect if `name` or `message` properties of `Error.prototype` are 1682 * enumerable by default (IE < 9, Safari < 5.1). 1683 * 1684 * @memberOf _.support 1685 * @type boolean 1686 */ 1687 support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || 1688 propertyIsEnumerable.call(errorProto, 'name'); 1689 1690 /** 1691 * Detect if `prototype` properties are enumerable by default. 1692 * 1693 * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 1694 * (if the prototype or a property on the prototype has been set) 1695 * incorrectly set the `[[Enumerable]]` value of a function's `prototype` 1696 * property to `true`. 1697 * 1698 * @memberOf _.support 1699 * @type boolean 1700 */ 1701 support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype'); 1702 1703 /** 1704 * Detect if properties shadowing those on `Object.prototype` are non-enumerable. 1705 * 1706 * In IE < 9 an object's own properties, shadowing non-enumerable ones, 1707 * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). 1708 * 1709 * @memberOf _.support 1710 * @type boolean 1711 */ 1712 support.nonEnumShadows = !/valueOf/.test(props); 1713 1714 /** 1715 * Detect if own properties are iterated after inherited properties (IE < 9). 1716 * 1717 * @memberOf _.support 1718 * @type boolean 1719 */ 1720 support.ownLast = props[0] != 'x'; 1721 1722 /** 1723 * Detect if `Array#shift` and `Array#splice` augment array-like objects 1724 * correctly. 1725 * 1726 * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array 1727 * `shift()` and `splice()` functions that fail to remove the last element, 1728 * `value[0]`, of array-like objects even though the "length" property is 1729 * set to `0`. The `shift()` method is buggy in compatibility modes of IE 8, 1730 * while `splice()` is buggy regardless of mode in IE < 9. 1731 * 1732 * @memberOf _.support 1733 * @type boolean 1734 */ 1735 support.spliceObjects = (splice.call(object, 0, 1), !object[0]); 1736 1737 /** 1738 * Detect lack of support for accessing string characters by index. 1739 * 1740 * IE < 8 can't access characters by index. IE 8 can only access characters 1741 * by index on string literals, not string objects. 1742 * 1743 * @memberOf _.support 1744 * @type boolean 1745 */ 1746 support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx'; 1747 }(1, 0)); 1748 1749 module.exports = support; 1750 1751 },{}],42:[function(_dereq_,module,exports){ 1752 /** 1753 * This method returns the first argument provided to it. 1754 * 1755 * @static 1756 * @memberOf _ 1757 * @category Utility 1758 * @param {*} value Any value. 1759 * @returns {*} Returns `value`. 1760 * @example 1761 * 1762 * var object = { 'user': 'fred' }; 1763 * 1764 * _.identity(object) === object; 1765 * // => true 1766 */ 1767 function identity(value) { 1768 return value; 1769 } 1770 1771 module.exports = identity; 1772 1773 },{}],43:[function(_dereq_,module,exports){ 1774 'use strict'; 1775 1776 var keys = _dereq_('object-keys'); 1777 1778 module.exports = function hasSymbols() { 1779 if (typeof Symbol !== 'function' || typeof Object.getOwnPropertySymbols !== 'function') { return false; } 1780 if (typeof Symbol.iterator === 'symbol') { return true; } 1781 1782 var obj = {}; 1783 var sym = Symbol('test'); 1784 if (typeof sym === 'string') { return false; } 1785 1786 // temp disabled per https://github.com/ljharb/object.assign/issues/17 1787 // if (sym instanceof Symbol) { return false; } 1788 // temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4 1789 // if (!(Object(sym) instanceof Symbol)) { return false; } 1790 1791 var symVal = 42; 1792 obj[sym] = symVal; 1793 for (sym in obj) { return false; } 1794 if (keys(obj).length !== 0) { return false; } 1795 if (typeof Object.keys === 'function' && Object.keys(obj).length !== 0) { return false; } 1796 1797 if (typeof Object.getOwnPropertyNames === 'function' && Object.getOwnPropertyNames(obj).length !== 0) { return false; } 1798 1799 var syms = Object.getOwnPropertySymbols(obj); 1800 if (syms.length !== 1 || syms[0] !== sym) { return false; } 1801 1802 if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) { return false; } 1803 1804 if (typeof Object.getOwnPropertyDescriptor === 'function') { 1805 var descriptor = Object.getOwnPropertyDescriptor(obj, sym); 1806 if (descriptor.value !== symVal || descriptor.enumerable !== true) { return false; } 1807 } 1808 1809 return true; 1810 }; 1811 1812 },{"object-keys":50}],44:[function(_dereq_,module,exports){ 1813 'use strict'; 1814 1815 // modified from https://github.com/es-shims/es6-shim 1816 var keys = _dereq_('object-keys'); 1817 var bind = _dereq_('function-bind'); 1818 var canBeObject = function (obj) { 1819 return typeof obj !== 'undefined' && obj !== null; 1820 }; 1821 var hasSymbols = _dereq_('./hasSymbols')(); 1822 var toObject = Object; 1823 var push = bind.call(Function.call, Array.prototype.push); 1824 var propIsEnumerable = bind.call(Function.call, Object.prototype.propertyIsEnumerable); 1825 1826 module.exports = function assign(target, source1) { 1827 if (!canBeObject(target)) { throw new TypeError('target must be an object'); } 1828 var objTarget = toObject(target); 1829 var s, source, i, props, syms, value, key; 1830 for (s = 1; s < arguments.length; ++s) { 1831 source = toObject(arguments[s]); 1832 props = keys(source); 1833 if (hasSymbols && Object.getOwnPropertySymbols) { 1834 syms = Object.getOwnPropertySymbols(source); 1835 for (i = 0; i < syms.length; ++i) { 1836 key = syms[i]; 1837 if (propIsEnumerable(source, key)) { 1838 push(props, key); 1839 } 1840 } 1841 } 1842 for (i = 0; i < props.length; ++i) { 1843 key = props[i]; 1844 value = source[key]; 1845 if (propIsEnumerable(source, key)) { 1846 objTarget[key] = value; 1847 } 1848 } 1849 } 1850 return objTarget; 1851 }; 1852 1853 },{"./hasSymbols":43,"function-bind":49,"object-keys":50}],45:[function(_dereq_,module,exports){ 1854 'use strict'; 1855 1856 var defineProperties = _dereq_('define-properties'); 1857 1858 var implementation = _dereq_('./implementation'); 1859 var getPolyfill = _dereq_('./polyfill'); 1860 var shim = _dereq_('./shim'); 1861 1862 defineProperties(implementation, { 1863 implementation: implementation, 1864 getPolyfill: getPolyfill, 1865 shim: shim 1866 }); 1867 1868 module.exports = implementation; 1869 1870 },{"./implementation":44,"./polyfill":52,"./shim":53,"define-properties":46}],46:[function(_dereq_,module,exports){ 1871 'use strict'; 1872 1873 var keys = _dereq_('object-keys'); 1874 var foreach = _dereq_('foreach'); 1875 var hasSymbols = typeof Symbol === 'function' && typeof Symbol() === 'symbol'; 1876 1877 var toStr = Object.prototype.toString; 1878 1879 var isFunction = function (fn) { 1880 return typeof fn === 'function' && toStr.call(fn) === '[object Function]'; 1881 }; 1882 1883 var arePropertyDescriptorsSupported = function () { 1884 var obj = {}; 1885 try { 1886 Object.defineProperty(obj, 'x', { enumerable: false, value: obj }); 1887 /* eslint-disable no-unused-vars, no-restricted-syntax */ 1888 for (var _ in obj) { return false; } 1889 /* eslint-enable no-unused-vars, no-restricted-syntax */ 1890 return obj.x === obj; 1891 } catch (e) { /* this is IE 8. */ 1892 return false; 1893 } 1894 }; 1895 var supportsDescriptors = Object.defineProperty && arePropertyDescriptorsSupported(); 1896 1897 var defineProperty = function (object, name, value, predicate) { 1898 if (name in object && (!isFunction(predicate) || !predicate())) { 1899 return; 1900 } 1901 if (supportsDescriptors) { 1902 Object.defineProperty(object, name, { 1903 configurable: true, 1904 enumerable: false, 1905 value: value, 1906 writable: true 1907 }); 1908 } else { 1909 object[name] = value; 1910 } 1911 }; 1912 1913 var defineProperties = function (object, map) { 1914 var predicates = arguments.length > 2 ? arguments[2] : {}; 1915 var props = keys(map); 1916 if (hasSymbols) { 1917 props = props.concat(Object.getOwnPropertySymbols(map)); 1918 } 1919 foreach(props, function (name) { 1920 defineProperty(object, name, map[name], predicates[name]); 1921 }); 1922 }; 1923 1924 defineProperties.supportsDescriptors = !!supportsDescriptors; 1925 1926 module.exports = defineProperties; 1927 1928 },{"foreach":47,"object-keys":50}],47:[function(_dereq_,module,exports){ 1929 1930 var hasOwn = Object.prototype.hasOwnProperty; 1931 var toString = Object.prototype.toString; 1932 1933 module.exports = function forEach (obj, fn, ctx) { 1934 if (toString.call(fn) !== '[object Function]') { 1935 throw new TypeError('iterator must be a function'); 1936 } 1937 var l = obj.length; 1938 if (l === +l) { 1939 for (var i = 0; i < l; i++) { 1940 fn.call(ctx, obj[i], i, obj); 1941 } 1942 } else { 1943 for (var k in obj) { 1944 if (hasOwn.call(obj, k)) { 1945 fn.call(ctx, obj[k], k, obj); 1946 } 1947 } 1948 } 1949 }; 1950 1951 1952 },{}],48:[function(_dereq_,module,exports){ 1953 var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible '; 1954 var slice = Array.prototype.slice; 1955 var toStr = Object.prototype.toString; 1956 var funcType = '[object Function]'; 1957 1958 module.exports = function bind(that) { 1959 var target = this; 1960 if (typeof target !== 'function' || toStr.call(target) !== funcType) { 1961 throw new TypeError(ERROR_MESSAGE + target); 1962 } 1963 var args = slice.call(arguments, 1); 1964 1965 var bound; 1966 var binder = function () { 1967 if (this instanceof bound) { 1968 var result = target.apply( 1969 this, 1970 args.concat(slice.call(arguments)) 1971 ); 1972 if (Object(result) === result) { 1973 return result; 1974 } 1975 return this; 1976 } else { 1977 return target.apply( 1978 that, 1979 args.concat(slice.call(arguments)) 1980 ); 1981 } 1982 }; 1983 1984 var boundLength = Math.max(0, target.length - args.length); 1985 var boundArgs = []; 1986 for (var i = 0; i < boundLength; i++) { 1987 boundArgs.push('$' + i); 1988 } 1989 1990 bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder); 1991 1992 if (target.prototype) { 1993 var Empty = function Empty() {}; 1994 Empty.prototype = target.prototype; 1995 bound.prototype = new Empty(); 1996 Empty.prototype = null; 1997 } 1998 1999 return bound; 2000 }; 2001 2002 },{}],49:[function(_dereq_,module,exports){ 2003 var implementation = _dereq_('./implementation'); 2004 2005 module.exports = Function.prototype.bind || implementation; 2006 2007 },{"./implementation":48}],50:[function(_dereq_,module,exports){ 2008 'use strict'; 2009 2010 // modified from https://github.com/es-shims/es5-shim 2011 var has = Object.prototype.hasOwnProperty; 2012 var toStr = Object.prototype.toString; 2013 var slice = Array.prototype.slice; 2014 var isArgs = _dereq_('./isArguments'); 2015 var hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'); 2016 var hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype'); 2017 var dontEnums = [ 2018 'toString', 2019 'toLocaleString', 2020 'valueOf', 2021 'hasOwnProperty', 2022 'isPrototypeOf', 2023 'propertyIsEnumerable', 2024 'constructor' 2025 ]; 2026 var equalsConstructorPrototype = function (o) { 2027 var ctor = o.constructor; 2028 return ctor && ctor.prototype === o; 2029 }; 2030 var blacklistedKeys = { 2031 $console: true, 2032 $frame: true, 2033 $frameElement: true, 2034 $frames: true, 2035 $parent: true, 2036 $self: true, 2037 $webkitIndexedDB: true, 2038 $webkitStorageInfo: true, 2039 $window: true 2040 }; 2041 var hasAutomationEqualityBug = (function () { 2042 /* global window */ 2043 if (typeof window === 'undefined') { return false; } 2044 for (var k in window) { 2045 try { 2046 if (!blacklistedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') { 2047 try { 2048 equalsConstructorPrototype(window[k]); 2049 } catch (e) { 2050 return true; 2051 } 2052 } 2053 } catch (e) { 2054 return true; 2055 } 2056 } 2057 return false; 2058 }()); 2059 var equalsConstructorPrototypeIfNotBuggy = function (o) { 2060 /* global window */ 2061 if (typeof window === 'undefined' || !hasAutomationEqualityBug) { 2062 return equalsConstructorPrototype(o); 2063 } 2064 try { 2065 return equalsConstructorPrototype(o); 2066 } catch (e) { 2067 return false; 2068 } 2069 }; 2070 2071 var keysShim = function keys(object) { 2072 var isObject = object !== null && typeof object === 'object'; 2073 var isFunction = toStr.call(object) === '[object Function]'; 2074 var isArguments = isArgs(object); 2075 var isString = isObject && toStr.call(object) === '[object String]'; 2076 var theKeys = []; 2077 2078 if (!isObject && !isFunction && !isArguments) { 2079 throw new TypeError('Object.keys called on a non-object'); 2080 } 2081 2082 var skipProto = hasProtoEnumBug && isFunction; 2083 if (isString && object.length > 0 && !has.call(object, 0)) { 2084 for (var i = 0; i < object.length; ++i) { 2085 theKeys.push(String(i)); 2086 } 2087 } 2088 2089 if (isArguments && object.length > 0) { 2090 for (var j = 0; j < object.length; ++j) { 2091 theKeys.push(String(j)); 2092 } 2093 } else { 2094 for (var name in object) { 2095 if (!(skipProto && name === 'prototype') && has.call(object, name)) { 2096 theKeys.push(String(name)); 2097 } 2098 } 2099 } 2100 2101 if (hasDontEnumBug) { 2102 var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object); 2103 2104 for (var k = 0; k < dontEnums.length; ++k) { 2105 if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) { 2106 theKeys.push(dontEnums[k]); 2107 } 2108 } 2109 } 2110 return theKeys; 2111 }; 2112 2113 keysShim.shim = function shimObjectKeys() { 2114 if (Object.keys) { 2115 var keysWorksWithArguments = (function () { 2116 // Safari 5.0 bug 2117 return (Object.keys(arguments) || '').length === 2; 2118 }(1, 2)); 2119 if (!keysWorksWithArguments) { 2120 var originalKeys = Object.keys; 2121 Object.keys = function keys(object) { 2122 if (isArgs(object)) { 2123 return originalKeys(slice.call(object)); 2124 } else { 2125 return originalKeys(object); 2126 } 2127 }; 2128 } 2129 } else { 2130 Object.keys = keysShim; 2131 } 2132 return Object.keys || keysShim; 2133 }; 2134 2135 module.exports = keysShim; 2136 2137 },{"./isArguments":51}],51:[function(_dereq_,module,exports){ 2138 'use strict'; 2139 2140 var toStr = Object.prototype.toString; 2141 2142 module.exports = function isArguments(value) { 2143 var str = toStr.call(value); 2144 var isArgs = str === '[object Arguments]'; 2145 if (!isArgs) { 2146 isArgs = str !== '[object Array]' && 2147 value !== null && 2148 typeof value === 'object' && 2149 typeof value.length === 'number' && 2150 value.length >= 0 && 2151 toStr.call(value.callee) === '[object Function]'; 2152 } 2153 return isArgs; 2154 }; 2155 2156 },{}],52:[function(_dereq_,module,exports){ 2157 'use strict'; 2158 2159 var implementation = _dereq_('./implementation'); 2160 2161 var lacksProperEnumerationOrder = function () { 2162 if (!Object.assign) { 2163 return false; 2164 } 2165 // v8, specifically in node 4.x, has a bug with incorrect property enumeration order 2166 // note: this does not detect the bug unless there's 20 characters 2167 var str = 'abcdefghijklmnopqrst'; 2168 var letters = str.split(''); 2169 var map = {}; 2170 for (var i = 0; i < letters.length; ++i) { 2171 map[letters[i]] = letters[i]; 2172 } 2173 var obj = Object.assign({}, map); 2174 var actual = ''; 2175 for (var k in obj) { 2176 actual += k; 2177 } 2178 return str !== actual; 2179 }; 2180 2181 var assignHasPendingExceptions = function () { 2182 if (!Object.assign || !Object.preventExtensions) { 2183 return false; 2184 } 2185 // Firefox 37 still has "pending exception" logic in its Object.assign implementation, 2186 // which is 72% slower than our shim, and Firefox 40's native implementation. 2187 var thrower = Object.preventExtensions({ 1: 2 }); 2188 try { 2189 Object.assign(thrower, 'xy'); 2190 } catch (e) { 2191 return thrower[1] === 'y'; 2192 } 2193 }; 2194 2195 module.exports = function getPolyfill() { 2196 if (!Object.assign) { 2197 return implementation; 2198 } 2199 if (lacksProperEnumerationOrder()) { 2200 return implementation; 2201 } 2202 if (assignHasPendingExceptions()) { 2203 return implementation; 2204 } 2205 return Object.assign; 2206 }; 2207 2208 },{"./implementation":44}],53:[function(_dereq_,module,exports){ 2209 'use strict'; 2210 2211 var define = _dereq_('define-properties'); 2212 var getPolyfill = _dereq_('./polyfill'); 2213 2214 module.exports = function shimAssign() { 2215 var polyfill = getPolyfill(); 2216 define( 2217 Object, 2218 { assign: polyfill }, 2219 { assign: function () { return Object.assign !== polyfill; } } 2220 ); 2221 return polyfill; 2222 }; 2223 2224 },{"./polyfill":52,"define-properties":46}],54:[function(_dereq_,module,exports){ 2225 module.exports = SafeParseTuple 2226 2227 function SafeParseTuple(obj, reviver) { 2228 var json 2229 var error = null 2230 2231 try { 2232 json = JSON.parse(obj, reviver) 2233 } catch (err) { 2234 error = err 2235 } 2236 2237 return [error, json] 2238 } 2239 2240 },{}],55:[function(_dereq_,module,exports){ 2241 function clean (s) { 2242 return s.replace(/\n\r?\s*/g, '') 2243 } 2244 2245 2246 module.exports = function tsml (sa) { 2247 var s = '' 2248 , i = 0 2249 2250 for (; i < arguments.length; i++) 2251 s += clean(sa[i]) + (arguments[i + 1] || '') 2252 2253 return s 2254 } 2255 },{}],56:[function(_dereq_,module,exports){ 2256 "use strict"; 2257 var window = _dereq_("global/window") 2258 var once = _dereq_("once") 2259 var isFunction = _dereq_("is-function") 2260 var parseHeaders = _dereq_("parse-headers") 2261 var xtend = _dereq_("xtend") 2262 2263 module.exports = createXHR 2264 createXHR.XMLHttpRequest = window.XMLHttpRequest || noop 2265 createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest 2266 2267 forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) { 2268 createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) { 2269 options = initParams(uri, options, callback) 2270 options.method = method.toUpperCase() 2271 return _createXHR(options) 2272 } 2273 }) 2274 2275 function forEachArray(array, iterator) { 2276 for (var i = 0; i < array.length; i++) { 2277 iterator(array[i]) 2278 } 2279 } 2280 2281 function isEmpty(obj){ 2282 for(var i in obj){ 2283 if(obj.hasOwnProperty(i)) return false 2284 } 2285 return true 2286 } 2287 2288 function initParams(uri, options, callback) { 2289 var params = uri 2290 2291 if (isFunction(options)) { 2292 callback = options 2293 if (typeof uri === "string") { 2294 params = {uri:uri} 2295 } 2296 } else { 2297 params = xtend(options, {uri: uri}) 2298 } 2299 2300 params.callback = callback 2301 return params 2302 } 2303 2304 function createXHR(uri, options, callback) { 2305 options = initParams(uri, options, callback) 2306 return _createXHR(options) 2307 } 2308 2309 function _createXHR(options) { 2310 var callback = options.callback 2311 if(typeof callback === "undefined"){ 2312 throw new Error("callback argument missing") 2313 } 2314 callback = once(callback) 2315 2316 function readystatechange() { 2317 if (xhr.readyState === 4) { 2318 loadFunc() 2319 } 2320 } 2321 2322 function getBody() { 2323 // Chrome with requestType=blob throws errors arround when even testing access to responseText 2324 var body = undefined 2325 2326 if (xhr.response) { 2327 body = xhr.response 2328 } else if (xhr.responseType === "text" || !xhr.responseType) { 2329 body = xhr.responseText || xhr.responseXML 2330 } 2331 2332 if (isJson) { 2333 try { 2334 body = JSON.parse(body) 2335 } catch (e) {} 2336 } 2337 2338 return body 2339 } 2340 2341 var failureResponse = { 2342 body: undefined, 2343 headers: {}, 2344 statusCode: 0, 2345 method: method, 2346 url: uri, 2347 rawRequest: xhr 2348 } 2349 2350 function errorFunc(evt) { 2351 clearTimeout(timeoutTimer) 2352 if(!(evt instanceof Error)){ 2353 evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") ) 2354 } 2355 evt.statusCode = 0 2356 callback(evt, failureResponse) 2357 } 2358 2359 // will load the data & process the response in a special response object 2360 function loadFunc() { 2361 if (aborted) return 2362 var status 2363 clearTimeout(timeoutTimer) 2364 if(options.useXDR && xhr.status===undefined) { 2365 //IE8 CORS GET successful response doesn't have a status field, but body is fine 2366 status = 200 2367 } else { 2368 status = (xhr.status === 1223 ? 204 : xhr.status) 2369 } 2370 var response = failureResponse 2371 var err = null 2372 2373 if (status !== 0){ 2374 response = { 2375 body: getBody(), 2376 statusCode: status, 2377 method: method, 2378 headers: {}, 2379 url: uri, 2380 rawRequest: xhr 2381 } 2382 if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE 2383 response.headers = parseHeaders(xhr.getAllResponseHeaders()) 2384 } 2385 } else { 2386 err = new Error("Internal XMLHttpRequest Error") 2387 } 2388 callback(err, response, response.body) 2389 2390 } 2391 2392 var xhr = options.xhr || null 2393 2394 if (!xhr) { 2395 if (options.cors || options.useXDR) { 2396 xhr = new createXHR.XDomainRequest() 2397 }else{ 2398 xhr = new createXHR.XMLHttpRequest() 2399 } 2400 } 2401 2402 var key 2403 var aborted 2404 var uri = xhr.url = options.uri || options.url 2405 var method = xhr.method = options.method || "GET" 2406 var body = options.body || options.data || null 2407 var headers = xhr.headers = options.headers || {} 2408 var sync = !!options.sync 2409 var isJson = false 2410 var timeoutTimer 2411 2412 if ("json" in options) { 2413 isJson = true 2414 headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don't override existing accept header declared by user 2415 if (method !== "GET" && method !== "HEAD") { 2416 headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don't override existing accept header declared by user 2417 body = JSON.stringify(options.json) 2418 } 2419 } 2420 2421 xhr.onreadystatechange = readystatechange 2422 xhr.onload = loadFunc 2423 xhr.onerror = errorFunc 2424 // IE9 must have onprogress be set to a unique function. 2425 xhr.onprogress = function () { 2426 // IE must die 2427 } 2428 xhr.ontimeout = errorFunc 2429 xhr.open(method, uri, !sync, options.username, options.password) 2430 //has to be after open 2431 if(!sync) { 2432 xhr.withCredentials = !!options.withCredentials 2433 } 2434 // Cannot set timeout with sync request 2435 // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly 2436 // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent 2437 if (!sync && options.timeout > 0 ) { 2438 timeoutTimer = setTimeout(function(){ 2439 aborted=true//IE9 may still call readystatechange 2440 xhr.abort("timeout") 2441 var e = new Error("XMLHttpRequest timeout") 2442 e.code = "ETIMEDOUT" 2443 errorFunc(e) 2444 }, options.timeout ) 2445 } 2446 2447 if (xhr.setRequestHeader) { 2448 for(key in headers){ 2449 if(headers.hasOwnProperty(key)){ 2450 xhr.setRequestHeader(key, headers[key]) 2451 } 2452 } 2453 } else if (options.headers && !isEmpty(options.headers)) { 2454 throw new Error("Headers cannot be set on an XDomainRequest object") 2455 } 2456 2457 if ("responseType" in options) { 2458 xhr.responseType = options.responseType 2459 } 2460 2461 if ("beforeSend" in options && 2462 typeof options.beforeSend === "function" 2463 ) { 2464 options.beforeSend(xhr) 2465 } 2466 2467 xhr.send(body) 2468 2469 return xhr 2470 2471 2472 } 2473 2474 function noop() {} 2475 2476 },{"global/window":2,"is-function":57,"once":58,"parse-headers":61,"xtend":62}],57:[function(_dereq_,module,exports){ 2477 module.exports = isFunction 2478 2479 var toString = Object.prototype.toString 2480 2481 function isFunction (fn) { 2482 var string = toString.call(fn) 2483 return string === '[object Function]' || 2484 (typeof fn === 'function' && string !== '[object RegExp]') || 2485 (typeof window !== 'undefined' && 2486 // IE8 and below 2487 (fn === window.setTimeout || 2488 fn === window.alert || 2489 fn === window.confirm || 2490 fn === window.prompt)) 2491 }; 2492 2493 },{}],58:[function(_dereq_,module,exports){ 2494 module.exports = once 2495 2496 once.proto = once(function () { 2497 Object.defineProperty(Function.prototype, 'once', { 2498 value: function () { 2499 return once(this) 2500 }, 2501 configurable: true 2502 }) 2503 }) 2504 2505 function once (fn) { 2506 var called = false 2507 return function () { 2508 if (called) return 2509 called = true 2510 return fn.apply(this, arguments) 2511 } 2512 } 2513 2514 },{}],59:[function(_dereq_,module,exports){ 2515 var isFunction = _dereq_('is-function') 2516 2517 module.exports = forEach 2518 2519 var toString = Object.prototype.toString 2520 var hasOwnProperty = Object.prototype.hasOwnProperty 2521 2522 function forEach(list, iterator, context) { 2523 if (!isFunction(iterator)) { 2524 throw new TypeError('iterator must be a function') 2525 } 2526 2527 if (arguments.length < 3) { 2528 context = this 2529 } 2530 2531 if (toString.call(list) === '[object Array]') 2532 forEachArray(list, iterator, context) 2533 else if (typeof list === 'string') 2534 forEachString(list, iterator, context) 2535 else 2536 forEachObject(list, iterator, context) 2537 } 2538 2539 function forEachArray(array, iterator, context) { 2540 for (var i = 0, len = array.length; i < len; i++) { 2541 if (hasOwnProperty.call(array, i)) { 2542 iterator.call(context, array[i], i, array) 2543 } 2544 } 2545 } 2546 2547 function forEachString(string, iterator, context) { 2548 for (var i = 0, len = string.length; i < len; i++) { 2549 // no such thing as a sparse string. 2550 iterator.call(context, string.charAt(i), i, string) 2551 } 2552 } 2553 2554 function forEachObject(object, iterator, context) { 2555 for (var k in object) { 2556 if (hasOwnProperty.call(object, k)) { 2557 iterator.call(context, object[k], k, object) 2558 } 2559 } 2560 } 2561 2562 },{"is-function":57}],60:[function(_dereq_,module,exports){ 2563 2564 exports = module.exports = trim; 2565 2566 function trim(str){ 2567 return str.replace(/^\s*|\s*$/g, ''); 2568 } 2569 2570 exports.left = function(str){ 2571 return str.replace(/^\s*/, ''); 2572 }; 2573 2574 exports.right = function(str){ 2575 return str.replace(/\s*$/, ''); 2576 }; 2577 2578 },{}],61:[function(_dereq_,module,exports){ 2579 var trim = _dereq_('trim') 2580 , forEach = _dereq_('for-each') 2581 , isArray = function(arg) { 2582 return Object.prototype.toString.call(arg) === '[object Array]'; 2583 } 2584 2585 module.exports = function (headers) { 2586 if (!headers) 2587 return {} 2588 2589 var result = {} 2590 2591 forEach( 2592 trim(headers).split('\n') 2593 , function (row) { 2594 var index = row.indexOf(':') 2595 , key = trim(row.slice(0, index)).toLowerCase() 2596 , value = trim(row.slice(index + 1)) 2597 2598 if (typeof(result[key]) === 'undefined') { 2599 result[key] = value 2600 } else if (isArray(result[key])) { 2601 result[key].push(value) 2602 } else { 2603 result[key] = [ result[key], value ] 2604 } 2605 } 2606 ) 2607 2608 return result 2609 } 2610 },{"for-each":59,"trim":60}],62:[function(_dereq_,module,exports){ 2611 module.exports = extend 2612 2613 var hasOwnProperty = Object.prototype.hasOwnProperty; 2614 2615 function extend() { 2616 var target = {} 2617 2618 for (var i = 0; i < arguments.length; i++) { 2619 var source = arguments[i] 2620 2621 for (var key in source) { 2622 if (hasOwnProperty.call(source, key)) { 2623 target[key] = source[key] 2624 } 2625 } 2626 } 2627 2628 return target 2629 } 2630 2631 },{}],63:[function(_dereq_,module,exports){ 2632 /** 2633 * @file big-play-button.js 2634 */ 2635 'use strict'; 2636 2637 exports.__esModule = true; 2638 2639 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 2640 2641 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 2642 2643 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; } 2644 2645 var _buttonJs = _dereq_('./button.js'); 2646 2647 var _buttonJs2 = _interopRequireDefault(_buttonJs); 2648 2649 var _componentJs = _dereq_('./component.js'); 2650 2651 var _componentJs2 = _interopRequireDefault(_componentJs); 2652 2653 /** 2654 * Initial play button. Shows before the video has played. The hiding of the 2655 * big play button is done via CSS and player states. 2656 * 2657 * @param {Object} player Main Player 2658 * @param {Object=} options Object of option names and values 2659 * @extends Button 2660 * @class BigPlayButton 2661 */ 2662 2663 var BigPlayButton = (function (_Button) { 2664 _inherits(BigPlayButton, _Button); 2665 2666 function BigPlayButton(player, options) { 2667 _classCallCheck(this, BigPlayButton); 2668 2669 _Button.call(this, player, options); 2670 } 2671 2672 /** 2673 * Allow sub components to stack CSS class names 2674 * 2675 * @return {String} The constructed class name 2676 * @method buildCSSClass 2677 */ 2678 2679 BigPlayButton.prototype.buildCSSClass = function buildCSSClass() { 2680 return 'vjs-big-play-button'; 2681 }; 2682 2683 /** 2684 * Handles click for play 2685 * 2686 * @method handleClick 2687 */ 2688 2689 BigPlayButton.prototype.handleClick = function handleClick() { 2690 this.player_.play(); 2691 }; 2692 2693 return BigPlayButton; 2694 })(_buttonJs2['default']); 2695 2696 BigPlayButton.prototype.controlText_ = 'Play Video'; 2697 2698 _componentJs2['default'].registerComponent('BigPlayButton', BigPlayButton); 2699 exports['default'] = BigPlayButton; 2700 module.exports = exports['default']; 2701 2702 },{"./button.js":64,"./component.js":67}],64:[function(_dereq_,module,exports){ 2703 /** 2704 * @file button.js 2705 */ 2706 'use strict'; 2707 2708 exports.__esModule = true; 2709 2710 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; } } 2711 2712 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 2713 2714 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 2715 2716 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; } 2717 2718 var _clickableComponentJs = _dereq_('./clickable-component.js'); 2719 2720 var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs); 2721 2722 var _component = _dereq_('./component'); 2723 2724 var _component2 = _interopRequireDefault(_component); 2725 2726 var _utilsEventsJs = _dereq_('./utils/events.js'); 2727 2728 var Events = _interopRequireWildcard(_utilsEventsJs); 2729 2730 var _utilsFnJs = _dereq_('./utils/fn.js'); 2731 2732 var Fn = _interopRequireWildcard(_utilsFnJs); 2733 2734 var _utilsLogJs = _dereq_('./utils/log.js'); 2735 2736 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 2737 2738 var _globalDocument = _dereq_('global/document'); 2739 2740 var _globalDocument2 = _interopRequireDefault(_globalDocument); 2741 2742 var _objectAssign = _dereq_('object.assign'); 2743 2744 var _objectAssign2 = _interopRequireDefault(_objectAssign); 2745 2746 /** 2747 * Base class for all buttons 2748 * 2749 * @param {Object} player Main Player 2750 * @param {Object=} options Object of option names and values 2751 * @extends ClickableComponent 2752 * @class Button 2753 */ 2754 2755 var Button = (function (_ClickableComponent) { 2756 _inherits(Button, _ClickableComponent); 2757 2758 function Button(player, options) { 2759 _classCallCheck(this, Button); 2760 2761 _ClickableComponent.call(this, player, options); 2762 } 2763 2764 /** 2765 * Create the component's DOM element 2766 * 2767 * @param {String=} type Element's node type. e.g. 'div' 2768 * @param {Object=} props An object of properties that should be set on the element 2769 * @param {Object=} attributes An object of attributes that should be set on the element 2770 * @return {Element} 2771 * @method createEl 2772 */ 2773 2774 Button.prototype.createEl = function createEl() { 2775 var tag = arguments.length <= 0 || arguments[0] === undefined ? 'button' : arguments[0]; 2776 var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 2777 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; 2778 2779 props = _objectAssign2['default']({ 2780 className: this.buildCSSClass() 2781 }, props); 2782 2783 if (tag !== 'button') { 2784 _utilsLogJs2['default'].warn('Creating a Button with an HTML element of ' + tag + ' is deprecated; use ClickableComponent instead.'); 2785 2786 // Add properties for clickable element which is not a native HTML button 2787 props = _objectAssign2['default']({ 2788 tabIndex: 0 2789 }, props); 2790 2791 // Add ARIA attributes for clickable element which is not a native HTML button 2792 attributes = _objectAssign2['default']({ 2793 role: 'button' 2794 }, attributes); 2795 } 2796 2797 // Add attributes for button element 2798 attributes = _objectAssign2['default']({ 2799 type: 'button', // Necessary since the default button type is "submit" 2800 'aria-live': 'polite' // let the screen reader user know that the text of the button may change 2801 }, attributes); 2802 2803 var el = _component2['default'].prototype.createEl.call(this, tag, props, attributes); 2804 2805 this.createControlTextEl(el); 2806 2807 return el; 2808 }; 2809 2810 /** 2811 * Adds a child component inside this button 2812 * 2813 * @param {String|Component} child The class name or instance of a child to add 2814 * @param {Object=} options Options, including options to be passed to children of the child. 2815 * @return {Component} The child component (created by this process if a string was used) 2816 * @deprecated 2817 * @method addChild 2818 */ 2819 2820 Button.prototype.addChild = function addChild(child) { 2821 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 2822 2823 var className = this.constructor.name; 2824 _utilsLogJs2['default'].warn('Adding an actionable (user controllable) child to a Button (' + className + ') is not supported; use a ClickableComponent instead.'); 2825 2826 // Avoid the error message generated by ClickableComponent's addChild method 2827 return _component2['default'].prototype.addChild.call(this, child, options); 2828 }; 2829 2830 /** 2831 * Handle KeyPress (document level) - Extend with specific functionality for button 2832 * 2833 * @method handleKeyPress 2834 */ 2835 2836 Button.prototype.handleKeyPress = function handleKeyPress(event) { 2837 // Ignore Space (32) or Enter (13) key operation, which is handled by the browser for a button. 2838 if (event.which === 32 || event.which === 13) {} else { 2839 _ClickableComponent.prototype.handleKeyPress.call(this, event); // Pass keypress handling up for unsupported keys 2840 } 2841 }; 2842 2843 return Button; 2844 })(_clickableComponentJs2['default']); 2845 2846 _component2['default'].registerComponent('Button', Button); 2847 exports['default'] = Button; 2848 module.exports = exports['default']; 2849 2850 },{"./clickable-component.js":65,"./component":67,"./utils/events.js":135,"./utils/fn.js":136,"./utils/log.js":139,"global/document":1,"object.assign":45}],65:[function(_dereq_,module,exports){ 2851 /** 2852 * @file button.js 2853 */ 2854 'use strict'; 2855 2856 exports.__esModule = true; 2857 2858 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; } } 2859 2860 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 2861 2862 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 2863 2864 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; } 2865 2866 var _component = _dereq_('./component'); 2867 2868 var _component2 = _interopRequireDefault(_component); 2869 2870 var _utilsDomJs = _dereq_('./utils/dom.js'); 2871 2872 var Dom = _interopRequireWildcard(_utilsDomJs); 2873 2874 var _utilsEventsJs = _dereq_('./utils/events.js'); 2875 2876 var Events = _interopRequireWildcard(_utilsEventsJs); 2877 2878 var _utilsFnJs = _dereq_('./utils/fn.js'); 2879 2880 var Fn = _interopRequireWildcard(_utilsFnJs); 2881 2882 var _utilsLogJs = _dereq_('./utils/log.js'); 2883 2884 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 2885 2886 var _globalDocument = _dereq_('global/document'); 2887 2888 var _globalDocument2 = _interopRequireDefault(_globalDocument); 2889 2890 var _objectAssign = _dereq_('object.assign'); 2891 2892 var _objectAssign2 = _interopRequireDefault(_objectAssign); 2893 2894 /** 2895 * Clickable Component which is clickable or keyboard actionable, but is not a native HTML button 2896 * 2897 * @param {Object} player Main Player 2898 * @param {Object=} options Object of option names and values 2899 * @extends Component 2900 * @class ClickableComponent 2901 */ 2902 2903 var ClickableComponent = (function (_Component) { 2904 _inherits(ClickableComponent, _Component); 2905 2906 function ClickableComponent(player, options) { 2907 _classCallCheck(this, ClickableComponent); 2908 2909 _Component.call(this, player, options); 2910 2911 this.emitTapEvents(); 2912 2913 this.on('tap', this.handleClick); 2914 this.on('click', this.handleClick); 2915 this.on('focus', this.handleFocus); 2916 this.on('blur', this.handleBlur); 2917 } 2918 2919 /** 2920 * Create the component's DOM element 2921 * 2922 * @param {String=} type Element's node type. e.g. 'div' 2923 * @param {Object=} props An object of properties that should be set on the element 2924 * @param {Object=} attributes An object of attributes that should be set on the element 2925 * @return {Element} 2926 * @method createEl 2927 */ 2928 2929 ClickableComponent.prototype.createEl = function createEl() { 2930 var tag = arguments.length <= 0 || arguments[0] === undefined ? 'div' : arguments[0]; 2931 var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 2932 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; 2933 2934 props = _objectAssign2['default']({ 2935 className: this.buildCSSClass(), 2936 tabIndex: 0 2937 }, props); 2938 2939 if (tag === 'button') { 2940 _utilsLogJs2['default'].error('Creating a ClickableComponent with an HTML element of ' + tag + ' is not supported; use a Button instead.'); 2941 } 2942 2943 // Add ARIA attributes for clickable element which is not a native HTML button 2944 attributes = _objectAssign2['default']({ 2945 role: 'button', 2946 'aria-live': 'polite' // let the screen reader user know that the text of the element may change 2947 }, attributes); 2948 2949 var el = _Component.prototype.createEl.call(this, tag, props, attributes); 2950 2951 this.createControlTextEl(el); 2952 2953 return el; 2954 }; 2955 2956 /** 2957 * create control text 2958 * 2959 * @param {Element} el Parent element for the control text 2960 * @return {Element} 2961 * @method controlText 2962 */ 2963 2964 ClickableComponent.prototype.createControlTextEl = function createControlTextEl(el) { 2965 this.controlTextEl_ = Dom.createEl('span', { 2966 className: 'vjs-control-text' 2967 }); 2968 2969 if (el) { 2970 el.appendChild(this.controlTextEl_); 2971 } 2972 2973 this.controlText(this.controlText_); 2974 2975 return this.controlTextEl_; 2976 }; 2977 2978 /** 2979 * Controls text - both request and localize 2980 * 2981 * @param {String} text Text for element 2982 * @return {String} 2983 * @method controlText 2984 */ 2985 2986 ClickableComponent.prototype.controlText = function controlText(text) { 2987 if (!text) return this.controlText_ || 'Need Text'; 2988 2989 this.controlText_ = text; 2990 this.controlTextEl_.innerHTML = this.localize(this.controlText_); 2991 2992 return this; 2993 }; 2994 2995 /** 2996 * Allows sub components to stack CSS class names 2997 * 2998 * @return {String} 2999 * @method buildCSSClass 3000 */ 3001 3002 ClickableComponent.prototype.buildCSSClass = function buildCSSClass() { 3003 return 'vjs-control vjs-button ' + _Component.prototype.buildCSSClass.call(this); 3004 }; 3005 3006 /** 3007 * Adds a child component inside this clickable-component 3008 * 3009 * @param {String|Component} child The class name or instance of a child to add 3010 * @param {Object=} options Options, including options to be passed to children of the child. 3011 * @return {Component} The child component (created by this process if a string was used) 3012 * @method addChild 3013 */ 3014 3015 ClickableComponent.prototype.addChild = function addChild(child) { 3016 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 3017 3018 // TODO: Fix adding an actionable child to a ClickableComponent; currently 3019 // it will cause issues with assistive technology (e.g. screen readers) 3020 // which support ARIA, since an element with role="button" cannot have 3021 // actionable child elements. 3022 3023 //let className = this.constructor.name; 3024 //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.`); 3025 3026 return _Component.prototype.addChild.call(this, child, options); 3027 }; 3028 3029 /** 3030 * Enable the component element 3031 * 3032 * @return {Component} 3033 * @method enable 3034 */ 3035 3036 ClickableComponent.prototype.enable = function enable() { 3037 this.removeClass('vjs-disabled'); 3038 this.el_.setAttribute('aria-disabled', 'false'); 3039 return this; 3040 }; 3041 3042 /** 3043 * Disable the component element 3044 * 3045 * @return {Component} 3046 * @method disable 3047 */ 3048 3049 ClickableComponent.prototype.disable = function disable() { 3050 this.addClass('vjs-disabled'); 3051 this.el_.setAttribute('aria-disabled', 'true'); 3052 return this; 3053 }; 3054 3055 /** 3056 * Handle Click - Override with specific functionality for component 3057 * 3058 * @method handleClick 3059 */ 3060 3061 ClickableComponent.prototype.handleClick = function handleClick() {}; 3062 3063 /** 3064 * Handle Focus - Add keyboard functionality to element 3065 * 3066 * @method handleFocus 3067 */ 3068 3069 ClickableComponent.prototype.handleFocus = function handleFocus() { 3070 Events.on(_globalDocument2['default'], 'keydown', Fn.bind(this, this.handleKeyPress)); 3071 }; 3072 3073 /** 3074 * Handle KeyPress (document level) - Trigger click when Space or Enter key is pressed 3075 * 3076 * @method handleKeyPress 3077 */ 3078 3079 ClickableComponent.prototype.handleKeyPress = function handleKeyPress(event) { 3080 // Support Space (32) or Enter (13) key operation to fire a click event 3081 if (event.which === 32 || event.which === 13) { 3082 event.preventDefault(); 3083 this.handleClick(event); 3084 } else if (_Component.prototype.handleKeyPress) { 3085 _Component.prototype.handleKeyPress.call(this, event); // Pass keypress handling up for unsupported keys 3086 } 3087 }; 3088 3089 /** 3090 * Handle Blur - Remove keyboard triggers 3091 * 3092 * @method handleBlur 3093 */ 3094 3095 ClickableComponent.prototype.handleBlur = function handleBlur() { 3096 Events.off(_globalDocument2['default'], 'keydown', Fn.bind(this, this.handleKeyPress)); 3097 }; 3098 3099 return ClickableComponent; 3100 })(_component2['default']); 3101 3102 _component2['default'].registerComponent('ClickableComponent', ClickableComponent); 3103 exports['default'] = ClickableComponent; 3104 module.exports = exports['default']; 3105 3106 },{"./component":67,"./utils/dom.js":134,"./utils/events.js":135,"./utils/fn.js":136,"./utils/log.js":139,"global/document":1,"object.assign":45}],66:[function(_dereq_,module,exports){ 3107 'use strict'; 3108 3109 exports.__esModule = true; 3110 3111 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 3112 3113 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 3114 3115 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; } 3116 3117 var _button = _dereq_('./button'); 3118 3119 var _button2 = _interopRequireDefault(_button); 3120 3121 var _component = _dereq_('./component'); 3122 3123 var _component2 = _interopRequireDefault(_component); 3124 3125 /** 3126 * The `CloseButton` component is a button which fires a "close" event 3127 * when it is activated. 3128 * 3129 * @extends Button 3130 * @class CloseButton 3131 */ 3132 3133 var CloseButton = (function (_Button) { 3134 _inherits(CloseButton, _Button); 3135 3136 function CloseButton(player, options) { 3137 _classCallCheck(this, CloseButton); 3138 3139 _Button.call(this, player, options); 3140 this.controlText(options && options.controlText || this.localize('Close')); 3141 } 3142 3143 CloseButton.prototype.buildCSSClass = function buildCSSClass() { 3144 return 'vjs-close-button ' + _Button.prototype.buildCSSClass.call(this); 3145 }; 3146 3147 CloseButton.prototype.handleClick = function handleClick() { 3148 this.trigger({ type: 'close', bubbles: false }); 3149 }; 3150 3151 return CloseButton; 3152 })(_button2['default']); 3153 3154 _component2['default'].registerComponent('CloseButton', CloseButton); 3155 exports['default'] = CloseButton; 3156 module.exports = exports['default']; 3157 3158 },{"./button":64,"./component":67}],67:[function(_dereq_,module,exports){ 3159 /** 3160 * @file component.js 3161 * 3162 * Player Component - Base class for all UI objects 3163 */ 3164 3165 'use strict'; 3166 3167 exports.__esModule = true; 3168 3169 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; } } 3170 3171 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 3172 3173 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 3174 3175 var _globalWindow = _dereq_('global/window'); 3176 3177 var _globalWindow2 = _interopRequireDefault(_globalWindow); 3178 3179 var _utilsDomJs = _dereq_('./utils/dom.js'); 3180 3181 var Dom = _interopRequireWildcard(_utilsDomJs); 3182 3183 var _utilsFnJs = _dereq_('./utils/fn.js'); 3184 3185 var Fn = _interopRequireWildcard(_utilsFnJs); 3186 3187 var _utilsGuidJs = _dereq_('./utils/guid.js'); 3188 3189 var Guid = _interopRequireWildcard(_utilsGuidJs); 3190 3191 var _utilsEventsJs = _dereq_('./utils/events.js'); 3192 3193 var Events = _interopRequireWildcard(_utilsEventsJs); 3194 3195 var _utilsLogJs = _dereq_('./utils/log.js'); 3196 3197 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 3198 3199 var _utilsToTitleCaseJs = _dereq_('./utils/to-title-case.js'); 3200 3201 var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs); 3202 3203 var _objectAssign = _dereq_('object.assign'); 3204 3205 var _objectAssign2 = _interopRequireDefault(_objectAssign); 3206 3207 var _utilsMergeOptionsJs = _dereq_('./utils/merge-options.js'); 3208 3209 var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs); 3210 3211 /** 3212 * Base UI Component class 3213 * Components are embeddable UI objects that are represented by both a 3214 * javascript object and an element in the DOM. They can be children of other 3215 * components, and can have many children themselves. 3216 * ```js 3217 * // adding a button to the player 3218 * var button = player.addChild('button'); 3219 * button.el(); // -> button element 3220 * ``` 3221 * ```html 3222 * <div class="video-js"> 3223 * <div class="vjs-button">Button</div> 3224 * </div> 3225 * ``` 3226 * Components are also event targets. 3227 * ```js 3228 * button.on('click', function(){ 3229 * console.log('Button Clicked!'); 3230 * }); 3231 * button.trigger('customevent'); 3232 * ``` 3233 * 3234 * @param {Object} player Main Player 3235 * @param {Object=} options Object of option names and values 3236 * @param {Function=} ready Ready callback function 3237 * @class Component 3238 */ 3239 3240 var Component = (function () { 3241 function Component(player, options, ready) { 3242 _classCallCheck(this, Component); 3243 3244 // The component might be the player itself and we can't pass `this` to super 3245 if (!player && this.play) { 3246 this.player_ = player = this; // eslint-disable-line 3247 } else { 3248 this.player_ = player; 3249 } 3250 3251 // Make a copy of prototype.options_ to protect against overriding defaults 3252 this.options_ = _utilsMergeOptionsJs2['default']({}, this.options_); 3253 3254 // Updated options with supplied options 3255 options = this.options_ = _utilsMergeOptionsJs2['default'](this.options_, options); 3256 3257 // Get ID from options or options element if one is supplied 3258 this.id_ = options.id || options.el && options.el.id; 3259 3260 // If there was no ID from the options, generate one 3261 if (!this.id_) { 3262 // Don't require the player ID function in the case of mock players 3263 var id = player && player.id && player.id() || 'no_player'; 3264 3265 this.id_ = id + '_component_' + Guid.newGUID(); 3266 } 3267 3268 this.name_ = options.name || null; 3269 3270 // Create element if one wasn't provided in options 3271 if (options.el) { 3272 this.el_ = options.el; 3273 } else if (options.createEl !== false) { 3274 this.el_ = this.createEl(); 3275 } 3276 3277 this.children_ = []; 3278 this.childIndex_ = {}; 3279 this.childNameIndex_ = {}; 3280 3281 // Add any child components in options 3282 if (options.initChildren !== false) { 3283 this.initChildren(); 3284 } 3285 3286 this.ready(ready); 3287 // Don't want to trigger ready here or it will before init is actually 3288 // finished for all children that run this constructor 3289 3290 if (options.reportTouchActivity !== false) { 3291 this.enableTouchActivity(); 3292 } 3293 } 3294 3295 /** 3296 * Dispose of the component and all child components 3297 * 3298 * @method dispose 3299 */ 3300 3301 Component.prototype.dispose = function dispose() { 3302 this.trigger({ type: 'dispose', bubbles: false }); 3303 3304 // Dispose all children. 3305 if (this.children_) { 3306 for (var i = this.children_.length - 1; i >= 0; i--) { 3307 if (this.children_[i].dispose) { 3308 this.children_[i].dispose(); 3309 } 3310 } 3311 } 3312 3313 // Delete child references 3314 this.children_ = null; 3315 this.childIndex_ = null; 3316 this.childNameIndex_ = null; 3317 3318 // Remove all event listeners. 3319 this.off(); 3320 3321 // Remove element from DOM 3322 if (this.el_.parentNode) { 3323 this.el_.parentNode.removeChild(this.el_); 3324 } 3325 3326 Dom.removeElData(this.el_); 3327 this.el_ = null; 3328 }; 3329 3330 /** 3331 * Return the component's player 3332 * 3333 * @return {Player} 3334 * @method player 3335 */ 3336 3337 Component.prototype.player = function player() { 3338 return this.player_; 3339 }; 3340 3341 /** 3342 * Deep merge of options objects 3343 * Whenever a property is an object on both options objects 3344 * the two properties will be merged using mergeOptions. 3345 * 3346 * ```js 3347 * Parent.prototype.options_ = { 3348 * optionSet: { 3349 * 'childOne': { 'foo': 'bar', 'asdf': 'fdsa' }, 3350 * 'childTwo': {}, 3351 * 'childThree': {} 3352 * } 3353 * } 3354 * newOptions = { 3355 * optionSet: { 3356 * 'childOne': { 'foo': 'baz', 'abc': '123' } 3357 * 'childTwo': null, 3358 * 'childFour': {} 3359 * } 3360 * } 3361 * 3362 * this.options(newOptions); 3363 * ``` 3364 * RESULT 3365 * ```js 3366 * { 3367 * optionSet: { 3368 * 'childOne': { 'foo': 'baz', 'asdf': 'fdsa', 'abc': '123' }, 3369 * 'childTwo': null, // Disabled. Won't be initialized. 3370 * 'childThree': {}, 3371 * 'childFour': {} 3372 * } 3373 * } 3374 * ``` 3375 * 3376 * @param {Object} obj Object of new option values 3377 * @return {Object} A NEW object of this.options_ and obj merged 3378 * @method options 3379 */ 3380 3381 Component.prototype.options = function options(obj) { 3382 _utilsLogJs2['default'].warn('this.options() has been deprecated and will be moved to the constructor in 6.0'); 3383 3384 if (!obj) { 3385 return this.options_; 3386 } 3387 3388 this.options_ = _utilsMergeOptionsJs2['default'](this.options_, obj); 3389 return this.options_; 3390 }; 3391 3392 /** 3393 * Get the component's DOM element 3394 * ```js 3395 * var domEl = myComponent.el(); 3396 * ``` 3397 * 3398 * @return {Element} 3399 * @method el 3400 */ 3401 3402 Component.prototype.el = function el() { 3403 return this.el_; 3404 }; 3405 3406 /** 3407 * Create the component's DOM element 3408 * 3409 * @param {String=} tagName Element's node type. e.g. 'div' 3410 * @param {Object=} properties An object of properties that should be set 3411 * @param {Object=} attributes An object of attributes that should be set 3412 * @return {Element} 3413 * @method createEl 3414 */ 3415 3416 Component.prototype.createEl = function createEl(tagName, properties, attributes) { 3417 return Dom.createEl(tagName, properties, attributes); 3418 }; 3419 3420 Component.prototype.localize = function localize(string) { 3421 var code = this.player_.language && this.player_.language(); 3422 var languages = this.player_.languages && this.player_.languages(); 3423 3424 if (!code || !languages) { 3425 return string; 3426 } 3427 3428 var language = languages[code]; 3429 3430 if (language && language[string]) { 3431 return language[string]; 3432 } 3433 3434 var primaryCode = code.split('-')[0]; 3435 var primaryLang = languages[primaryCode]; 3436 3437 if (primaryLang && primaryLang[string]) { 3438 return primaryLang[string]; 3439 } 3440 3441 return string; 3442 }; 3443 3444 /** 3445 * Return the component's DOM element where children are inserted. 3446 * Will either be the same as el() or a new element defined in createEl(). 3447 * 3448 * @return {Element} 3449 * @method contentEl 3450 */ 3451 3452 Component.prototype.contentEl = function contentEl() { 3453 return this.contentEl_ || this.el_; 3454 }; 3455 3456 /** 3457 * Get the component's ID 3458 * ```js 3459 * var id = myComponent.id(); 3460 * ``` 3461 * 3462 * @return {String} 3463 * @method id 3464 */ 3465 3466 Component.prototype.id = function id() { 3467 return this.id_; 3468 }; 3469 3470 /** 3471 * Get the component's name. The name is often used to reference the component. 3472 * ```js 3473 * var name = myComponent.name(); 3474 * ``` 3475 * 3476 * @return {String} 3477 * @method name 3478 */ 3479 3480 Component.prototype.name = function name() { 3481 return this.name_; 3482 }; 3483 3484 /** 3485 * Get an array of all child components 3486 * ```js 3487 * var kids = myComponent.children(); 3488 * ``` 3489 * 3490 * @return {Array} The children 3491 * @method children 3492 */ 3493 3494 Component.prototype.children = function children() { 3495 return this.children_; 3496 }; 3497 3498 /** 3499 * Returns a child component with the provided ID 3500 * 3501 * @return {Component} 3502 * @method getChildById 3503 */ 3504 3505 Component.prototype.getChildById = function getChildById(id) { 3506 return this.childIndex_[id]; 3507 }; 3508 3509 /** 3510 * Returns a child component with the provided name 3511 * 3512 * @return {Component} 3513 * @method getChild 3514 */ 3515 3516 Component.prototype.getChild = function getChild(name) { 3517 return this.childNameIndex_[name]; 3518 }; 3519 3520 /** 3521 * Adds a child component inside this component 3522 * ```js 3523 * myComponent.el(); 3524 * // -> <div class='my-component'></div> 3525 * myComponent.children(); 3526 * // [empty array] 3527 * 3528 * var myButton = myComponent.addChild('MyButton'); 3529 * // -> <div class='my-component'><div class="my-button">myButton<div></div> 3530 * // -> myButton === myComponent.children()[0]; 3531 * ``` 3532 * Pass in options for child constructors and options for children of the child 3533 * ```js 3534 * var myButton = myComponent.addChild('MyButton', { 3535 * text: 'Press Me', 3536 * buttonChildExample: { 3537 * buttonChildOption: true 3538 * } 3539 * }); 3540 * ``` 3541 * 3542 * @param {String|Component} child The class name or instance of a child to add 3543 * @param {Object=} options Options, including options to be passed to children of the child. 3544 * @param {Number} index into our children array to attempt to add the child 3545 * @return {Component} The child component (created by this process if a string was used) 3546 * @method addChild 3547 */ 3548 3549 Component.prototype.addChild = function addChild(child) { 3550 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 3551 var index = arguments.length <= 2 || arguments[2] === undefined ? this.children_.length : arguments[2]; 3552 3553 var component = undefined; 3554 var componentName = undefined; 3555 3556 // If child is a string, create nt with options 3557 if (typeof child === 'string') { 3558 componentName = child; 3559 3560 // Options can also be specified as a boolean, so convert to an empty object if false. 3561 if (!options) { 3562 options = {}; 3563 } 3564 3565 // Same as above, but true is deprecated so show a warning. 3566 if (options === true) { 3567 _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`.'); 3568 options = {}; 3569 } 3570 3571 // If no componentClass in options, assume componentClass is the name lowercased 3572 // (e.g. playButton) 3573 var componentClassName = options.componentClass || _utilsToTitleCaseJs2['default'](componentName); 3574 3575 // Set name through options 3576 options.name = componentName; 3577 3578 // Create a new object & element for this controls set 3579 // If there's no .player_, this is a player 3580 var ComponentClass = Component.getComponent(componentClassName); 3581 3582 if (!ComponentClass) { 3583 throw new Error('Component ' + componentClassName + ' does not exist'); 3584 } 3585 3586 // data stored directly on the videojs object may be 3587 // misidentified as a component to retain 3588 // backwards-compatibility with 4.x. check to make sure the 3589 // component class can be instantiated. 3590 if (typeof ComponentClass !== 'function') { 3591 return null; 3592 } 3593 3594 component = new ComponentClass(this.player_ || this, options); 3595 3596 // child is a component instance 3597 } else { 3598 component = child; 3599 } 3600 3601 this.children_.splice(index, 0, component); 3602 3603 if (typeof component.id === 'function') { 3604 this.childIndex_[component.id()] = component; 3605 } 3606 3607 // If a name wasn't used to create the component, check if we can use the 3608 // name function of the component 3609 componentName = componentName || component.name && component.name(); 3610 3611 if (componentName) { 3612 this.childNameIndex_[componentName] = component; 3613 } 3614 3615 // Add the UI object's element to the container div (box) 3616 // Having an element is not required 3617 if (typeof component.el === 'function' && component.el()) { 3618 var childNodes = this.contentEl().children; 3619 var refNode = childNodes[index] || null; 3620 this.contentEl().insertBefore(component.el(), refNode); 3621 } 3622 3623 // Return so it can stored on parent object if desired. 3624 return component; 3625 }; 3626 3627 /** 3628 * Remove a child component from this component's list of children, and the 3629 * child component's element from this component's element 3630 * 3631 * @param {Component} component Component to remove 3632 * @method removeChild 3633 */ 3634 3635 Component.prototype.removeChild = function removeChild(component) { 3636 if (typeof component === 'string') { 3637 component = this.getChild(component); 3638 } 3639 3640 if (!component || !this.children_) { 3641 return; 3642 } 3643 3644 var childFound = false; 3645 3646 for (var i = this.children_.length - 1; i >= 0; i--) { 3647 if (this.children_[i] === component) { 3648 childFound = true; 3649 this.children_.splice(i, 1); 3650 break; 3651 } 3652 } 3653 3654 if (!childFound) { 3655 return; 3656 } 3657 3658 this.childIndex_[component.id()] = null; 3659 this.childNameIndex_[component.name()] = null; 3660 3661 var compEl = component.el(); 3662 3663 if (compEl && compEl.parentNode === this.contentEl()) { 3664 this.contentEl().removeChild(component.el()); 3665 } 3666 }; 3667 3668 /** 3669 * Add and initialize default child components from options 3670 * ```js 3671 * // when an instance of MyComponent is created, all children in options 3672 * // will be added to the instance by their name strings and options 3673 * MyComponent.prototype.options_ = { 3674 * children: [ 3675 * 'myChildComponent' 3676 * ], 3677 * myChildComponent: { 3678 * myChildOption: true 3679 * } 3680 * }; 3681 * 3682 * // Or when creating the component 3683 * var myComp = new MyComponent(player, { 3684 * children: [ 3685 * 'myChildComponent' 3686 * ], 3687 * myChildComponent: { 3688 * myChildOption: true 3689 * } 3690 * }); 3691 * ``` 3692 * The children option can also be an array of 3693 * child options objects (that also include a 'name' key). 3694 * This can be used if you have two child components of the 3695 * same type that need different options. 3696 * ```js 3697 * var myComp = new MyComponent(player, { 3698 * children: [ 3699 * 'button', 3700 * { 3701 * name: 'button', 3702 * someOtherOption: true 3703 * }, 3704 * { 3705 * name: 'button', 3706 * someOtherOption: false 3707 * } 3708 * ] 3709 * }); 3710 * ``` 3711 * 3712 * @method initChildren 3713 */ 3714 3715 Component.prototype.initChildren = function initChildren() { 3716 var _this = this; 3717 3718 var children = this.options_.children; 3719 3720 if (children) { 3721 (function () { 3722 // `this` is `parent` 3723 var parentOptions = _this.options_; 3724 3725 var handleAdd = function handleAdd(child) { 3726 var name = child.name; 3727 var opts = child.opts; 3728 3729 // Allow options for children to be set at the parent options 3730 // e.g. videojs(id, { controlBar: false }); 3731 // instead of videojs(id, { children: { controlBar: false }); 3732 if (parentOptions[name] !== undefined) { 3733 opts = parentOptions[name]; 3734 } 3735 3736 // Allow for disabling default components 3737 // e.g. options['children']['posterImage'] = false 3738 if (opts === false) { 3739 return; 3740 } 3741 3742 // Allow options to be passed as a simple boolean if no configuration 3743 // is necessary. 3744 if (opts === true) { 3745 opts = {}; 3746 } 3747 3748 // We also want to pass the original player options to each component as well so they don't need to 3749 // reach back into the player for options later. 3750 opts.playerOptions = _this.options_.playerOptions; 3751 3752 // Create and add the child component. 3753 // Add a direct reference to the child by name on the parent instance. 3754 // If two of the same component are used, different names should be supplied 3755 // for each 3756 var newChild = _this.addChild(name, opts); 3757 if (newChild) { 3758 _this[name] = newChild; 3759 } 3760 }; 3761 3762 // Allow for an array of children details to passed in the options 3763 var workingChildren = undefined; 3764 var Tech = Component.getComponent('Tech'); 3765 3766 if (Array.isArray(children)) { 3767 workingChildren = children; 3768 } else { 3769 workingChildren = Object.keys(children); 3770 } 3771 3772 workingChildren 3773 // children that are in this.options_ but also in workingChildren would 3774 // give us extra children we do not want. So, we want to filter them out. 3775 .concat(Object.keys(_this.options_).filter(function (child) { 3776 return !workingChildren.some(function (wchild) { 3777 if (typeof wchild === 'string') { 3778 return child === wchild; 3779 } else { 3780 return child === wchild.name; 3781 } 3782 }); 3783 })).map(function (child) { 3784 var name = undefined, 3785 opts = undefined; 3786 3787 if (typeof child === 'string') { 3788 name = child; 3789 opts = children[name] || _this.options_[name] || {}; 3790 } else { 3791 name = child.name; 3792 opts = child; 3793 } 3794 3795 return { name: name, opts: opts }; 3796 }).filter(function (child) { 3797 // we have to make sure that child.name isn't in the techOrder since 3798 // techs are registerd as Components but can't aren't compatible 3799 // See https://github.com/videojs/video.js/issues/2772 3800 var c = Component.getComponent(child.opts.componentClass || _utilsToTitleCaseJs2['default'](child.name)); 3801 return c && !Tech.isTech(c); 3802 }).forEach(handleAdd); 3803 })(); 3804 } 3805 }; 3806 3807 /** 3808 * Allows sub components to stack CSS class names 3809 * 3810 * @return {String} The constructed class name 3811 * @method buildCSSClass 3812 */ 3813 3814 Component.prototype.buildCSSClass = function buildCSSClass() { 3815 // Child classes can include a function that does: 3816 // return 'CLASS NAME' + this._super(); 3817 return ''; 3818 }; 3819 3820 /** 3821 * Add an event listener to this component's element 3822 * ```js 3823 * var myFunc = function(){ 3824 * var myComponent = this; 3825 * // Do something when the event is fired 3826 * }; 3827 * 3828 * myComponent.on('eventType', myFunc); 3829 * ``` 3830 * The context of myFunc will be myComponent unless previously bound. 3831 * Alternatively, you can add a listener to another element or component. 3832 * ```js 3833 * myComponent.on(otherElement, 'eventName', myFunc); 3834 * myComponent.on(otherComponent, 'eventName', myFunc); 3835 * ``` 3836 * The benefit of using this over `VjsEvents.on(otherElement, 'eventName', myFunc)` 3837 * and `otherComponent.on('eventName', myFunc)` is that this way the listeners 3838 * will be automatically cleaned up when either component is disposed. 3839 * It will also bind myComponent as the context of myFunc. 3840 * **NOTE**: When using this on elements in the page other than window 3841 * and document (both permanent), if you remove the element from the DOM 3842 * you need to call `myComponent.trigger(el, 'dispose')` on it to clean up 3843 * references to it and allow the browser to garbage collect it. 3844 * 3845 * @param {String|Component} first The event type or other component 3846 * @param {Function|String} second The event handler or event type 3847 * @param {Function} third The event handler 3848 * @return {Component} 3849 * @method on 3850 */ 3851 3852 Component.prototype.on = function on(first, second, third) { 3853 var _this2 = this; 3854 3855 if (typeof first === 'string' || Array.isArray(first)) { 3856 Events.on(this.el_, first, Fn.bind(this, second)); 3857 3858 // Targeting another component or element 3859 } else { 3860 (function () { 3861 var target = first; 3862 var type = second; 3863 var fn = Fn.bind(_this2, third); 3864 3865 // When this component is disposed, remove the listener from the other component 3866 var removeOnDispose = function removeOnDispose() { 3867 return _this2.off(target, type, fn); 3868 }; 3869 3870 // Use the same function ID so we can remove it later it using the ID 3871 // of the original listener 3872 removeOnDispose.guid = fn.guid; 3873 _this2.on('dispose', removeOnDispose); 3874 3875 // If the other component is disposed first we need to clean the reference 3876 // to the other component in this component's removeOnDispose listener 3877 // Otherwise we create a memory leak. 3878 var cleanRemover = function cleanRemover() { 3879 return _this2.off('dispose', removeOnDispose); 3880 }; 3881 3882 // Add the same function ID so we can easily remove it later 3883 cleanRemover.guid = fn.guid; 3884 3885 // Check if this is a DOM node 3886 if (first.nodeName) { 3887 // Add the listener to the other element 3888 Events.on(target, type, fn); 3889 Events.on(target, 'dispose', cleanRemover); 3890 3891 // Should be a component 3892 // Not using `instanceof Component` because it makes mock players difficult 3893 } else if (typeof first.on === 'function') { 3894 // Add the listener to the other component 3895 target.on(type, fn); 3896 target.on('dispose', cleanRemover); 3897 } 3898 })(); 3899 } 3900 3901 return this; 3902 }; 3903 3904 /** 3905 * Remove an event listener from this component's element 3906 * ```js 3907 * myComponent.off('eventType', myFunc); 3908 * ``` 3909 * If myFunc is excluded, ALL listeners for the event type will be removed. 3910 * If eventType is excluded, ALL listeners will be removed from the component. 3911 * Alternatively you can use `off` to remove listeners that were added to other 3912 * elements or components using `myComponent.on(otherComponent...`. 3913 * In this case both the event type and listener function are REQUIRED. 3914 * ```js 3915 * myComponent.off(otherElement, 'eventType', myFunc); 3916 * myComponent.off(otherComponent, 'eventType', myFunc); 3917 * ``` 3918 * 3919 * @param {String=|Component} first The event type or other component 3920 * @param {Function=|String} second The listener function or event type 3921 * @param {Function=} third The listener for other component 3922 * @return {Component} 3923 * @method off 3924 */ 3925 3926 Component.prototype.off = function off(first, second, third) { 3927 if (!first || typeof first === 'string' || Array.isArray(first)) { 3928 Events.off(this.el_, first, second); 3929 } else { 3930 var target = first; 3931 var type = second; 3932 // Ensure there's at least a guid, even if the function hasn't been used 3933 var fn = Fn.bind(this, third); 3934 3935 // Remove the dispose listener on this component, 3936 // which was given the same guid as the event listener 3937 this.off('dispose', fn); 3938 3939 if (first.nodeName) { 3940 // Remove the listener 3941 Events.off(target, type, fn); 3942 // Remove the listener for cleaning the dispose listener 3943 Events.off(target, 'dispose', fn); 3944 } else { 3945 target.off(type, fn); 3946 target.off('dispose', fn); 3947 } 3948 } 3949 3950 return this; 3951 }; 3952 3953 /** 3954 * Add an event listener to be triggered only once and then removed 3955 * ```js 3956 * myComponent.one('eventName', myFunc); 3957 * ``` 3958 * Alternatively you can add a listener to another element or component 3959 * that will be triggered only once. 3960 * ```js 3961 * myComponent.one(otherElement, 'eventName', myFunc); 3962 * myComponent.one(otherComponent, 'eventName', myFunc); 3963 * ``` 3964 * 3965 * @param {String|Component} first The event type or other component 3966 * @param {Function|String} second The listener function or event type 3967 * @param {Function=} third The listener function for other component 3968 * @return {Component} 3969 * @method one 3970 */ 3971 3972 Component.prototype.one = function one(first, second, third) { 3973 var _this3 = this, 3974 _arguments = arguments; 3975 3976 if (typeof first === 'string' || Array.isArray(first)) { 3977 Events.one(this.el_, first, Fn.bind(this, second)); 3978 } else { 3979 (function () { 3980 var target = first; 3981 var type = second; 3982 var fn = Fn.bind(_this3, third); 3983 3984 var newFunc = function newFunc() { 3985 _this3.off(target, type, newFunc); 3986 fn.apply(null, _arguments); 3987 }; 3988 3989 // Keep the same function ID so we can remove it later 3990 newFunc.guid = fn.guid; 3991 3992 _this3.on(target, type, newFunc); 3993 })(); 3994 } 3995 3996 return this; 3997 }; 3998 3999 /** 4000 * Trigger an event on an element 4001 * ```js 4002 * myComponent.trigger('eventName'); 4003 * myComponent.trigger({'type':'eventName'}); 4004 * myComponent.trigger('eventName', {data: 'some data'}); 4005 * myComponent.trigger({'type':'eventName'}, {data: 'some data'}); 4006 * ``` 4007 * 4008 * @param {Event|Object|String} event A string (the type) or an event object with a type attribute 4009 * @param {Object} [hash] data hash to pass along with the event 4010 * @return {Component} self 4011 * @method trigger 4012 */ 4013 4014 Component.prototype.trigger = function trigger(event, hash) { 4015 Events.trigger(this.el_, event, hash); 4016 return this; 4017 }; 4018 4019 /** 4020 * Bind a listener to the component's ready state. 4021 * Different from event listeners in that if the ready event has already happened 4022 * it will trigger the function immediately. 4023 * 4024 * @param {Function} fn Ready listener 4025 * @param {Boolean} sync Exec the listener synchronously if component is ready 4026 * @return {Component} 4027 * @method ready 4028 */ 4029 4030 Component.prototype.ready = function ready(fn) { 4031 var sync = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; 4032 4033 if (fn) { 4034 if (this.isReady_) { 4035 if (sync) { 4036 fn.call(this); 4037 } else { 4038 // Call the function asynchronously by default for consistency 4039 this.setTimeout(fn, 1); 4040 } 4041 } else { 4042 this.readyQueue_ = this.readyQueue_ || []; 4043 this.readyQueue_.push(fn); 4044 } 4045 } 4046 return this; 4047 }; 4048 4049 /** 4050 * Trigger the ready listeners 4051 * 4052 * @return {Component} 4053 * @method triggerReady 4054 */ 4055 4056 Component.prototype.triggerReady = function triggerReady() { 4057 this.isReady_ = true; 4058 4059 // Ensure ready is triggerd asynchronously 4060 this.setTimeout(function () { 4061 var readyQueue = this.readyQueue_; 4062 4063 // Reset Ready Queue 4064 this.readyQueue_ = []; 4065 4066 if (readyQueue && readyQueue.length > 0) { 4067 readyQueue.forEach(function (fn) { 4068 fn.call(this); 4069 }, this); 4070 } 4071 4072 // Allow for using event listeners also 4073 this.trigger('ready'); 4074 }, 1); 4075 }; 4076 4077 /** 4078 * Finds a single DOM element matching `selector` within the component's 4079 * `contentEl` or another custom context. 4080 * 4081 * @method $ 4082 * @param {String} selector 4083 * A valid CSS selector, which will be passed to `querySelector`. 4084 * 4085 * @param {Element|String} [context=document] 4086 * A DOM element within which to query. Can also be a selector 4087 * string in which case the first matching element will be used 4088 * as context. If missing (or no element matches selector), falls 4089 * back to `document`. 4090 * 4091 * @return {Element|null} 4092 */ 4093 4094 Component.prototype.$ = function $(selector, context) { 4095 return Dom.$(selector, context || this.contentEl()); 4096 }; 4097 4098 /** 4099 * Finds a all DOM elements matching `selector` within the component's 4100 * `contentEl` or another custom context. 4101 * 4102 * @method $$ 4103 * @param {String} selector 4104 * A valid CSS selector, which will be passed to `querySelectorAll`. 4105 * 4106 * @param {Element|String} [context=document] 4107 * A DOM element within which to query. Can also be a selector 4108 * string in which case the first matching element will be used 4109 * as context. If missing (or no element matches selector), falls 4110 * back to `document`. 4111 * 4112 * @return {NodeList} 4113 */ 4114 4115 Component.prototype.$$ = function $$(selector, context) { 4116 return Dom.$$(selector, context || this.contentEl()); 4117 }; 4118 4119 /** 4120 * Check if a component's element has a CSS class name 4121 * 4122 * @param {String} classToCheck Classname to check 4123 * @return {Component} 4124 * @method hasClass 4125 */ 4126 4127 Component.prototype.hasClass = function hasClass(classToCheck) { 4128 return Dom.hasElClass(this.el_, classToCheck); 4129 }; 4130 4131 /** 4132 * Add a CSS class name to the component's element 4133 * 4134 * @param {String} classToAdd Classname to add 4135 * @return {Component} 4136 * @method addClass 4137 */ 4138 4139 Component.prototype.addClass = function addClass(classToAdd) { 4140 Dom.addElClass(this.el_, classToAdd); 4141 return this; 4142 }; 4143 4144 /** 4145 * Remove a CSS class name from the component's element 4146 * 4147 * @param {String} classToRemove Classname to remove 4148 * @return {Component} 4149 * @method removeClass 4150 */ 4151 4152 Component.prototype.removeClass = function removeClass(classToRemove) { 4153 Dom.removeElClass(this.el_, classToRemove); 4154 return this; 4155 }; 4156 4157 /** 4158 * Add or remove a CSS class name from the component's element 4159 * 4160 * @param {String} classToToggle 4161 * @param {Boolean|Function} [predicate] 4162 * Can be a function that returns a Boolean. If `true`, the class 4163 * will be added; if `false`, the class will be removed. If not 4164 * given, the class will be added if not present and vice versa. 4165 * 4166 * @return {Component} 4167 * @method toggleClass 4168 */ 4169 4170 Component.prototype.toggleClass = function toggleClass(classToToggle, predicate) { 4171 Dom.toggleElClass(this.el_, classToToggle, predicate); 4172 return this; 4173 }; 4174 4175 /** 4176 * Show the component element if hidden 4177 * 4178 * @return {Component} 4179 * @method show 4180 */ 4181 4182 Component.prototype.show = function show() { 4183 this.removeClass('vjs-hidden'); 4184 return this; 4185 }; 4186 4187 /** 4188 * Hide the component element if currently showing 4189 * 4190 * @return {Component} 4191 * @method hide 4192 */ 4193 4194 Component.prototype.hide = function hide() { 4195 this.addClass('vjs-hidden'); 4196 return this; 4197 }; 4198 4199 /** 4200 * Lock an item in its visible state 4201 * To be used with fadeIn/fadeOut. 4202 * 4203 * @return {Component} 4204 * @private 4205 * @method lockShowing 4206 */ 4207 4208 Component.prototype.lockShowing = function lockShowing() { 4209 this.addClass('vjs-lock-showing'); 4210 return this; 4211 }; 4212 4213 /** 4214 * Unlock an item to be hidden 4215 * To be used with fadeIn/fadeOut. 4216 * 4217 * @return {Component} 4218 * @private 4219 * @method unlockShowing 4220 */ 4221 4222 Component.prototype.unlockShowing = function unlockShowing() { 4223 this.removeClass('vjs-lock-showing'); 4224 return this; 4225 }; 4226 4227 /** 4228 * Set or get the width of the component (CSS values) 4229 * Setting the video tag dimension values only works with values in pixels. 4230 * Percent values will not work. 4231 * Some percents can be used, but width()/height() will return the number + %, 4232 * not the actual computed width/height. 4233 * 4234 * @param {Number|String=} num Optional width number 4235 * @param {Boolean} skipListeners Skip the 'resize' event trigger 4236 * @return {Component} This component, when setting the width 4237 * @return {Number|String} The width, when getting 4238 * @method width 4239 */ 4240 4241 Component.prototype.width = function width(num, skipListeners) { 4242 return this.dimension('width', num, skipListeners); 4243 }; 4244 4245 /** 4246 * Get or set the height of the component (CSS values) 4247 * Setting the video tag dimension values only works with values in pixels. 4248 * Percent values will not work. 4249 * Some percents can be used, but width()/height() will return the number + %, 4250 * not the actual computed width/height. 4251 * 4252 * @param {Number|String=} num New component height 4253 * @param {Boolean=} skipListeners Skip the resize event trigger 4254 * @return {Component} This component, when setting the height 4255 * @return {Number|String} The height, when getting 4256 * @method height 4257 */ 4258 4259 Component.prototype.height = function height(num, skipListeners) { 4260 return this.dimension('height', num, skipListeners); 4261 }; 4262 4263 /** 4264 * Set both width and height at the same time 4265 * 4266 * @param {Number|String} width Width of player 4267 * @param {Number|String} height Height of player 4268 * @return {Component} The component 4269 * @method dimensions 4270 */ 4271 4272 Component.prototype.dimensions = function dimensions(width, height) { 4273 // Skip resize listeners on width for optimization 4274 return this.width(width, true).height(height); 4275 }; 4276 4277 /** 4278 * Get or set width or height 4279 * This is the shared code for the width() and height() methods. 4280 * All for an integer, integer + 'px' or integer + '%'; 4281 * Known issue: Hidden elements officially have a width of 0. We're defaulting 4282 * to the style.width value and falling back to computedStyle which has the 4283 * hidden element issue. Info, but probably not an efficient fix: 4284 * http://www.foliotek.com/devblog/getting-the-width-of-a-hidden-element-with-jquery-using-width/ 4285 * 4286 * @param {String} widthOrHeight 'width' or 'height' 4287 * @param {Number|String=} num New dimension 4288 * @param {Boolean=} skipListeners Skip resize event trigger 4289 * @return {Component} The component if a dimension was set 4290 * @return {Number|String} The dimension if nothing was set 4291 * @private 4292 * @method dimension 4293 */ 4294 4295 Component.prototype.dimension = function dimension(widthOrHeight, num, skipListeners) { 4296 if (num !== undefined) { 4297 // Set to zero if null or literally NaN (NaN !== NaN) 4298 if (num === null || num !== num) { 4299 num = 0; 4300 } 4301 4302 // Check if using css width/height (% or px) and adjust 4303 if (('' + num).indexOf('%') !== -1 || ('' + num).indexOf('px') !== -1) { 4304 this.el_.style[widthOrHeight] = num; 4305 } else if (num === 'auto') { 4306 this.el_.style[widthOrHeight] = ''; 4307 } else { 4308 this.el_.style[widthOrHeight] = num + 'px'; 4309 } 4310 4311 // skipListeners allows us to avoid triggering the resize event when setting both width and height 4312 if (!skipListeners) { 4313 this.trigger('resize'); 4314 } 4315 4316 // Return component 4317 return this; 4318 } 4319 4320 // Not setting a value, so getting it 4321 // Make sure element exists 4322 if (!this.el_) { 4323 return 0; 4324 } 4325 4326 // Get dimension value from style 4327 var val = this.el_.style[widthOrHeight]; 4328 var pxIndex = val.indexOf('px'); 4329 4330 if (pxIndex !== -1) { 4331 // Return the pixel value with no 'px' 4332 return parseInt(val.slice(0, pxIndex), 10); 4333 } 4334 4335 // No px so using % or no style was set, so falling back to offsetWidth/height 4336 // If component has display:none, offset will return 0 4337 // TODO: handle display:none and no dimension style using px 4338 return parseInt(this.el_['offset' + _utilsToTitleCaseJs2['default'](widthOrHeight)], 10); 4339 }; 4340 4341 /** 4342 * Get width or height of computed style 4343 * @param {String} widthOrHeight 'width' or 'height' 4344 * @return {Number|Boolean} The bolean false if nothing was set 4345 * @method currentDimension 4346 */ 4347 4348 Component.prototype.currentDimension = function currentDimension(widthOrHeight) { 4349 var computedWidthOrHeight = 0; 4350 4351 if (widthOrHeight !== 'width' && widthOrHeight !== 'height') { 4352 throw new Error('currentDimension only accepts width or height value'); 4353 } 4354 4355 if (typeof _globalWindow2['default'].getComputedStyle === 'function') { 4356 var computedStyle = _globalWindow2['default'].getComputedStyle(this.el_); 4357 computedWidthOrHeight = computedStyle.getPropertyValue(widthOrHeight) || computedStyle[widthOrHeight]; 4358 } else if (this.el_.currentStyle) { 4359 // ie 8 doesn't support computed style, shim it 4360 // return clientWidth or clientHeight instead for better accuracy 4361 var rule = 'offset' + _utilsToTitleCaseJs2['default'](widthOrHeight); 4362 computedWidthOrHeight = this.el_[rule]; 4363 } 4364 4365 // remove 'px' from variable and parse as integer 4366 computedWidthOrHeight = parseFloat(computedWidthOrHeight); 4367 return computedWidthOrHeight; 4368 }; 4369 4370 /** 4371 * Get an object which contains width and height values of computed style 4372 * @return {Object} The dimensions of element 4373 * @method currentDimensions 4374 */ 4375 4376 Component.prototype.currentDimensions = function currentDimensions() { 4377 return { 4378 width: this.currentDimension('width'), 4379 height: this.currentDimension('height') 4380 }; 4381 }; 4382 4383 /** 4384 * Get width of computed style 4385 * @return {Integer} 4386 * @method currentWidth 4387 */ 4388 4389 Component.prototype.currentWidth = function currentWidth() { 4390 return this.currentDimension('width'); 4391 }; 4392 4393 /** 4394 * Get height of computed style 4395 * @return {Integer} 4396 * @method currentHeight 4397 */ 4398 4399 Component.prototype.currentHeight = function currentHeight() { 4400 return this.currentDimension('height'); 4401 }; 4402 4403 /** 4404 * Emit 'tap' events when touch events are supported 4405 * This is used to support toggling the controls through a tap on the video. 4406 * We're requiring them to be enabled because otherwise every component would 4407 * have this extra overhead unnecessarily, on mobile devices where extra 4408 * overhead is especially bad. 4409 * 4410 * @private 4411 * @method emitTapEvents 4412 */ 4413 4414 Component.prototype.emitTapEvents = function emitTapEvents() { 4415 // Track the start time so we can determine how long the touch lasted 4416 var touchStart = 0; 4417 var firstTouch = null; 4418 4419 // Maximum movement allowed during a touch event to still be considered a tap 4420 // Other popular libs use anywhere from 2 (hammer.js) to 15, so 10 seems like a nice, round number. 4421 var tapMovementThreshold = 10; 4422 4423 // The maximum length a touch can be while still being considered a tap 4424 var touchTimeThreshold = 200; 4425 4426 var couldBeTap = undefined; 4427 4428 this.on('touchstart', function (event) { 4429 // If more than one finger, don't consider treating this as a click 4430 if (event.touches.length === 1) { 4431 // Copy the touches object to prevent modifying the original 4432 firstTouch = _objectAssign2['default']({}, event.touches[0]); 4433 // Record start time so we can detect a tap vs. "touch and hold" 4434 touchStart = new Date().getTime(); 4435 // Reset couldBeTap tracking 4436 couldBeTap = true; 4437 } 4438 }); 4439 4440 this.on('touchmove', function (event) { 4441 // If more than one finger, don't consider treating this as a click 4442 if (event.touches.length > 1) { 4443 couldBeTap = false; 4444 } else if (firstTouch) { 4445 // Some devices will throw touchmoves for all but the slightest of taps. 4446 // So, if we moved only a small distance, this could still be a tap 4447 var xdiff = event.touches[0].pageX - firstTouch.pageX; 4448 var ydiff = event.touches[0].pageY - firstTouch.pageY; 4449 var touchDistance = Math.sqrt(xdiff * xdiff + ydiff * ydiff); 4450 4451 if (touchDistance > tapMovementThreshold) { 4452 couldBeTap = false; 4453 } 4454 } 4455 }); 4456 4457 var noTap = function noTap() { 4458 couldBeTap = false; 4459 }; 4460 4461 // TODO: Listen to the original target. http://youtu.be/DujfpXOKUp8?t=13m8s 4462 this.on('touchleave', noTap); 4463 this.on('touchcancel', noTap); 4464 4465 // When the touch ends, measure how long it took and trigger the appropriate 4466 // event 4467 this.on('touchend', function (event) { 4468 firstTouch = null; 4469 // Proceed only if the touchmove/leave/cancel event didn't happen 4470 if (couldBeTap === true) { 4471 // Measure how long the touch lasted 4472 var touchTime = new Date().getTime() - touchStart; 4473 4474 // Make sure the touch was less than the threshold to be considered a tap 4475 if (touchTime < touchTimeThreshold) { 4476 // Don't let browser turn this into a click 4477 event.preventDefault(); 4478 this.trigger('tap'); 4479 // It may be good to copy the touchend event object and change the 4480 // type to tap, if the other event properties aren't exact after 4481 // Events.fixEvent runs (e.g. event.target) 4482 } 4483 } 4484 }); 4485 }; 4486 4487 /** 4488 * Report user touch activity when touch events occur 4489 * User activity is used to determine when controls should show/hide. It's 4490 * relatively simple when it comes to mouse events, because any mouse event 4491 * should show the controls. So we capture mouse events that bubble up to the 4492 * player and report activity when that happens. 4493 * With touch events it isn't as easy. We can't rely on touch events at the 4494 * player level, because a tap (touchstart + touchend) on the video itself on 4495 * mobile devices is meant to turn controls off (and on). User activity is 4496 * checked asynchronously, so what could happen is a tap event on the video 4497 * turns the controls off, then the touchend event bubbles up to the player, 4498 * which if it reported user activity, would turn the controls right back on. 4499 * (We also don't want to completely block touch events from bubbling up) 4500 * Also a touchmove, touch+hold, and anything other than a tap is not supposed 4501 * to turn the controls back on on a mobile device. 4502 * Here we're setting the default component behavior to report user activity 4503 * whenever touch events happen, and this can be turned off by components that 4504 * want touch events to act differently. 4505 * 4506 * @method enableTouchActivity 4507 */ 4508 4509 Component.prototype.enableTouchActivity = function enableTouchActivity() { 4510 // Don't continue if the root player doesn't support reporting user activity 4511 if (!this.player() || !this.player().reportUserActivity) { 4512 return; 4513 } 4514 4515 // listener for reporting that the user is active 4516 var report = Fn.bind(this.player(), this.player().reportUserActivity); 4517 4518 var touchHolding = undefined; 4519 4520 this.on('touchstart', function () { 4521 report(); 4522 // For as long as the they are touching the device or have their mouse down, 4523 // we consider them active even if they're not moving their finger or mouse. 4524 // So we want to continue to update that they are active 4525 this.clearInterval(touchHolding); 4526 // report at the same interval as activityCheck 4527 touchHolding = this.setInterval(report, 250); 4528 }); 4529 4530 var touchEnd = function touchEnd(event) { 4531 report(); 4532 // stop the interval that maintains activity if the touch is holding 4533 this.clearInterval(touchHolding); 4534 }; 4535 4536 this.on('touchmove', report); 4537 this.on('touchend', touchEnd); 4538 this.on('touchcancel', touchEnd); 4539 }; 4540 4541 /** 4542 * Creates timeout and sets up disposal automatically. 4543 * 4544 * @param {Function} fn The function to run after the timeout. 4545 * @param {Number} timeout Number of ms to delay before executing specified function. 4546 * @return {Number} Returns the timeout ID 4547 * @method setTimeout 4548 */ 4549 4550 Component.prototype.setTimeout = function setTimeout(fn, timeout) { 4551 fn = Fn.bind(this, fn); 4552 4553 // window.setTimeout would be preferable here, but due to some bizarre issue with Sinon and/or Phantomjs, we can't. 4554 var timeoutId = _globalWindow2['default'].setTimeout(fn, timeout); 4555 4556 var disposeFn = function disposeFn() { 4557 this.clearTimeout(timeoutId); 4558 }; 4559 4560 disposeFn.guid = 'vjs-timeout-' + timeoutId; 4561 4562 this.on('dispose', disposeFn); 4563 4564 return timeoutId; 4565 }; 4566 4567 /** 4568 * Clears a timeout and removes the associated dispose listener 4569 * 4570 * @param {Number} timeoutId The id of the timeout to clear 4571 * @return {Number} Returns the timeout ID 4572 * @method clearTimeout 4573 */ 4574 4575 Component.prototype.clearTimeout = function clearTimeout(timeoutId) { 4576 _globalWindow2['default'].clearTimeout(timeoutId); 4577 4578 var disposeFn = function disposeFn() {}; 4579 4580 disposeFn.guid = 'vjs-timeout-' + timeoutId; 4581 4582 this.off('dispose', disposeFn); 4583 4584 return timeoutId; 4585 }; 4586 4587 /** 4588 * Creates an interval and sets up disposal automatically. 4589 * 4590 * @param {Function} fn The function to run every N seconds. 4591 * @param {Number} interval Number of ms to delay before executing specified function. 4592 * @return {Number} Returns the interval ID 4593 * @method setInterval 4594 */ 4595 4596 Component.prototype.setInterval = function setInterval(fn, interval) { 4597 fn = Fn.bind(this, fn); 4598 4599 var intervalId = _globalWindow2['default'].setInterval(fn, interval); 4600 4601 var disposeFn = function disposeFn() { 4602 this.clearInterval(intervalId); 4603 }; 4604 4605 disposeFn.guid = 'vjs-interval-' + intervalId; 4606 4607 this.on('dispose', disposeFn); 4608 4609 return intervalId; 4610 }; 4611 4612 /** 4613 * Clears an interval and removes the associated dispose listener 4614 * 4615 * @param {Number} intervalId The id of the interval to clear 4616 * @return {Number} Returns the interval ID 4617 * @method clearInterval 4618 */ 4619 4620 Component.prototype.clearInterval = function clearInterval(intervalId) { 4621 _globalWindow2['default'].clearInterval(intervalId); 4622 4623 var disposeFn = function disposeFn() {}; 4624 4625 disposeFn.guid = 'vjs-interval-' + intervalId; 4626 4627 this.off('dispose', disposeFn); 4628 4629 return intervalId; 4630 }; 4631 4632 /** 4633 * Registers a component 4634 * 4635 * @param {String} name Name of the component to register 4636 * @param {Object} comp The component to register 4637 * @static 4638 * @method registerComponent 4639 */ 4640 4641 Component.registerComponent = function registerComponent(name, comp) { 4642 if (!Component.components_) { 4643 Component.components_ = {}; 4644 } 4645 4646 Component.components_[name] = comp; 4647 return comp; 4648 }; 4649 4650 /** 4651 * Gets a component by name 4652 * 4653 * @param {String} name Name of the component to get 4654 * @return {Component} 4655 * @static 4656 * @method getComponent 4657 */ 4658 4659 Component.getComponent = function getComponent(name) { 4660 if (Component.components_ && Component.components_[name]) { 4661 return Component.components_[name]; 4662 } 4663 4664 if (_globalWindow2['default'] && _globalWindow2['default'].videojs && _globalWindow2['default'].videojs[name]) { 4665 _utilsLogJs2['default'].warn('The ' + name + ' component was added to the videojs object when it should be registered using videojs.registerComponent(name, component)'); 4666 return _globalWindow2['default'].videojs[name]; 4667 } 4668 }; 4669 4670 /** 4671 * Sets up the constructor using the supplied init method 4672 * or uses the init of the parent object 4673 * 4674 * @param {Object} props An object of properties 4675 * @static 4676 * @deprecated 4677 * @method extend 4678 */ 4679 4680 Component.extend = function extend(props) { 4681 props = props || {}; 4682 4683 _utilsLogJs2['default'].warn('Component.extend({}) has been deprecated, use videojs.extend(Component, {}) instead'); 4684 4685 // Set up the constructor using the supplied init method 4686 // or using the init of the parent object 4687 // Make sure to check the unobfuscated version for external libs 4688 var init = props.init || props.init || this.prototype.init || this.prototype.init || function () {}; 4689 // In Resig's simple class inheritance (previously used) the constructor 4690 // is a function that calls `this.init.apply(arguments)` 4691 // However that would prevent us from using `ParentObject.call(this);` 4692 // in a Child constructor because the `this` in `this.init` 4693 // would still refer to the Child and cause an infinite loop. 4694 // We would instead have to do 4695 // `ParentObject.prototype.init.apply(this, arguments);` 4696 // Bleh. We're not creating a _super() function, so it's good to keep 4697 // the parent constructor reference simple. 4698 var subObj = function subObj() { 4699 init.apply(this, arguments); 4700 }; 4701 4702 // Inherit from this object's prototype 4703 subObj.prototype = Object.create(this.prototype); 4704 // Reset the constructor property for subObj otherwise 4705 // instances of subObj would have the constructor of the parent Object 4706 subObj.prototype.constructor = subObj; 4707 4708 // Make the class extendable 4709 subObj.extend = Component.extend; 4710 4711 // Extend subObj's prototype with functions and other properties from props 4712 for (var _name in props) { 4713 if (props.hasOwnProperty(_name)) { 4714 subObj.prototype[_name] = props[_name]; 4715 } 4716 } 4717 4718 return subObj; 4719 }; 4720 4721 return Component; 4722 })(); 4723 4724 Component.registerComponent('Component', Component); 4725 exports['default'] = Component; 4726 module.exports = exports['default']; 4727 4728 },{"./utils/dom.js":134,"./utils/events.js":135,"./utils/fn.js":136,"./utils/guid.js":138,"./utils/log.js":139,"./utils/merge-options.js":140,"./utils/to-title-case.js":143,"global/window":2,"object.assign":45}],68:[function(_dereq_,module,exports){ 4729 /** 4730 * @file control-bar.js 4731 */ 4732 'use strict'; 4733 4734 exports.__esModule = true; 4735 4736 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 4737 4738 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 4739 4740 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; } 4741 4742 var _componentJs = _dereq_('../component.js'); 4743 4744 var _componentJs2 = _interopRequireDefault(_componentJs); 4745 4746 // Required children 4747 4748 var _playToggleJs = _dereq_('./play-toggle.js'); 4749 4750 var _playToggleJs2 = _interopRequireDefault(_playToggleJs); 4751 4752 var _timeControlsCurrentTimeDisplayJs = _dereq_('./time-controls/current-time-display.js'); 4753 4754 var _timeControlsCurrentTimeDisplayJs2 = _interopRequireDefault(_timeControlsCurrentTimeDisplayJs); 4755 4756 var _timeControlsDurationDisplayJs = _dereq_('./time-controls/duration-display.js'); 4757 4758 var _timeControlsDurationDisplayJs2 = _interopRequireDefault(_timeControlsDurationDisplayJs); 4759 4760 var _timeControlsTimeDividerJs = _dereq_('./time-controls/time-divider.js'); 4761 4762 var _timeControlsTimeDividerJs2 = _interopRequireDefault(_timeControlsTimeDividerJs); 4763 4764 var _timeControlsRemainingTimeDisplayJs = _dereq_('./time-controls/remaining-time-display.js'); 4765 4766 var _timeControlsRemainingTimeDisplayJs2 = _interopRequireDefault(_timeControlsRemainingTimeDisplayJs); 4767 4768 var _liveDisplayJs = _dereq_('./live-display.js'); 4769 4770 var _liveDisplayJs2 = _interopRequireDefault(_liveDisplayJs); 4771 4772 var _progressControlProgressControlJs = _dereq_('./progress-control/progress-control.js'); 4773 4774 var _progressControlProgressControlJs2 = _interopRequireDefault(_progressControlProgressControlJs); 4775 4776 var _fullscreenToggleJs = _dereq_('./fullscreen-toggle.js'); 4777 4778 var _fullscreenToggleJs2 = _interopRequireDefault(_fullscreenToggleJs); 4779 4780 var _volumeControlVolumeControlJs = _dereq_('./volume-control/volume-control.js'); 4781 4782 var _volumeControlVolumeControlJs2 = _interopRequireDefault(_volumeControlVolumeControlJs); 4783 4784 var _volumeMenuButtonJs = _dereq_('./volume-menu-button.js'); 4785 4786 var _volumeMenuButtonJs2 = _interopRequireDefault(_volumeMenuButtonJs); 4787 4788 var _muteToggleJs = _dereq_('./mute-toggle.js'); 4789 4790 var _muteToggleJs2 = _interopRequireDefault(_muteToggleJs); 4791 4792 var _textTrackControlsChaptersButtonJs = _dereq_('./text-track-controls/chapters-button.js'); 4793 4794 var _textTrackControlsChaptersButtonJs2 = _interopRequireDefault(_textTrackControlsChaptersButtonJs); 4795 4796 var _textTrackControlsDescriptionsButtonJs = _dereq_('./text-track-controls/descriptions-button.js'); 4797 4798 var _textTrackControlsDescriptionsButtonJs2 = _interopRequireDefault(_textTrackControlsDescriptionsButtonJs); 4799 4800 var _textTrackControlsSubtitlesButtonJs = _dereq_('./text-track-controls/subtitles-button.js'); 4801 4802 var _textTrackControlsSubtitlesButtonJs2 = _interopRequireDefault(_textTrackControlsSubtitlesButtonJs); 4803 4804 var _textTrackControlsCaptionsButtonJs = _dereq_('./text-track-controls/captions-button.js'); 4805 4806 var _textTrackControlsCaptionsButtonJs2 = _interopRequireDefault(_textTrackControlsCaptionsButtonJs); 4807 4808 var _playbackRateMenuPlaybackRateMenuButtonJs = _dereq_('./playback-rate-menu/playback-rate-menu-button.js'); 4809 4810 var _playbackRateMenuPlaybackRateMenuButtonJs2 = _interopRequireDefault(_playbackRateMenuPlaybackRateMenuButtonJs); 4811 4812 var _spacerControlsCustomControlSpacerJs = _dereq_('./spacer-controls/custom-control-spacer.js'); 4813 4814 var _spacerControlsCustomControlSpacerJs2 = _interopRequireDefault(_spacerControlsCustomControlSpacerJs); 4815 4816 /** 4817 * Container of main controls 4818 * 4819 * @extends Component 4820 * @class ControlBar 4821 */ 4822 4823 var ControlBar = (function (_Component) { 4824 _inherits(ControlBar, _Component); 4825 4826 function ControlBar() { 4827 _classCallCheck(this, ControlBar); 4828 4829 _Component.apply(this, arguments); 4830 } 4831 4832 /** 4833 * Create the component's DOM element 4834 * 4835 * @return {Element} 4836 * @method createEl 4837 */ 4838 4839 ControlBar.prototype.createEl = function createEl() { 4840 return _Component.prototype.createEl.call(this, 'div', { 4841 className: 'vjs-control-bar', 4842 dir: 'ltr' 4843 }, { 4844 'role': 'group' // The control bar is a group, so it can contain menuitems 4845 }); 4846 }; 4847 4848 return ControlBar; 4849 })(_componentJs2['default']); 4850 4851 ControlBar.prototype.options_ = { 4852 loadEvent: 'play', 4853 children: ['playToggle', 'volumeMenuButton', 'currentTimeDisplay', 'timeDivider', 'durationDisplay', 'progressControl', 'liveDisplay', 'remainingTimeDisplay', 'customControlSpacer', 'playbackRateMenuButton', 'chaptersButton', 'descriptionsButton', 'subtitlesButton', 'captionsButton', 'fullscreenToggle'] 4854 }; 4855 4856 _componentJs2['default'].registerComponent('ControlBar', ControlBar); 4857 exports['default'] = ControlBar; 4858 module.exports = exports['default']; 4859 4860 },{"../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":81,"./text-track-controls/captions-button.js":84,"./text-track-controls/chapters-button.js":85,"./text-track-controls/descriptions-button.js":87,"./text-track-controls/subtitles-button.js":89,"./time-controls/current-time-display.js":92,"./time-controls/duration-display.js":93,"./time-controls/remaining-time-display.js":94,"./time-controls/time-divider.js":95,"./volume-control/volume-control.js":97,"./volume-menu-button.js":99}],69:[function(_dereq_,module,exports){ 4861 /** 4862 * @file fullscreen-toggle.js 4863 */ 4864 'use strict'; 4865 4866 exports.__esModule = true; 4867 4868 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 4869 4870 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 4871 4872 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; } 4873 4874 var _buttonJs = _dereq_('../button.js'); 4875 4876 var _buttonJs2 = _interopRequireDefault(_buttonJs); 4877 4878 var _componentJs = _dereq_('../component.js'); 4879 4880 var _componentJs2 = _interopRequireDefault(_componentJs); 4881 4882 /** 4883 * Toggle fullscreen video 4884 * 4885 * @extends Button 4886 * @class FullscreenToggle 4887 */ 4888 4889 var FullscreenToggle = (function (_Button) { 4890 _inherits(FullscreenToggle, _Button); 4891 4892 function FullscreenToggle() { 4893 _classCallCheck(this, FullscreenToggle); 4894 4895 _Button.apply(this, arguments); 4896 } 4897 4898 /** 4899 * Allow sub components to stack CSS class names 4900 * 4901 * @return {String} The constructed class name 4902 * @method buildCSSClass 4903 */ 4904 4905 FullscreenToggle.prototype.buildCSSClass = function buildCSSClass() { 4906 return 'vjs-fullscreen-control ' + _Button.prototype.buildCSSClass.call(this); 4907 }; 4908 4909 /** 4910 * Handles click for full screen 4911 * 4912 * @method handleClick 4913 */ 4914 4915 FullscreenToggle.prototype.handleClick = function handleClick() { 4916 if (!this.player_.isFullscreen()) { 4917 this.player_.requestFullscreen(); 4918 this.controlText('Non-Fullscreen'); 4919 } else { 4920 this.player_.exitFullscreen(); 4921 this.controlText('Fullscreen'); 4922 } 4923 }; 4924 4925 return FullscreenToggle; 4926 })(_buttonJs2['default']); 4927 4928 FullscreenToggle.prototype.controlText_ = 'Fullscreen'; 4929 4930 _componentJs2['default'].registerComponent('FullscreenToggle', FullscreenToggle); 4931 exports['default'] = FullscreenToggle; 4932 module.exports = exports['default']; 4933 4934 },{"../button.js":64,"../component.js":67}],70:[function(_dereq_,module,exports){ 4935 /** 4936 * @file live-display.js 4937 */ 4938 'use strict'; 4939 4940 exports.__esModule = true; 4941 4942 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; } } 4943 4944 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 4945 4946 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 4947 4948 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; } 4949 4950 var _component = _dereq_('../component'); 4951 4952 var _component2 = _interopRequireDefault(_component); 4953 4954 var _utilsDomJs = _dereq_('../utils/dom.js'); 4955 4956 var Dom = _interopRequireWildcard(_utilsDomJs); 4957 4958 /** 4959 * Displays the live indicator 4960 * TODO - Future make it click to snap to live 4961 * 4962 * @extends Component 4963 * @class LiveDisplay 4964 */ 4965 4966 var LiveDisplay = (function (_Component) { 4967 _inherits(LiveDisplay, _Component); 4968 4969 function LiveDisplay(player, options) { 4970 _classCallCheck(this, LiveDisplay); 4971 4972 _Component.call(this, player, options); 4973 4974 this.updateShowing(); 4975 this.on(this.player(), 'durationchange', this.updateShowing); 4976 } 4977 4978 /** 4979 * Create the component's DOM element 4980 * 4981 * @return {Element} 4982 * @method createEl 4983 */ 4984 4985 LiveDisplay.prototype.createEl = function createEl() { 4986 var el = _Component.prototype.createEl.call(this, 'div', { 4987 className: 'vjs-live-control vjs-control' 4988 }); 4989 4990 this.contentEl_ = Dom.createEl('div', { 4991 className: 'vjs-live-display', 4992 innerHTML: '<span class="vjs-control-text">' + this.localize('Stream Type') + '</span>' + this.localize('LIVE') 4993 }, { 4994 'aria-live': 'off' 4995 }); 4996 4997 el.appendChild(this.contentEl_); 4998 return el; 4999 }; 5000 5001 LiveDisplay.prototype.updateShowing = function updateShowing() { 5002 if (this.player().duration() === Infinity) { 5003 this.show(); 5004 } else { 5005 this.hide(); 5006 } 5007 }; 5008 5009 return LiveDisplay; 5010 })(_component2['default']); 5011 5012 _component2['default'].registerComponent('LiveDisplay', LiveDisplay); 5013 exports['default'] = LiveDisplay; 5014 module.exports = exports['default']; 5015 5016 },{"../component":67,"../utils/dom.js":134}],71:[function(_dereq_,module,exports){ 5017 /** 5018 * @file mute-toggle.js 5019 */ 5020 'use strict'; 5021 5022 exports.__esModule = true; 5023 5024 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; } } 5025 5026 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5027 5028 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5029 5030 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; } 5031 5032 var _button = _dereq_('../button'); 5033 5034 var _button2 = _interopRequireDefault(_button); 5035 5036 var _component = _dereq_('../component'); 5037 5038 var _component2 = _interopRequireDefault(_component); 5039 5040 var _utilsDomJs = _dereq_('../utils/dom.js'); 5041 5042 var Dom = _interopRequireWildcard(_utilsDomJs); 5043 5044 /** 5045 * A button component for muting the audio 5046 * 5047 * @param {Player|Object} player 5048 * @param {Object=} options 5049 * @extends Button 5050 * @class MuteToggle 5051 */ 5052 5053 var MuteToggle = (function (_Button) { 5054 _inherits(MuteToggle, _Button); 5055 5056 function MuteToggle(player, options) { 5057 _classCallCheck(this, MuteToggle); 5058 5059 _Button.call(this, player, options); 5060 5061 this.on(player, 'volumechange', this.update); 5062 5063 // hide mute toggle if the current tech doesn't support volume control 5064 if (player.tech_ && player.tech_['featuresVolumeControl'] === false) { 5065 this.addClass('vjs-hidden'); 5066 } 5067 5068 this.on(player, 'loadstart', function () { 5069 this.update(); // We need to update the button to account for a default muted state. 5070 5071 if (player.tech_['featuresVolumeControl'] === false) { 5072 this.addClass('vjs-hidden'); 5073 } else { 5074 this.removeClass('vjs-hidden'); 5075 } 5076 }); 5077 } 5078 5079 /** 5080 * Allow sub components to stack CSS class names 5081 * 5082 * @return {String} The constructed class name 5083 * @method buildCSSClass 5084 */ 5085 5086 MuteToggle.prototype.buildCSSClass = function buildCSSClass() { 5087 return 'vjs-mute-control ' + _Button.prototype.buildCSSClass.call(this); 5088 }; 5089 5090 /** 5091 * Handle click on mute 5092 * 5093 * @method handleClick 5094 */ 5095 5096 MuteToggle.prototype.handleClick = function handleClick() { 5097 this.player_.muted(this.player_.muted() ? false : true); 5098 }; 5099 5100 /** 5101 * Update volume 5102 * 5103 * @method update 5104 */ 5105 5106 MuteToggle.prototype.update = function update() { 5107 var vol = this.player_.volume(), 5108 level = 3; 5109 5110 if (vol === 0 || this.player_.muted()) { 5111 level = 0; 5112 } else if (vol < 0.33) { 5113 level = 1; 5114 } else if (vol < 0.67) { 5115 level = 2; 5116 } 5117 5118 // Don't rewrite the button text if the actual text doesn't change. 5119 // This causes unnecessary and confusing information for screen reader users. 5120 // This check is needed because this function gets called every time the volume level is changed. 5121 var toMute = this.player_.muted() ? 'Unmute' : 'Mute'; 5122 if (this.controlText() !== toMute) { 5123 this.controlText(toMute); 5124 } 5125 5126 /* TODO improve muted icon classes */ 5127 for (var i = 0; i < 4; i++) { 5128 Dom.removeElClass(this.el_, 'vjs-vol-' + i); 5129 } 5130 Dom.addElClass(this.el_, 'vjs-vol-' + level); 5131 }; 5132 5133 return MuteToggle; 5134 })(_button2['default']); 5135 5136 MuteToggle.prototype.controlText_ = 'Mute'; 5137 5138 _component2['default'].registerComponent('MuteToggle', MuteToggle); 5139 exports['default'] = MuteToggle; 5140 module.exports = exports['default']; 5141 5142 },{"../button":64,"../component":67,"../utils/dom.js":134}],72:[function(_dereq_,module,exports){ 5143 /** 5144 * @file play-toggle.js 5145 */ 5146 'use strict'; 5147 5148 exports.__esModule = true; 5149 5150 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5151 5152 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5153 5154 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; } 5155 5156 var _buttonJs = _dereq_('../button.js'); 5157 5158 var _buttonJs2 = _interopRequireDefault(_buttonJs); 5159 5160 var _componentJs = _dereq_('../component.js'); 5161 5162 var _componentJs2 = _interopRequireDefault(_componentJs); 5163 5164 /** 5165 * Button to toggle between play and pause 5166 * 5167 * @param {Player|Object} player 5168 * @param {Object=} options 5169 * @extends Button 5170 * @class PlayToggle 5171 */ 5172 5173 var PlayToggle = (function (_Button) { 5174 _inherits(PlayToggle, _Button); 5175 5176 function PlayToggle(player, options) { 5177 _classCallCheck(this, PlayToggle); 5178 5179 _Button.call(this, player, options); 5180 5181 this.on(player, 'play', this.handlePlay); 5182 this.on(player, 'pause', this.handlePause); 5183 } 5184 5185 /** 5186 * Allow sub components to stack CSS class names 5187 * 5188 * @return {String} The constructed class name 5189 * @method buildCSSClass 5190 */ 5191 5192 PlayToggle.prototype.buildCSSClass = function buildCSSClass() { 5193 return 'vjs-play-control ' + _Button.prototype.buildCSSClass.call(this); 5194 }; 5195 5196 /** 5197 * Handle click to toggle between play and pause 5198 * 5199 * @method handleClick 5200 */ 5201 5202 PlayToggle.prototype.handleClick = function handleClick() { 5203 if (this.player_.paused()) { 5204 this.player_.play(); 5205 } else { 5206 this.player_.pause(); 5207 } 5208 }; 5209 5210 /** 5211 * Add the vjs-playing class to the element so it can change appearance 5212 * 5213 * @method handlePlay 5214 */ 5215 5216 PlayToggle.prototype.handlePlay = function handlePlay() { 5217 this.removeClass('vjs-paused'); 5218 this.addClass('vjs-playing'); 5219 this.controlText('Pause'); // change the button text to "Pause" 5220 }; 5221 5222 /** 5223 * Add the vjs-paused class to the element so it can change appearance 5224 * 5225 * @method handlePause 5226 */ 5227 5228 PlayToggle.prototype.handlePause = function handlePause() { 5229 this.removeClass('vjs-playing'); 5230 this.addClass('vjs-paused'); 5231 this.controlText('Play'); // change the button text to "Play" 5232 }; 5233 5234 return PlayToggle; 5235 })(_buttonJs2['default']); 5236 5237 PlayToggle.prototype.controlText_ = 'Play'; 5238 5239 _componentJs2['default'].registerComponent('PlayToggle', PlayToggle); 5240 exports['default'] = PlayToggle; 5241 module.exports = exports['default']; 5242 5243 },{"../button.js":64,"../component.js":67}],73:[function(_dereq_,module,exports){ 5244 /** 5245 * @file playback-rate-menu-button.js 5246 */ 5247 'use strict'; 5248 5249 exports.__esModule = true; 5250 5251 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; } } 5252 5253 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5254 5255 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5256 5257 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; } 5258 5259 var _menuMenuButtonJs = _dereq_('../../menu/menu-button.js'); 5260 5261 var _menuMenuButtonJs2 = _interopRequireDefault(_menuMenuButtonJs); 5262 5263 var _menuMenuJs = _dereq_('../../menu/menu.js'); 5264 5265 var _menuMenuJs2 = _interopRequireDefault(_menuMenuJs); 5266 5267 var _playbackRateMenuItemJs = _dereq_('./playback-rate-menu-item.js'); 5268 5269 var _playbackRateMenuItemJs2 = _interopRequireDefault(_playbackRateMenuItemJs); 5270 5271 var _componentJs = _dereq_('../../component.js'); 5272 5273 var _componentJs2 = _interopRequireDefault(_componentJs); 5274 5275 var _utilsDomJs = _dereq_('../../utils/dom.js'); 5276 5277 var Dom = _interopRequireWildcard(_utilsDomJs); 5278 5279 /** 5280 * The component for controlling the playback rate 5281 * 5282 * @param {Player|Object} player 5283 * @param {Object=} options 5284 * @extends MenuButton 5285 * @class PlaybackRateMenuButton 5286 */ 5287 5288 var PlaybackRateMenuButton = (function (_MenuButton) { 5289 _inherits(PlaybackRateMenuButton, _MenuButton); 5290 5291 function PlaybackRateMenuButton(player, options) { 5292 _classCallCheck(this, PlaybackRateMenuButton); 5293 5294 _MenuButton.call(this, player, options); 5295 5296 this.updateVisibility(); 5297 this.updateLabel(); 5298 5299 this.on(player, 'loadstart', this.updateVisibility); 5300 this.on(player, 'ratechange', this.updateLabel); 5301 } 5302 5303 /** 5304 * Create the component's DOM element 5305 * 5306 * @return {Element} 5307 * @method createEl 5308 */ 5309 5310 PlaybackRateMenuButton.prototype.createEl = function createEl() { 5311 var el = _MenuButton.prototype.createEl.call(this); 5312 5313 this.labelEl_ = Dom.createEl('div', { 5314 className: 'vjs-playback-rate-value', 5315 innerHTML: 1.0 5316 }); 5317 5318 el.appendChild(this.labelEl_); 5319 5320 return el; 5321 }; 5322 5323 /** 5324 * Allow sub components to stack CSS class names 5325 * 5326 * @return {String} The constructed class name 5327 * @method buildCSSClass 5328 */ 5329 5330 PlaybackRateMenuButton.prototype.buildCSSClass = function buildCSSClass() { 5331 return 'vjs-playback-rate ' + _MenuButton.prototype.buildCSSClass.call(this); 5332 }; 5333 5334 /** 5335 * Create the playback rate menu 5336 * 5337 * @return {Menu} Menu object populated with items 5338 * @method createMenu 5339 */ 5340 5341 PlaybackRateMenuButton.prototype.createMenu = function createMenu() { 5342 var menu = new _menuMenuJs2['default'](this.player()); 5343 var rates = this.playbackRates(); 5344 5345 if (rates) { 5346 for (var i = rates.length - 1; i >= 0; i--) { 5347 menu.addChild(new _playbackRateMenuItemJs2['default'](this.player(), { 'rate': rates[i] + 'x' })); 5348 } 5349 } 5350 5351 return menu; 5352 }; 5353 5354 /** 5355 * Updates ARIA accessibility attributes 5356 * 5357 * @method updateARIAAttributes 5358 */ 5359 5360 PlaybackRateMenuButton.prototype.updateARIAAttributes = function updateARIAAttributes() { 5361 // Current playback rate 5362 this.el().setAttribute('aria-valuenow', this.player().playbackRate()); 5363 }; 5364 5365 /** 5366 * Handle menu item click 5367 * 5368 * @method handleClick 5369 */ 5370 5371 PlaybackRateMenuButton.prototype.handleClick = function handleClick() { 5372 // select next rate option 5373 var currentRate = this.player().playbackRate(); 5374 var rates = this.playbackRates(); 5375 5376 // this will select first one if the last one currently selected 5377 var newRate = rates[0]; 5378 for (var i = 0; i < rates.length; i++) { 5379 if (rates[i] > currentRate) { 5380 newRate = rates[i]; 5381 break; 5382 } 5383 } 5384 this.player().playbackRate(newRate); 5385 }; 5386 5387 /** 5388 * Get possible playback rates 5389 * 5390 * @return {Array} Possible playback rates 5391 * @method playbackRates 5392 */ 5393 5394 PlaybackRateMenuButton.prototype.playbackRates = function playbackRates() { 5395 return this.options_['playbackRates'] || this.options_.playerOptions && this.options_.playerOptions['playbackRates']; 5396 }; 5397 5398 /** 5399 * Get supported playback rates 5400 * 5401 * @return {Array} Supported playback rates 5402 * @method playbackRateSupported 5403 */ 5404 5405 PlaybackRateMenuButton.prototype.playbackRateSupported = function playbackRateSupported() { 5406 return this.player().tech_ && this.player().tech_['featuresPlaybackRate'] && this.playbackRates() && this.playbackRates().length > 0; 5407 }; 5408 5409 /** 5410 * Hide playback rate controls when they're no playback rate options to select 5411 * 5412 * @method updateVisibility 5413 */ 5414 5415 PlaybackRateMenuButton.prototype.updateVisibility = function updateVisibility() { 5416 if (this.playbackRateSupported()) { 5417 this.removeClass('vjs-hidden'); 5418 } else { 5419 this.addClass('vjs-hidden'); 5420 } 5421 }; 5422 5423 /** 5424 * Update button label when rate changed 5425 * 5426 * @method updateLabel 5427 */ 5428 5429 PlaybackRateMenuButton.prototype.updateLabel = function updateLabel() { 5430 if (this.playbackRateSupported()) { 5431 this.labelEl_.innerHTML = this.player().playbackRate() + 'x'; 5432 } 5433 }; 5434 5435 return PlaybackRateMenuButton; 5436 })(_menuMenuButtonJs2['default']); 5437 5438 PlaybackRateMenuButton.prototype.controlText_ = 'Playback Rate'; 5439 5440 _componentJs2['default'].registerComponent('PlaybackRateMenuButton', PlaybackRateMenuButton); 5441 exports['default'] = PlaybackRateMenuButton; 5442 module.exports = exports['default']; 5443 5444 },{"../../component.js":67,"../../menu/menu-button.js":106,"../../menu/menu.js":108,"../../utils/dom.js":134,"./playback-rate-menu-item.js":74}],74:[function(_dereq_,module,exports){ 5445 /** 5446 * @file playback-rate-menu-item.js 5447 */ 5448 'use strict'; 5449 5450 exports.__esModule = true; 5451 5452 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5453 5454 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5455 5456 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; } 5457 5458 var _menuMenuItemJs = _dereq_('../../menu/menu-item.js'); 5459 5460 var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs); 5461 5462 var _componentJs = _dereq_('../../component.js'); 5463 5464 var _componentJs2 = _interopRequireDefault(_componentJs); 5465 5466 /** 5467 * The specific menu item type for selecting a playback rate 5468 * 5469 * @param {Player|Object} player 5470 * @param {Object=} options 5471 * @extends MenuItem 5472 * @class PlaybackRateMenuItem 5473 */ 5474 5475 var PlaybackRateMenuItem = (function (_MenuItem) { 5476 _inherits(PlaybackRateMenuItem, _MenuItem); 5477 5478 function PlaybackRateMenuItem(player, options) { 5479 _classCallCheck(this, PlaybackRateMenuItem); 5480 5481 var label = options['rate']; 5482 var rate = parseFloat(label, 10); 5483 5484 // Modify options for parent MenuItem class's init. 5485 options['label'] = label; 5486 options['selected'] = rate === 1; 5487 _MenuItem.call(this, player, options); 5488 5489 this.label = label; 5490 this.rate = rate; 5491 5492 this.on(player, 'ratechange', this.update); 5493 } 5494 5495 /** 5496 * Handle click on menu item 5497 * 5498 * @method handleClick 5499 */ 5500 5501 PlaybackRateMenuItem.prototype.handleClick = function handleClick() { 5502 _MenuItem.prototype.handleClick.call(this); 5503 this.player().playbackRate(this.rate); 5504 }; 5505 5506 /** 5507 * Update playback rate with selected rate 5508 * 5509 * @method update 5510 */ 5511 5512 PlaybackRateMenuItem.prototype.update = function update() { 5513 this.selected(this.player().playbackRate() === this.rate); 5514 }; 5515 5516 return PlaybackRateMenuItem; 5517 })(_menuMenuItemJs2['default']); 5518 5519 PlaybackRateMenuItem.prototype.contentElType = 'button'; 5520 5521 _componentJs2['default'].registerComponent('PlaybackRateMenuItem', PlaybackRateMenuItem); 5522 exports['default'] = PlaybackRateMenuItem; 5523 module.exports = exports['default']; 5524 5525 },{"../../component.js":67,"../../menu/menu-item.js":107}],75:[function(_dereq_,module,exports){ 5526 /** 5527 * @file load-progress-bar.js 5528 */ 5529 'use strict'; 5530 5531 exports.__esModule = true; 5532 5533 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; } } 5534 5535 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5536 5537 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5538 5539 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; } 5540 5541 var _componentJs = _dereq_('../../component.js'); 5542 5543 var _componentJs2 = _interopRequireDefault(_componentJs); 5544 5545 var _utilsDomJs = _dereq_('../../utils/dom.js'); 5546 5547 var Dom = _interopRequireWildcard(_utilsDomJs); 5548 5549 /** 5550 * Shows load progress 5551 * 5552 * @param {Player|Object} player 5553 * @param {Object=} options 5554 * @extends Component 5555 * @class LoadProgressBar 5556 */ 5557 5558 var LoadProgressBar = (function (_Component) { 5559 _inherits(LoadProgressBar, _Component); 5560 5561 function LoadProgressBar(player, options) { 5562 _classCallCheck(this, LoadProgressBar); 5563 5564 _Component.call(this, player, options); 5565 this.on(player, 'progress', this.update); 5566 } 5567 5568 /** 5569 * Create the component's DOM element 5570 * 5571 * @return {Element} 5572 * @method createEl 5573 */ 5574 5575 LoadProgressBar.prototype.createEl = function createEl() { 5576 return _Component.prototype.createEl.call(this, 'div', { 5577 className: 'vjs-load-progress', 5578 innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Loaded') + '</span>: 0%</span>' 5579 }); 5580 }; 5581 5582 /** 5583 * Update progress bar 5584 * 5585 * @method update 5586 */ 5587 5588 LoadProgressBar.prototype.update = function update() { 5589 var buffered = this.player_.buffered(); 5590 var duration = this.player_.duration(); 5591 var bufferedEnd = this.player_.bufferedEnd(); 5592 var children = this.el_.children; 5593 5594 // get the percent width of a time compared to the total end 5595 var percentify = function percentify(time, end) { 5596 var percent = time / end || 0; // no NaN 5597 return (percent >= 1 ? 1 : percent) * 100 + '%'; 5598 }; 5599 5600 // update the width of the progress bar 5601 this.el_.style.width = percentify(bufferedEnd, duration); 5602 5603 // add child elements to represent the individual buffered time ranges 5604 for (var i = 0; i < buffered.length; i++) { 5605 var start = buffered.start(i); 5606 var end = buffered.end(i); 5607 var part = children[i]; 5608 5609 if (!part) { 5610 part = this.el_.appendChild(Dom.createEl()); 5611 } 5612 5613 // set the percent based on the width of the progress bar (bufferedEnd) 5614 part.style.left = percentify(start, bufferedEnd); 5615 part.style.width = percentify(end - start, bufferedEnd); 5616 } 5617 5618 // remove unused buffered range elements 5619 for (var i = children.length; i > buffered.length; i--) { 5620 this.el_.removeChild(children[i - 1]); 5621 } 5622 }; 5623 5624 return LoadProgressBar; 5625 })(_componentJs2['default']); 5626 5627 _componentJs2['default'].registerComponent('LoadProgressBar', LoadProgressBar); 5628 exports['default'] = LoadProgressBar; 5629 module.exports = exports['default']; 5630 5631 },{"../../component.js":67,"../../utils/dom.js":134}],76:[function(_dereq_,module,exports){ 5632 /** 5633 * @file mouse-time-display.js 5634 */ 5635 'use strict'; 5636 5637 exports.__esModule = true; 5638 5639 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; } } 5640 5641 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5642 5643 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5644 5645 function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 5646 5647 var _globalWindow = _dereq_('global/window'); 5648 5649 var _globalWindow2 = _interopRequireDefault(_globalWindow); 5650 5651 var _componentJs = _dereq_('../../component.js'); 5652 5653 var _componentJs2 = _interopRequireDefault(_componentJs); 5654 5655 var _utilsDomJs = _dereq_('../../utils/dom.js'); 5656 5657 var Dom = _interopRequireWildcard(_utilsDomJs); 5658 5659 var _utilsFnJs = _dereq_('../../utils/fn.js'); 5660 5661 var Fn = _interopRequireWildcard(_utilsFnJs); 5662 5663 var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js'); 5664 5665 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 5666 5667 var _lodashCompatFunctionThrottle = _dereq_('lodash-compat/function/throttle'); 5668 5669 var _lodashCompatFunctionThrottle2 = _interopRequireDefault(_lodashCompatFunctionThrottle); 5670 5671 /** 5672 * The Mouse Time Display component shows the time you will seek to 5673 * when hovering over the progress bar 5674 * 5675 * @param {Player|Object} player 5676 * @param {Object=} options 5677 * @extends Component 5678 * @class MouseTimeDisplay 5679 */ 5680 5681 var MouseTimeDisplay = (function (_Component) { 5682 _inherits(MouseTimeDisplay, _Component); 5683 5684 function MouseTimeDisplay(player, options) { 5685 var _this = this; 5686 5687 _classCallCheck(this, MouseTimeDisplay); 5688 5689 _Component.call(this, player, options); 5690 5691 if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) { 5692 this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside; 5693 } 5694 5695 if (this.keepTooltipsInside) { 5696 this.tooltip = Dom.createEl('div', { className: 'vjs-time-tooltip' }); 5697 this.el().appendChild(this.tooltip); 5698 this.addClass('vjs-keep-tooltips-inside'); 5699 } 5700 5701 this.update(0, 0); 5702 5703 player.on('ready', function () { 5704 _this.on(player.controlBar.progressControl.el(), 'mousemove', _lodashCompatFunctionThrottle2['default'](Fn.bind(_this, _this.handleMouseMove), 25)); 5705 }); 5706 } 5707 5708 /** 5709 * Create the component's DOM element 5710 * 5711 * @return {Element} 5712 * @method createEl 5713 */ 5714 5715 MouseTimeDisplay.prototype.createEl = function createEl() { 5716 return _Component.prototype.createEl.call(this, 'div', { 5717 className: 'vjs-mouse-display' 5718 }); 5719 }; 5720 5721 MouseTimeDisplay.prototype.handleMouseMove = function handleMouseMove(event) { 5722 var duration = this.player_.duration(); 5723 var newTime = this.calculateDistance(event) * duration; 5724 var position = event.pageX - Dom.findElPosition(this.el().parentNode).left; 5725 5726 this.update(newTime, position); 5727 }; 5728 5729 MouseTimeDisplay.prototype.update = function update(newTime, position) { 5730 var time = _utilsFormatTimeJs2['default'](newTime, this.player_.duration()); 5731 5732 this.el().style.left = position + 'px'; 5733 this.el().setAttribute('data-current-time', time); 5734 5735 if (this.keepTooltipsInside) { 5736 var clampedPosition = this.clampPosition_(position); 5737 var difference = position - clampedPosition + 1; 5738 var tooltipWidth = parseFloat(_globalWindow2['default'].getComputedStyle(this.tooltip).width); 5739 var tooltipWidthHalf = tooltipWidth / 2; 5740 5741 this.tooltip.innerHTML = time; 5742 this.tooltip.style.right = '-' + (tooltipWidthHalf - difference) + 'px'; 5743 } 5744 }; 5745 5746 MouseTimeDisplay.prototype.calculateDistance = function calculateDistance(event) { 5747 return Dom.getPointerPosition(this.el().parentNode, event).x; 5748 }; 5749 5750 /** 5751 * This takes in a horizontal position for the bar and returns a clamped position. 5752 * Clamped position means that it will keep the position greater than half the width 5753 * of the tooltip and smaller than the player width minus half the width o the tooltip. 5754 * It will only clamp the position if `keepTooltipsInside` option is set. 5755 * 5756 * @param {Number} position the position the bar wants to be 5757 * @return {Number} newPosition the (potentially) clamped position 5758 * @method clampPosition_ 5759 */ 5760 5761 MouseTimeDisplay.prototype.clampPosition_ = function clampPosition_(position) { 5762 if (!this.keepTooltipsInside) { 5763 return position; 5764 } 5765 5766 var playerWidth = parseFloat(_globalWindow2['default'].getComputedStyle(this.player().el()).width); 5767 var tooltipWidth = parseFloat(_globalWindow2['default'].getComputedStyle(this.tooltip).width); 5768 var tooltipWidthHalf = tooltipWidth / 2; 5769 var actualPosition = position; 5770 5771 if (position < tooltipWidthHalf) { 5772 actualPosition = Math.ceil(tooltipWidthHalf); 5773 } else if (position > playerWidth - tooltipWidthHalf) { 5774 actualPosition = Math.floor(playerWidth - tooltipWidthHalf); 5775 } 5776 5777 return actualPosition; 5778 }; 5779 5780 return MouseTimeDisplay; 5781 })(_componentJs2['default']); 5782 5783 _componentJs2['default'].registerComponent('MouseTimeDisplay', MouseTimeDisplay); 5784 exports['default'] = MouseTimeDisplay; 5785 module.exports = exports['default']; 5786 5787 },{"../../component.js":67,"../../utils/dom.js":134,"../../utils/fn.js":136,"../../utils/format-time.js":137,"global/window":2,"lodash-compat/function/throttle":7}],77:[function(_dereq_,module,exports){ 5788 /** 5789 * @file play-progress-bar.js 5790 */ 5791 'use strict'; 5792 5793 exports.__esModule = true; 5794 5795 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; } } 5796 5797 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5798 5799 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5800 5801 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; } 5802 5803 var _componentJs = _dereq_('../../component.js'); 5804 5805 var _componentJs2 = _interopRequireDefault(_componentJs); 5806 5807 var _utilsFnJs = _dereq_('../../utils/fn.js'); 5808 5809 var Fn = _interopRequireWildcard(_utilsFnJs); 5810 5811 var _utilsDomJs = _dereq_('../../utils/dom.js'); 5812 5813 var Dom = _interopRequireWildcard(_utilsDomJs); 5814 5815 var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js'); 5816 5817 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 5818 5819 /** 5820 * Shows play progress 5821 * 5822 * @param {Player|Object} player 5823 * @param {Object=} options 5824 * @extends Component 5825 * @class PlayProgressBar 5826 */ 5827 5828 var PlayProgressBar = (function (_Component) { 5829 _inherits(PlayProgressBar, _Component); 5830 5831 function PlayProgressBar(player, options) { 5832 _classCallCheck(this, PlayProgressBar); 5833 5834 _Component.call(this, player, options); 5835 this.updateDataAttr(); 5836 this.on(player, 'timeupdate', this.updateDataAttr); 5837 player.ready(Fn.bind(this, this.updateDataAttr)); 5838 5839 if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) { 5840 this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside; 5841 } 5842 5843 if (this.keepTooltipsInside) { 5844 this.addClass('vjs-keep-tooltips-inside'); 5845 } 5846 } 5847 5848 /** 5849 * Create the component's DOM element 5850 * 5851 * @return {Element} 5852 * @method createEl 5853 */ 5854 5855 PlayProgressBar.prototype.createEl = function createEl() { 5856 return _Component.prototype.createEl.call(this, 'div', { 5857 className: 'vjs-play-progress vjs-slider-bar', 5858 innerHTML: '<span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>' 5859 }); 5860 }; 5861 5862 PlayProgressBar.prototype.updateDataAttr = function updateDataAttr() { 5863 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime(); 5864 this.el_.setAttribute('data-current-time', _utilsFormatTimeJs2['default'](time, this.player_.duration())); 5865 }; 5866 5867 return PlayProgressBar; 5868 })(_componentJs2['default']); 5869 5870 _componentJs2['default'].registerComponent('PlayProgressBar', PlayProgressBar); 5871 exports['default'] = PlayProgressBar; 5872 module.exports = exports['default']; 5873 5874 },{"../../component.js":67,"../../utils/dom.js":134,"../../utils/fn.js":136,"../../utils/format-time.js":137}],78:[function(_dereq_,module,exports){ 5875 /** 5876 * @file progress-control.js 5877 */ 5878 'use strict'; 5879 5880 exports.__esModule = true; 5881 5882 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5883 5884 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5885 5886 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; } 5887 5888 var _componentJs = _dereq_('../../component.js'); 5889 5890 var _componentJs2 = _interopRequireDefault(_componentJs); 5891 5892 var _seekBarJs = _dereq_('./seek-bar.js'); 5893 5894 var _seekBarJs2 = _interopRequireDefault(_seekBarJs); 5895 5896 var _mouseTimeDisplayJs = _dereq_('./mouse-time-display.js'); 5897 5898 var _mouseTimeDisplayJs2 = _interopRequireDefault(_mouseTimeDisplayJs); 5899 5900 /** 5901 * The Progress Control component contains the seek bar, load progress, 5902 * and play progress 5903 * 5904 * @param {Player|Object} player 5905 * @param {Object=} options 5906 * @extends Component 5907 * @class ProgressControl 5908 */ 5909 5910 var ProgressControl = (function (_Component) { 5911 _inherits(ProgressControl, _Component); 5912 5913 function ProgressControl() { 5914 _classCallCheck(this, ProgressControl); 5915 5916 _Component.apply(this, arguments); 5917 } 5918 5919 /** 5920 * Create the component's DOM element 5921 * 5922 * @return {Element} 5923 * @method createEl 5924 */ 5925 5926 ProgressControl.prototype.createEl = function createEl() { 5927 return _Component.prototype.createEl.call(this, 'div', { 5928 className: 'vjs-progress-control vjs-control' 5929 }); 5930 }; 5931 5932 return ProgressControl; 5933 })(_componentJs2['default']); 5934 5935 ProgressControl.prototype.options_ = { 5936 children: ['seekBar'] 5937 }; 5938 5939 _componentJs2['default'].registerComponent('ProgressControl', ProgressControl); 5940 exports['default'] = ProgressControl; 5941 module.exports = exports['default']; 5942 5943 },{"../../component.js":67,"./mouse-time-display.js":76,"./seek-bar.js":79}],79:[function(_dereq_,module,exports){ 5944 /** 5945 * @file seek-bar.js 5946 */ 5947 'use strict'; 5948 5949 exports.__esModule = true; 5950 5951 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; } } 5952 5953 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 5954 5955 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 5956 5957 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; } 5958 5959 var _globalWindow = _dereq_('global/window'); 5960 5961 var _globalWindow2 = _interopRequireDefault(_globalWindow); 5962 5963 var _sliderSliderJs = _dereq_('../../slider/slider.js'); 5964 5965 var _sliderSliderJs2 = _interopRequireDefault(_sliderSliderJs); 5966 5967 var _componentJs = _dereq_('../../component.js'); 5968 5969 var _componentJs2 = _interopRequireDefault(_componentJs); 5970 5971 var _loadProgressBarJs = _dereq_('./load-progress-bar.js'); 5972 5973 var _loadProgressBarJs2 = _interopRequireDefault(_loadProgressBarJs); 5974 5975 var _playProgressBarJs = _dereq_('./play-progress-bar.js'); 5976 5977 var _playProgressBarJs2 = _interopRequireDefault(_playProgressBarJs); 5978 5979 var _tooltipProgressBarJs = _dereq_('./tooltip-progress-bar.js'); 5980 5981 var _tooltipProgressBarJs2 = _interopRequireDefault(_tooltipProgressBarJs); 5982 5983 var _utilsFnJs = _dereq_('../../utils/fn.js'); 5984 5985 var Fn = _interopRequireWildcard(_utilsFnJs); 5986 5987 var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js'); 5988 5989 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 5990 5991 var _objectAssign = _dereq_('object.assign'); 5992 5993 var _objectAssign2 = _interopRequireDefault(_objectAssign); 5994 5995 /** 5996 * Seek Bar and holder for the progress bars 5997 * 5998 * @param {Player|Object} player 5999 * @param {Object=} options 6000 * @extends Slider 6001 * @class SeekBar 6002 */ 6003 6004 var SeekBar = (function (_Slider) { 6005 _inherits(SeekBar, _Slider); 6006 6007 function SeekBar(player, options) { 6008 _classCallCheck(this, SeekBar); 6009 6010 _Slider.call(this, player, options); 6011 this.on(player, 'timeupdate', this.updateProgress); 6012 this.on(player, 'ended', this.updateProgress); 6013 player.ready(Fn.bind(this, this.updateProgress)); 6014 6015 if (options.playerOptions && options.playerOptions.controlBar && options.playerOptions.controlBar.progressControl && options.playerOptions.controlBar.progressControl.keepTooltipsInside) { 6016 this.keepTooltipsInside = options.playerOptions.controlBar.progressControl.keepTooltipsInside; 6017 } 6018 6019 if (this.keepTooltipsInside) { 6020 this.tooltipProgressBar = this.addChild('TooltipProgressBar'); 6021 } 6022 } 6023 6024 /** 6025 * Create the component's DOM element 6026 * 6027 * @return {Element} 6028 * @method createEl 6029 */ 6030 6031 SeekBar.prototype.createEl = function createEl() { 6032 return _Slider.prototype.createEl.call(this, 'div', { 6033 className: 'vjs-progress-holder' 6034 }, { 6035 'aria-label': 'progress bar' 6036 }); 6037 }; 6038 6039 /** 6040 * Update ARIA accessibility attributes 6041 * 6042 * @method updateARIAAttributes 6043 */ 6044 6045 SeekBar.prototype.updateProgress = function updateProgress() { 6046 this.updateAriaAttributes(this.el_); 6047 6048 if (this.keepTooltipsInside) { 6049 this.updateAriaAttributes(this.tooltipProgressBar.el_); 6050 this.tooltipProgressBar.el_.style.width = this.bar.el_.style.width; 6051 6052 var playerWidth = parseFloat(_globalWindow2['default'].getComputedStyle(this.player().el()).width); 6053 var tooltipWidth = parseFloat(_globalWindow2['default'].getComputedStyle(this.tooltipProgressBar.tooltip).width); 6054 var tooltipStyle = this.tooltipProgressBar.el().style; 6055 tooltipStyle.maxWidth = Math.floor(playerWidth - tooltipWidth / 2) + 'px'; 6056 tooltipStyle.minWidth = Math.ceil(tooltipWidth / 2) + 'px'; 6057 tooltipStyle.right = '-' + tooltipWidth / 2 + 'px'; 6058 } 6059 }; 6060 6061 SeekBar.prototype.updateAriaAttributes = function updateAriaAttributes(el) { 6062 // Allows for smooth scrubbing, when player can't keep up. 6063 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime(); 6064 el.setAttribute('aria-valuenow', (this.getPercent() * 100).toFixed(2)); // machine readable value of progress bar (percentage complete) 6065 el.setAttribute('aria-valuetext', _utilsFormatTimeJs2['default'](time, this.player_.duration())); // human readable value of progress bar (time complete) 6066 }; 6067 6068 /** 6069 * Get percentage of video played 6070 * 6071 * @return {Number} Percentage played 6072 * @method getPercent 6073 */ 6074 6075 SeekBar.prototype.getPercent = function getPercent() { 6076 var percent = this.player_.currentTime() / this.player_.duration(); 6077 return percent >= 1 ? 1 : percent; 6078 }; 6079 6080 /** 6081 * Handle mouse down on seek bar 6082 * 6083 * @method handleMouseDown 6084 */ 6085 6086 SeekBar.prototype.handleMouseDown = function handleMouseDown(event) { 6087 _Slider.prototype.handleMouseDown.call(this, event); 6088 6089 this.player_.scrubbing(true); 6090 6091 this.videoWasPlaying = !this.player_.paused(); 6092 this.player_.pause(); 6093 }; 6094 6095 /** 6096 * Handle mouse move on seek bar 6097 * 6098 * @method handleMouseMove 6099 */ 6100 6101 SeekBar.prototype.handleMouseMove = function handleMouseMove(event) { 6102 var newTime = this.calculateDistance(event) * this.player_.duration(); 6103 6104 // Don't let video end while scrubbing. 6105 if (newTime === this.player_.duration()) { 6106 newTime = newTime - 0.1; 6107 } 6108 6109 // Set new time (tell player to seek to new time) 6110 this.player_.currentTime(newTime); 6111 }; 6112 6113 /** 6114 * Handle mouse up on seek bar 6115 * 6116 * @method handleMouseUp 6117 */ 6118 6119 SeekBar.prototype.handleMouseUp = function handleMouseUp(event) { 6120 _Slider.prototype.handleMouseUp.call(this, event); 6121 6122 this.player_.scrubbing(false); 6123 if (this.videoWasPlaying) { 6124 this.player_.play(); 6125 } 6126 }; 6127 6128 /** 6129 * Move more quickly fast forward for keyboard-only users 6130 * 6131 * @method stepForward 6132 */ 6133 6134 SeekBar.prototype.stepForward = function stepForward() { 6135 this.player_.currentTime(this.player_.currentTime() + 5); // more quickly fast forward for keyboard-only users 6136 }; 6137 6138 /** 6139 * Move more quickly rewind for keyboard-only users 6140 * 6141 * @method stepBack 6142 */ 6143 6144 SeekBar.prototype.stepBack = function stepBack() { 6145 this.player_.currentTime(this.player_.currentTime() - 5); // more quickly rewind for keyboard-only users 6146 }; 6147 6148 return SeekBar; 6149 })(_sliderSliderJs2['default']); 6150 6151 SeekBar.prototype.options_ = { 6152 children: ['loadProgressBar', 'mouseTimeDisplay', 'playProgressBar'], 6153 'barName': 'playProgressBar' 6154 }; 6155 6156 SeekBar.prototype.playerEvent = 'timeupdate'; 6157 6158 _componentJs2['default'].registerComponent('SeekBar', SeekBar); 6159 exports['default'] = SeekBar; 6160 module.exports = exports['default']; 6161 6162 },{"../../component.js":67,"../../slider/slider.js":116,"../../utils/fn.js":136,"../../utils/format-time.js":137,"./load-progress-bar.js":75,"./play-progress-bar.js":77,"./tooltip-progress-bar.js":80,"global/window":2,"object.assign":45}],80:[function(_dereq_,module,exports){ 6163 /** 6164 * @file play-progress-bar.js 6165 */ 6166 'use strict'; 6167 6168 exports.__esModule = true; 6169 6170 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; } } 6171 6172 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6173 6174 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6175 6176 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; } 6177 6178 var _componentJs = _dereq_('../../component.js'); 6179 6180 var _componentJs2 = _interopRequireDefault(_componentJs); 6181 6182 var _utilsFnJs = _dereq_('../../utils/fn.js'); 6183 6184 var Fn = _interopRequireWildcard(_utilsFnJs); 6185 6186 var _utilsDomJs = _dereq_('../../utils/dom.js'); 6187 6188 var Dom = _interopRequireWildcard(_utilsDomJs); 6189 6190 var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js'); 6191 6192 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 6193 6194 /** 6195 * Shows play progress 6196 * 6197 * @param {Player|Object} player 6198 * @param {Object=} options 6199 * @extends Component 6200 * @class PlayProgressBar 6201 */ 6202 6203 var TooltipProgressBar = (function (_Component) { 6204 _inherits(TooltipProgressBar, _Component); 6205 6206 function TooltipProgressBar(player, options) { 6207 _classCallCheck(this, TooltipProgressBar); 6208 6209 _Component.call(this, player, options); 6210 this.updateDataAttr(); 6211 this.on(player, 'timeupdate', this.updateDataAttr); 6212 player.ready(Fn.bind(this, this.updateDataAttr)); 6213 } 6214 6215 /** 6216 * Create the component's DOM element 6217 * 6218 * @return {Element} 6219 * @method createEl 6220 */ 6221 6222 TooltipProgressBar.prototype.createEl = function createEl() { 6223 var el = _Component.prototype.createEl.call(this, 'div', { 6224 className: 'vjs-tooltip-progress-bar vjs-slider-bar', 6225 innerHTML: '<div class="vjs-time-tooltip"></div>\n <span class="vjs-control-text"><span>' + this.localize('Progress') + '</span>: 0%</span>' 6226 }); 6227 6228 this.tooltip = el.querySelector('.vjs-time-tooltip'); 6229 6230 return el; 6231 }; 6232 6233 TooltipProgressBar.prototype.updateDataAttr = function updateDataAttr() { 6234 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime(); 6235 var formattedTime = _utilsFormatTimeJs2['default'](time, this.player_.duration()); 6236 this.el_.setAttribute('data-current-time', formattedTime); 6237 this.tooltip.innerHTML = formattedTime; 6238 }; 6239 6240 return TooltipProgressBar; 6241 })(_componentJs2['default']); 6242 6243 _componentJs2['default'].registerComponent('TooltipProgressBar', TooltipProgressBar); 6244 exports['default'] = TooltipProgressBar; 6245 module.exports = exports['default']; 6246 6247 },{"../../component.js":67,"../../utils/dom.js":134,"../../utils/fn.js":136,"../../utils/format-time.js":137}],81:[function(_dereq_,module,exports){ 6248 /** 6249 * @file custom-control-spacer.js 6250 */ 6251 'use strict'; 6252 6253 exports.__esModule = true; 6254 6255 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6256 6257 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6258 6259 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; } 6260 6261 var _spacerJs = _dereq_('./spacer.js'); 6262 6263 var _spacerJs2 = _interopRequireDefault(_spacerJs); 6264 6265 var _componentJs = _dereq_('../../component.js'); 6266 6267 var _componentJs2 = _interopRequireDefault(_componentJs); 6268 6269 /** 6270 * Spacer specifically meant to be used as an insertion point for new plugins, etc. 6271 * 6272 * @extends Spacer 6273 * @class CustomControlSpacer 6274 */ 6275 6276 var CustomControlSpacer = (function (_Spacer) { 6277 _inherits(CustomControlSpacer, _Spacer); 6278 6279 function CustomControlSpacer() { 6280 _classCallCheck(this, CustomControlSpacer); 6281 6282 _Spacer.apply(this, arguments); 6283 } 6284 6285 /** 6286 * Allow sub components to stack CSS class names 6287 * 6288 * @return {String} The constructed class name 6289 * @method buildCSSClass 6290 */ 6291 6292 CustomControlSpacer.prototype.buildCSSClass = function buildCSSClass() { 6293 return 'vjs-custom-control-spacer ' + _Spacer.prototype.buildCSSClass.call(this); 6294 }; 6295 6296 /** 6297 * Create the component's DOM element 6298 * 6299 * @return {Element} 6300 * @method createEl 6301 */ 6302 6303 CustomControlSpacer.prototype.createEl = function createEl() { 6304 var el = _Spacer.prototype.createEl.call(this, { 6305 className: this.buildCSSClass() 6306 }); 6307 6308 // No-flex/table-cell mode requires there be some content 6309 // in the cell to fill the remaining space of the table. 6310 el.innerHTML = ' '; 6311 return el; 6312 }; 6313 6314 return CustomControlSpacer; 6315 })(_spacerJs2['default']); 6316 6317 _componentJs2['default'].registerComponent('CustomControlSpacer', CustomControlSpacer); 6318 exports['default'] = CustomControlSpacer; 6319 module.exports = exports['default']; 6320 6321 },{"../../component.js":67,"./spacer.js":82}],82:[function(_dereq_,module,exports){ 6322 /** 6323 * @file spacer.js 6324 */ 6325 'use strict'; 6326 6327 exports.__esModule = true; 6328 6329 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6330 6331 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6332 6333 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; } 6334 6335 var _componentJs = _dereq_('../../component.js'); 6336 6337 var _componentJs2 = _interopRequireDefault(_componentJs); 6338 6339 /** 6340 * Just an empty spacer element that can be used as an append point for plugins, etc. 6341 * Also can be used to create space between elements when necessary. 6342 * 6343 * @extends Component 6344 * @class Spacer 6345 */ 6346 6347 var Spacer = (function (_Component) { 6348 _inherits(Spacer, _Component); 6349 6350 function Spacer() { 6351 _classCallCheck(this, Spacer); 6352 6353 _Component.apply(this, arguments); 6354 } 6355 6356 /** 6357 * Allow sub components to stack CSS class names 6358 * 6359 * @return {String} The constructed class name 6360 * @method buildCSSClass 6361 */ 6362 6363 Spacer.prototype.buildCSSClass = function buildCSSClass() { 6364 return 'vjs-spacer ' + _Component.prototype.buildCSSClass.call(this); 6365 }; 6366 6367 /** 6368 * Create the component's DOM element 6369 * 6370 * @return {Element} 6371 * @method createEl 6372 */ 6373 6374 Spacer.prototype.createEl = function createEl() { 6375 return _Component.prototype.createEl.call(this, 'div', { 6376 className: this.buildCSSClass() 6377 }); 6378 }; 6379 6380 return Spacer; 6381 })(_componentJs2['default']); 6382 6383 _componentJs2['default'].registerComponent('Spacer', Spacer); 6384 6385 exports['default'] = Spacer; 6386 module.exports = exports['default']; 6387 6388 },{"../../component.js":67}],83:[function(_dereq_,module,exports){ 6389 /** 6390 * @file caption-settings-menu-item.js 6391 */ 6392 'use strict'; 6393 6394 exports.__esModule = true; 6395 6396 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6397 6398 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6399 6400 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; } 6401 6402 var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js'); 6403 6404 var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs); 6405 6406 var _componentJs = _dereq_('../../component.js'); 6407 6408 var _componentJs2 = _interopRequireDefault(_componentJs); 6409 6410 /** 6411 * The menu item for caption track settings menu 6412 * 6413 * @param {Player|Object} player 6414 * @param {Object=} options 6415 * @extends TextTrackMenuItem 6416 * @class CaptionSettingsMenuItem 6417 */ 6418 6419 var CaptionSettingsMenuItem = (function (_TextTrackMenuItem) { 6420 _inherits(CaptionSettingsMenuItem, _TextTrackMenuItem); 6421 6422 function CaptionSettingsMenuItem(player, options) { 6423 _classCallCheck(this, CaptionSettingsMenuItem); 6424 6425 options['track'] = { 6426 'kind': options['kind'], 6427 'player': player, 6428 'label': options['kind'] + ' settings', 6429 'selectable': false, 6430 'default': false, 6431 mode: 'disabled' 6432 }; 6433 6434 // CaptionSettingsMenuItem has no concept of 'selected' 6435 options['selectable'] = false; 6436 6437 _TextTrackMenuItem.call(this, player, options); 6438 this.addClass('vjs-texttrack-settings'); 6439 this.controlText(', opens ' + options['kind'] + ' settings dialog'); 6440 } 6441 6442 /** 6443 * Handle click on menu item 6444 * 6445 * @method handleClick 6446 */ 6447 6448 CaptionSettingsMenuItem.prototype.handleClick = function handleClick() { 6449 this.player().getChild('textTrackSettings').show(); 6450 this.player().getChild('textTrackSettings').el_.focus(); 6451 }; 6452 6453 return CaptionSettingsMenuItem; 6454 })(_textTrackMenuItemJs2['default']); 6455 6456 _componentJs2['default'].registerComponent('CaptionSettingsMenuItem', CaptionSettingsMenuItem); 6457 exports['default'] = CaptionSettingsMenuItem; 6458 module.exports = exports['default']; 6459 6460 },{"../../component.js":67,"./text-track-menu-item.js":91}],84:[function(_dereq_,module,exports){ 6461 /** 6462 * @file captions-button.js 6463 */ 6464 'use strict'; 6465 6466 exports.__esModule = true; 6467 6468 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6469 6470 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6471 6472 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; } 6473 6474 var _textTrackButtonJs = _dereq_('./text-track-button.js'); 6475 6476 var _textTrackButtonJs2 = _interopRequireDefault(_textTrackButtonJs); 6477 6478 var _componentJs = _dereq_('../../component.js'); 6479 6480 var _componentJs2 = _interopRequireDefault(_componentJs); 6481 6482 var _captionSettingsMenuItemJs = _dereq_('./caption-settings-menu-item.js'); 6483 6484 var _captionSettingsMenuItemJs2 = _interopRequireDefault(_captionSettingsMenuItemJs); 6485 6486 /** 6487 * The button component for toggling and selecting captions 6488 * 6489 * @param {Object} player Player object 6490 * @param {Object=} options Object of option names and values 6491 * @param {Function=} ready Ready callback function 6492 * @extends TextTrackButton 6493 * @class CaptionsButton 6494 */ 6495 6496 var CaptionsButton = (function (_TextTrackButton) { 6497 _inherits(CaptionsButton, _TextTrackButton); 6498 6499 function CaptionsButton(player, options, ready) { 6500 _classCallCheck(this, CaptionsButton); 6501 6502 _TextTrackButton.call(this, player, options, ready); 6503 this.el_.setAttribute('aria-label', 'Captions Menu'); 6504 } 6505 6506 /** 6507 * Allow sub components to stack CSS class names 6508 * 6509 * @return {String} The constructed class name 6510 * @method buildCSSClass 6511 */ 6512 6513 CaptionsButton.prototype.buildCSSClass = function buildCSSClass() { 6514 return 'vjs-captions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); 6515 }; 6516 6517 /** 6518 * Update caption menu items 6519 * 6520 * @method update 6521 */ 6522 6523 CaptionsButton.prototype.update = function update() { 6524 var threshold = 2; 6525 _TextTrackButton.prototype.update.call(this); 6526 6527 // if native, then threshold is 1 because no settings button 6528 if (this.player().tech_ && this.player().tech_['featuresNativeTextTracks']) { 6529 threshold = 1; 6530 } 6531 6532 if (this.items && this.items.length > threshold) { 6533 this.show(); 6534 } else { 6535 this.hide(); 6536 } 6537 }; 6538 6539 /** 6540 * Create caption menu items 6541 * 6542 * @return {Array} Array of menu items 6543 * @method createItems 6544 */ 6545 6546 CaptionsButton.prototype.createItems = function createItems() { 6547 var items = []; 6548 6549 if (!(this.player().tech_ && this.player().tech_['featuresNativeTextTracks'])) { 6550 items.push(new _captionSettingsMenuItemJs2['default'](this.player_, { 'kind': this.kind_ })); 6551 } 6552 6553 return _TextTrackButton.prototype.createItems.call(this, items); 6554 }; 6555 6556 return CaptionsButton; 6557 })(_textTrackButtonJs2['default']); 6558 6559 CaptionsButton.prototype.kind_ = 'captions'; 6560 CaptionsButton.prototype.controlText_ = 'Captions'; 6561 6562 _componentJs2['default'].registerComponent('CaptionsButton', CaptionsButton); 6563 exports['default'] = CaptionsButton; 6564 module.exports = exports['default']; 6565 6566 },{"../../component.js":67,"./caption-settings-menu-item.js":83,"./text-track-button.js":90}],85:[function(_dereq_,module,exports){ 6567 /** 6568 * @file chapters-button.js 6569 */ 6570 'use strict'; 6571 6572 exports.__esModule = true; 6573 6574 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; } } 6575 6576 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6577 6578 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6579 6580 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; } 6581 6582 var _textTrackButtonJs = _dereq_('./text-track-button.js'); 6583 6584 var _textTrackButtonJs2 = _interopRequireDefault(_textTrackButtonJs); 6585 6586 var _componentJs = _dereq_('../../component.js'); 6587 6588 var _componentJs2 = _interopRequireDefault(_componentJs); 6589 6590 var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js'); 6591 6592 var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs); 6593 6594 var _chaptersTrackMenuItemJs = _dereq_('./chapters-track-menu-item.js'); 6595 6596 var _chaptersTrackMenuItemJs2 = _interopRequireDefault(_chaptersTrackMenuItemJs); 6597 6598 var _menuMenuJs = _dereq_('../../menu/menu.js'); 6599 6600 var _menuMenuJs2 = _interopRequireDefault(_menuMenuJs); 6601 6602 var _utilsDomJs = _dereq_('../../utils/dom.js'); 6603 6604 var Dom = _interopRequireWildcard(_utilsDomJs); 6605 6606 var _utilsFnJs = _dereq_('../../utils/fn.js'); 6607 6608 var Fn = _interopRequireWildcard(_utilsFnJs); 6609 6610 var _utilsToTitleCaseJs = _dereq_('../../utils/to-title-case.js'); 6611 6612 var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs); 6613 6614 var _globalWindow = _dereq_('global/window'); 6615 6616 var _globalWindow2 = _interopRequireDefault(_globalWindow); 6617 6618 /** 6619 * The button component for toggling and selecting chapters 6620 * Chapters act much differently than other text tracks 6621 * Cues are navigation vs. other tracks of alternative languages 6622 * 6623 * @param {Object} player Player object 6624 * @param {Object=} options Object of option names and values 6625 * @param {Function=} ready Ready callback function 6626 * @extends TextTrackButton 6627 * @class ChaptersButton 6628 */ 6629 6630 var ChaptersButton = (function (_TextTrackButton) { 6631 _inherits(ChaptersButton, _TextTrackButton); 6632 6633 function ChaptersButton(player, options, ready) { 6634 _classCallCheck(this, ChaptersButton); 6635 6636 _TextTrackButton.call(this, player, options, ready); 6637 this.el_.setAttribute('aria-label', 'Chapters Menu'); 6638 } 6639 6640 /** 6641 * Allow sub components to stack CSS class names 6642 * 6643 * @return {String} The constructed class name 6644 * @method buildCSSClass 6645 */ 6646 6647 ChaptersButton.prototype.buildCSSClass = function buildCSSClass() { 6648 return 'vjs-chapters-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); 6649 }; 6650 6651 /** 6652 * Create a menu item for each text track 6653 * 6654 * @return {Array} Array of menu items 6655 * @method createItems 6656 */ 6657 6658 ChaptersButton.prototype.createItems = function createItems() { 6659 var items = []; 6660 6661 var tracks = this.player_.textTracks(); 6662 6663 if (!tracks) { 6664 return items; 6665 } 6666 6667 for (var i = 0; i < tracks.length; i++) { 6668 var track = tracks[i]; 6669 if (track['kind'] === this.kind_) { 6670 items.push(new _textTrackMenuItemJs2['default'](this.player_, { 6671 'track': track 6672 })); 6673 } 6674 } 6675 6676 return items; 6677 }; 6678 6679 /** 6680 * Create menu from chapter buttons 6681 * 6682 * @return {Menu} Menu of chapter buttons 6683 * @method createMenu 6684 */ 6685 6686 ChaptersButton.prototype.createMenu = function createMenu() { 6687 var _this = this; 6688 6689 var tracks = this.player_.textTracks() || []; 6690 var chaptersTrack = undefined; 6691 var items = this.items = []; 6692 6693 for (var i = 0, _length = tracks.length; i < _length; i++) { 6694 var track = tracks[i]; 6695 6696 if (track['kind'] === this.kind_) { 6697 chaptersTrack = track; 6698 6699 break; 6700 } 6701 } 6702 6703 var menu = this.menu; 6704 if (menu === undefined) { 6705 menu = new _menuMenuJs2['default'](this.player_); 6706 var title = Dom.createEl('li', { 6707 className: 'vjs-menu-title', 6708 innerHTML: _utilsToTitleCaseJs2['default'](this.kind_), 6709 tabIndex: -1 6710 }); 6711 menu.children_.unshift(title); 6712 Dom.insertElFirst(title, menu.contentEl()); 6713 } 6714 6715 if (chaptersTrack && chaptersTrack.cues == null) { 6716 chaptersTrack['mode'] = 'hidden'; 6717 6718 var remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(chaptersTrack); 6719 6720 if (remoteTextTrackEl) { 6721 remoteTextTrackEl.addEventListener('load', function (event) { 6722 return _this.update(); 6723 }); 6724 } 6725 } 6726 6727 if (chaptersTrack && chaptersTrack.cues && chaptersTrack.cues.length > 0) { 6728 var cues = chaptersTrack['cues'], 6729 cue = undefined; 6730 6731 for (var i = 0, l = cues.length; i < l; i++) { 6732 cue = cues[i]; 6733 6734 var mi = new _chaptersTrackMenuItemJs2['default'](this.player_, { 6735 'track': chaptersTrack, 6736 'cue': cue 6737 }); 6738 6739 items.push(mi); 6740 6741 menu.addChild(mi); 6742 } 6743 6744 this.addChild(menu); 6745 } 6746 6747 if (this.items.length > 0) { 6748 this.show(); 6749 } 6750 6751 return menu; 6752 }; 6753 6754 return ChaptersButton; 6755 })(_textTrackButtonJs2['default']); 6756 6757 ChaptersButton.prototype.kind_ = 'chapters'; 6758 ChaptersButton.prototype.controlText_ = 'Chapters'; 6759 6760 _componentJs2['default'].registerComponent('ChaptersButton', ChaptersButton); 6761 exports['default'] = ChaptersButton; 6762 module.exports = exports['default']; 6763 6764 },{"../../component.js":67,"../../menu/menu.js":108,"../../utils/dom.js":134,"../../utils/fn.js":136,"../../utils/to-title-case.js":143,"./chapters-track-menu-item.js":86,"./text-track-button.js":90,"./text-track-menu-item.js":91,"global/window":2}],86:[function(_dereq_,module,exports){ 6765 /** 6766 * @file chapters-track-menu-item.js 6767 */ 6768 'use strict'; 6769 6770 exports.__esModule = true; 6771 6772 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; } } 6773 6774 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6775 6776 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6777 6778 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; } 6779 6780 var _menuMenuItemJs = _dereq_('../../menu/menu-item.js'); 6781 6782 var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs); 6783 6784 var _componentJs = _dereq_('../../component.js'); 6785 6786 var _componentJs2 = _interopRequireDefault(_componentJs); 6787 6788 var _utilsFnJs = _dereq_('../../utils/fn.js'); 6789 6790 var Fn = _interopRequireWildcard(_utilsFnJs); 6791 6792 /** 6793 * The chapter track menu item 6794 * 6795 * @param {Player|Object} player 6796 * @param {Object=} options 6797 * @extends MenuItem 6798 * @class ChaptersTrackMenuItem 6799 */ 6800 6801 var ChaptersTrackMenuItem = (function (_MenuItem) { 6802 _inherits(ChaptersTrackMenuItem, _MenuItem); 6803 6804 function ChaptersTrackMenuItem(player, options) { 6805 _classCallCheck(this, ChaptersTrackMenuItem); 6806 6807 var track = options['track']; 6808 var cue = options['cue']; 6809 var currentTime = player.currentTime(); 6810 6811 // Modify options for parent MenuItem class's init. 6812 options['label'] = cue.text; 6813 options['selected'] = cue['startTime'] <= currentTime && currentTime < cue['endTime']; 6814 _MenuItem.call(this, player, options); 6815 6816 this.track = track; 6817 this.cue = cue; 6818 track.addEventListener('cuechange', Fn.bind(this, this.update)); 6819 } 6820 6821 /** 6822 * Handle click on menu item 6823 * 6824 * @method handleClick 6825 */ 6826 6827 ChaptersTrackMenuItem.prototype.handleClick = function handleClick() { 6828 _MenuItem.prototype.handleClick.call(this); 6829 this.player_.currentTime(this.cue.startTime); 6830 this.update(this.cue.startTime); 6831 }; 6832 6833 /** 6834 * Update chapter menu item 6835 * 6836 * @method update 6837 */ 6838 6839 ChaptersTrackMenuItem.prototype.update = function update() { 6840 var cue = this.cue; 6841 var currentTime = this.player_.currentTime(); 6842 6843 // vjs.log(currentTime, cue.startTime); 6844 this.selected(cue['startTime'] <= currentTime && currentTime < cue['endTime']); 6845 }; 6846 6847 return ChaptersTrackMenuItem; 6848 })(_menuMenuItemJs2['default']); 6849 6850 _componentJs2['default'].registerComponent('ChaptersTrackMenuItem', ChaptersTrackMenuItem); 6851 exports['default'] = ChaptersTrackMenuItem; 6852 module.exports = exports['default']; 6853 6854 },{"../../component.js":67,"../../menu/menu-item.js":107,"../../utils/fn.js":136}],87:[function(_dereq_,module,exports){ 6855 /** 6856 * @file descriptions-button.js 6857 */ 6858 'use strict'; 6859 6860 exports.__esModule = true; 6861 6862 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; } } 6863 6864 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6865 6866 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6867 6868 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; } 6869 6870 var _textTrackButtonJs = _dereq_('./text-track-button.js'); 6871 6872 var _textTrackButtonJs2 = _interopRequireDefault(_textTrackButtonJs); 6873 6874 var _componentJs = _dereq_('../../component.js'); 6875 6876 var _componentJs2 = _interopRequireDefault(_componentJs); 6877 6878 var _utilsFnJs = _dereq_('../../utils/fn.js'); 6879 6880 var Fn = _interopRequireWildcard(_utilsFnJs); 6881 6882 /** 6883 * The button component for toggling and selecting descriptions 6884 * 6885 * @param {Object} player Player object 6886 * @param {Object=} options Object of option names and values 6887 * @param {Function=} ready Ready callback function 6888 * @extends TextTrackButton 6889 * @class DescriptionsButton 6890 */ 6891 6892 var DescriptionsButton = (function (_TextTrackButton) { 6893 _inherits(DescriptionsButton, _TextTrackButton); 6894 6895 function DescriptionsButton(player, options, ready) { 6896 var _this = this; 6897 6898 _classCallCheck(this, DescriptionsButton); 6899 6900 _TextTrackButton.call(this, player, options, ready); 6901 this.el_.setAttribute('aria-label', 'Descriptions Menu'); 6902 6903 var tracks = player.textTracks(); 6904 6905 if (tracks) { 6906 (function () { 6907 var changeHandler = Fn.bind(_this, _this.handleTracksChange); 6908 6909 tracks.addEventListener('change', changeHandler); 6910 _this.on('dispose', function () { 6911 tracks.removeEventListener('change', changeHandler); 6912 }); 6913 })(); 6914 } 6915 } 6916 6917 /** 6918 * Handle text track change 6919 * 6920 * @method handleTracksChange 6921 */ 6922 6923 DescriptionsButton.prototype.handleTracksChange = function handleTracksChange(event) { 6924 var tracks = this.player().textTracks(); 6925 var disabled = false; 6926 6927 // Check whether a track of a different kind is showing 6928 for (var i = 0, l = tracks.length; i < l; i++) { 6929 var track = tracks[i]; 6930 if (track['kind'] !== this.kind_ && track['mode'] === 'showing') { 6931 disabled = true; 6932 break; 6933 } 6934 } 6935 6936 // If another track is showing, disable this menu button 6937 if (disabled) { 6938 this.disable(); 6939 } else { 6940 this.enable(); 6941 } 6942 }; 6943 6944 /** 6945 * Allow sub components to stack CSS class names 6946 * 6947 * @return {String} The constructed class name 6948 * @method buildCSSClass 6949 */ 6950 6951 DescriptionsButton.prototype.buildCSSClass = function buildCSSClass() { 6952 return 'vjs-descriptions-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); 6953 }; 6954 6955 return DescriptionsButton; 6956 })(_textTrackButtonJs2['default']); 6957 6958 DescriptionsButton.prototype.kind_ = 'descriptions'; 6959 DescriptionsButton.prototype.controlText_ = 'Descriptions'; 6960 6961 _componentJs2['default'].registerComponent('DescriptionsButton', DescriptionsButton); 6962 exports['default'] = DescriptionsButton; 6963 module.exports = exports['default']; 6964 6965 },{"../../component.js":67,"../../utils/fn.js":136,"./text-track-button.js":90}],88:[function(_dereq_,module,exports){ 6966 /** 6967 * @file off-text-track-menu-item.js 6968 */ 6969 'use strict'; 6970 6971 exports.__esModule = true; 6972 6973 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 6974 6975 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 6976 6977 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; } 6978 6979 var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js'); 6980 6981 var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs); 6982 6983 var _componentJs = _dereq_('../../component.js'); 6984 6985 var _componentJs2 = _interopRequireDefault(_componentJs); 6986 6987 /** 6988 * A special menu item for turning of a specific type of text track 6989 * 6990 * @param {Player|Object} player 6991 * @param {Object=} options 6992 * @extends TextTrackMenuItem 6993 * @class OffTextTrackMenuItem 6994 */ 6995 6996 var OffTextTrackMenuItem = (function (_TextTrackMenuItem) { 6997 _inherits(OffTextTrackMenuItem, _TextTrackMenuItem); 6998 6999 function OffTextTrackMenuItem(player, options) { 7000 _classCallCheck(this, OffTextTrackMenuItem); 7001 7002 // Create pseudo track info 7003 // Requires options['kind'] 7004 options['track'] = { 7005 'kind': options['kind'], 7006 'player': player, 7007 'label': options['kind'] + ' off', 7008 'default': false, 7009 'mode': 'disabled' 7010 }; 7011 7012 // MenuItem is selectable 7013 options['selectable'] = true; 7014 7015 _TextTrackMenuItem.call(this, player, options); 7016 this.selected(true); 7017 } 7018 7019 /** 7020 * Handle text track change 7021 * 7022 * @param {Object} event Event object 7023 * @method handleTracksChange 7024 */ 7025 7026 OffTextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) { 7027 var tracks = this.player().textTracks(); 7028 var selected = true; 7029 7030 for (var i = 0, l = tracks.length; i < l; i++) { 7031 var track = tracks[i]; 7032 if (track['kind'] === this.track['kind'] && track['mode'] === 'showing') { 7033 selected = false; 7034 break; 7035 } 7036 } 7037 7038 this.selected(selected); 7039 }; 7040 7041 return OffTextTrackMenuItem; 7042 })(_textTrackMenuItemJs2['default']); 7043 7044 _componentJs2['default'].registerComponent('OffTextTrackMenuItem', OffTextTrackMenuItem); 7045 exports['default'] = OffTextTrackMenuItem; 7046 module.exports = exports['default']; 7047 7048 },{"../../component.js":67,"./text-track-menu-item.js":91}],89:[function(_dereq_,module,exports){ 7049 /** 7050 * @file subtitles-button.js 7051 */ 7052 'use strict'; 7053 7054 exports.__esModule = true; 7055 7056 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7057 7058 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7059 7060 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; } 7061 7062 var _textTrackButtonJs = _dereq_('./text-track-button.js'); 7063 7064 var _textTrackButtonJs2 = _interopRequireDefault(_textTrackButtonJs); 7065 7066 var _componentJs = _dereq_('../../component.js'); 7067 7068 var _componentJs2 = _interopRequireDefault(_componentJs); 7069 7070 /** 7071 * The button component for toggling and selecting subtitles 7072 * 7073 * @param {Object} player Player object 7074 * @param {Object=} options Object of option names and values 7075 * @param {Function=} ready Ready callback function 7076 * @extends TextTrackButton 7077 * @class SubtitlesButton 7078 */ 7079 7080 var SubtitlesButton = (function (_TextTrackButton) { 7081 _inherits(SubtitlesButton, _TextTrackButton); 7082 7083 function SubtitlesButton(player, options, ready) { 7084 _classCallCheck(this, SubtitlesButton); 7085 7086 _TextTrackButton.call(this, player, options, ready); 7087 this.el_.setAttribute('aria-label', 'Subtitles Menu'); 7088 } 7089 7090 /** 7091 * Allow sub components to stack CSS class names 7092 * 7093 * @return {String} The constructed class name 7094 * @method buildCSSClass 7095 */ 7096 7097 SubtitlesButton.prototype.buildCSSClass = function buildCSSClass() { 7098 return 'vjs-subtitles-button ' + _TextTrackButton.prototype.buildCSSClass.call(this); 7099 }; 7100 7101 return SubtitlesButton; 7102 })(_textTrackButtonJs2['default']); 7103 7104 SubtitlesButton.prototype.kind_ = 'subtitles'; 7105 SubtitlesButton.prototype.controlText_ = 'Subtitles'; 7106 7107 _componentJs2['default'].registerComponent('SubtitlesButton', SubtitlesButton); 7108 exports['default'] = SubtitlesButton; 7109 module.exports = exports['default']; 7110 7111 },{"../../component.js":67,"./text-track-button.js":90}],90:[function(_dereq_,module,exports){ 7112 /** 7113 * @file text-track-button.js 7114 */ 7115 'use strict'; 7116 7117 exports.__esModule = true; 7118 7119 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; } } 7120 7121 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7122 7123 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7124 7125 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; } 7126 7127 var _menuMenuButtonJs = _dereq_('../../menu/menu-button.js'); 7128 7129 var _menuMenuButtonJs2 = _interopRequireDefault(_menuMenuButtonJs); 7130 7131 var _componentJs = _dereq_('../../component.js'); 7132 7133 var _componentJs2 = _interopRequireDefault(_componentJs); 7134 7135 var _utilsFnJs = _dereq_('../../utils/fn.js'); 7136 7137 var Fn = _interopRequireWildcard(_utilsFnJs); 7138 7139 var _textTrackMenuItemJs = _dereq_('./text-track-menu-item.js'); 7140 7141 var _textTrackMenuItemJs2 = _interopRequireDefault(_textTrackMenuItemJs); 7142 7143 var _offTextTrackMenuItemJs = _dereq_('./off-text-track-menu-item.js'); 7144 7145 var _offTextTrackMenuItemJs2 = _interopRequireDefault(_offTextTrackMenuItemJs); 7146 7147 /** 7148 * The base class for buttons that toggle specific text track types (e.g. subtitles) 7149 * 7150 * @param {Player|Object} player 7151 * @param {Object=} options 7152 * @extends MenuButton 7153 * @class TextTrackButton 7154 */ 7155 7156 var TextTrackButton = (function (_MenuButton) { 7157 _inherits(TextTrackButton, _MenuButton); 7158 7159 function TextTrackButton(player, options) { 7160 _classCallCheck(this, TextTrackButton); 7161 7162 _MenuButton.call(this, player, options); 7163 7164 var tracks = this.player_.textTracks(); 7165 7166 if (this.items.length <= 1) { 7167 this.hide(); 7168 } 7169 7170 if (!tracks) { 7171 return; 7172 } 7173 7174 var updateHandler = Fn.bind(this, this.update); 7175 tracks.addEventListener('removetrack', updateHandler); 7176 tracks.addEventListener('addtrack', updateHandler); 7177 7178 this.player_.on('dispose', function () { 7179 tracks.removeEventListener('removetrack', updateHandler); 7180 tracks.removeEventListener('addtrack', updateHandler); 7181 }); 7182 } 7183 7184 // Create a menu item for each text track 7185 7186 TextTrackButton.prototype.createItems = function createItems() { 7187 var items = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; 7188 7189 // Add an OFF menu item to turn all tracks off 7190 items.push(new _offTextTrackMenuItemJs2['default'](this.player_, { 'kind': this.kind_ })); 7191 7192 var tracks = this.player_.textTracks(); 7193 7194 if (!tracks) { 7195 return items; 7196 } 7197 7198 for (var i = 0; i < tracks.length; i++) { 7199 var track = tracks[i]; 7200 7201 // only add tracks that are of the appropriate kind and have a label 7202 if (track['kind'] === this.kind_) { 7203 items.push(new _textTrackMenuItemJs2['default'](this.player_, { 7204 // MenuItem is selectable 7205 'selectable': true, 7206 'track': track 7207 })); 7208 } 7209 } 7210 7211 return items; 7212 }; 7213 7214 return TextTrackButton; 7215 })(_menuMenuButtonJs2['default']); 7216 7217 _componentJs2['default'].registerComponent('TextTrackButton', TextTrackButton); 7218 exports['default'] = TextTrackButton; 7219 module.exports = exports['default']; 7220 7221 },{"../../component.js":67,"../../menu/menu-button.js":106,"../../utils/fn.js":136,"./off-text-track-menu-item.js":88,"./text-track-menu-item.js":91}],91:[function(_dereq_,module,exports){ 7222 /** 7223 * @file text-track-menu-item.js 7224 */ 7225 'use strict'; 7226 7227 exports.__esModule = true; 7228 7229 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; } } 7230 7231 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7232 7233 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7234 7235 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; } 7236 7237 var _menuMenuItemJs = _dereq_('../../menu/menu-item.js'); 7238 7239 var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs); 7240 7241 var _componentJs = _dereq_('../../component.js'); 7242 7243 var _componentJs2 = _interopRequireDefault(_componentJs); 7244 7245 var _utilsFnJs = _dereq_('../../utils/fn.js'); 7246 7247 var Fn = _interopRequireWildcard(_utilsFnJs); 7248 7249 var _globalWindow = _dereq_('global/window'); 7250 7251 var _globalWindow2 = _interopRequireDefault(_globalWindow); 7252 7253 var _globalDocument = _dereq_('global/document'); 7254 7255 var _globalDocument2 = _interopRequireDefault(_globalDocument); 7256 7257 /** 7258 * The specific menu item type for selecting a language within a text track kind 7259 * 7260 * @param {Player|Object} player 7261 * @param {Object=} options 7262 * @extends MenuItem 7263 * @class TextTrackMenuItem 7264 */ 7265 7266 var TextTrackMenuItem = (function (_MenuItem) { 7267 _inherits(TextTrackMenuItem, _MenuItem); 7268 7269 function TextTrackMenuItem(player, options) { 7270 var _this = this; 7271 7272 _classCallCheck(this, TextTrackMenuItem); 7273 7274 var track = options['track']; 7275 var tracks = player.textTracks(); 7276 7277 // Modify options for parent MenuItem class's init. 7278 options['label'] = track['label'] || track['language'] || 'Unknown'; 7279 options['selected'] = track['default'] || track['mode'] === 'showing'; 7280 7281 _MenuItem.call(this, player, options); 7282 7283 this.track = track; 7284 7285 if (tracks) { 7286 (function () { 7287 var changeHandler = Fn.bind(_this, _this.handleTracksChange); 7288 7289 tracks.addEventListener('change', changeHandler); 7290 _this.on('dispose', function () { 7291 tracks.removeEventListener('change', changeHandler); 7292 }); 7293 })(); 7294 } 7295 7296 // iOS7 doesn't dispatch change events to TextTrackLists when an 7297 // associated track's mode changes. Without something like 7298 // Object.observe() (also not present on iOS7), it's not 7299 // possible to detect changes to the mode attribute and polyfill 7300 // the change event. As a poor substitute, we manually dispatch 7301 // change events whenever the controls modify the mode. 7302 if (tracks && tracks.onchange === undefined) { 7303 (function () { 7304 var event = undefined; 7305 7306 _this.on(['tap', 'click'], function () { 7307 if (typeof _globalWindow2['default'].Event !== 'object') { 7308 // Android 2.3 throws an Illegal Constructor error for window.Event 7309 try { 7310 event = new _globalWindow2['default'].Event('change'); 7311 } catch (err) {} 7312 } 7313 7314 if (!event) { 7315 event = _globalDocument2['default'].createEvent('Event'); 7316 event.initEvent('change', true, true); 7317 } 7318 7319 tracks.dispatchEvent(event); 7320 }); 7321 })(); 7322 } 7323 } 7324 7325 /** 7326 * Handle click on text track 7327 * 7328 * @method handleClick 7329 */ 7330 7331 TextTrackMenuItem.prototype.handleClick = function handleClick(event) { 7332 var kind = this.track['kind']; 7333 var tracks = this.player_.textTracks(); 7334 7335 _MenuItem.prototype.handleClick.call(this, event); 7336 7337 if (!tracks) return; 7338 7339 for (var i = 0; i < tracks.length; i++) { 7340 var track = tracks[i]; 7341 7342 if (track['kind'] !== kind) { 7343 continue; 7344 } 7345 7346 if (track === this.track) { 7347 track['mode'] = 'showing'; 7348 } else { 7349 track['mode'] = 'disabled'; 7350 } 7351 } 7352 }; 7353 7354 /** 7355 * Handle text track change 7356 * 7357 * @method handleTracksChange 7358 */ 7359 7360 TextTrackMenuItem.prototype.handleTracksChange = function handleTracksChange(event) { 7361 this.selected(this.track['mode'] === 'showing'); 7362 }; 7363 7364 return TextTrackMenuItem; 7365 })(_menuMenuItemJs2['default']); 7366 7367 _componentJs2['default'].registerComponent('TextTrackMenuItem', TextTrackMenuItem); 7368 exports['default'] = TextTrackMenuItem; 7369 module.exports = exports['default']; 7370 7371 },{"../../component.js":67,"../../menu/menu-item.js":107,"../../utils/fn.js":136,"global/document":1,"global/window":2}],92:[function(_dereq_,module,exports){ 7372 /** 7373 * @file current-time-display.js 7374 */ 7375 'use strict'; 7376 7377 exports.__esModule = true; 7378 7379 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; } } 7380 7381 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7382 7383 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7384 7385 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; } 7386 7387 var _componentJs = _dereq_('../../component.js'); 7388 7389 var _componentJs2 = _interopRequireDefault(_componentJs); 7390 7391 var _utilsDomJs = _dereq_('../../utils/dom.js'); 7392 7393 var Dom = _interopRequireWildcard(_utilsDomJs); 7394 7395 var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js'); 7396 7397 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 7398 7399 /** 7400 * Displays the current time 7401 * 7402 * @param {Player|Object} player 7403 * @param {Object=} options 7404 * @extends Component 7405 * @class CurrentTimeDisplay 7406 */ 7407 7408 var CurrentTimeDisplay = (function (_Component) { 7409 _inherits(CurrentTimeDisplay, _Component); 7410 7411 function CurrentTimeDisplay(player, options) { 7412 _classCallCheck(this, CurrentTimeDisplay); 7413 7414 _Component.call(this, player, options); 7415 7416 this.on(player, 'timeupdate', this.updateContent); 7417 } 7418 7419 /** 7420 * Create the component's DOM element 7421 * 7422 * @return {Element} 7423 * @method createEl 7424 */ 7425 7426 CurrentTimeDisplay.prototype.createEl = function createEl() { 7427 var el = _Component.prototype.createEl.call(this, 'div', { 7428 className: 'vjs-current-time vjs-time-control vjs-control' 7429 }); 7430 7431 this.contentEl_ = Dom.createEl('div', { 7432 className: 'vjs-current-time-display', 7433 // label the current time for screen reader users 7434 innerHTML: '<span class="vjs-control-text">Current Time </span>' + '0:00' 7435 }, { 7436 // tell screen readers not to automatically read the time as it changes 7437 'aria-live': 'off' 7438 }); 7439 7440 el.appendChild(this.contentEl_); 7441 return el; 7442 }; 7443 7444 /** 7445 * Update current time display 7446 * 7447 * @method updateContent 7448 */ 7449 7450 CurrentTimeDisplay.prototype.updateContent = function updateContent() { 7451 // Allows for smooth scrubbing, when player can't keep up. 7452 var time = this.player_.scrubbing() ? this.player_.getCache().currentTime : this.player_.currentTime(); 7453 var localizedText = this.localize('Current Time'); 7454 var formattedTime = _utilsFormatTimeJs2['default'](time, this.player_.duration()); 7455 if (formattedTime !== this.formattedTime_) { 7456 this.formattedTime_ = formattedTime; 7457 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime; 7458 } 7459 }; 7460 7461 return CurrentTimeDisplay; 7462 })(_componentJs2['default']); 7463 7464 _componentJs2['default'].registerComponent('CurrentTimeDisplay', CurrentTimeDisplay); 7465 exports['default'] = CurrentTimeDisplay; 7466 module.exports = exports['default']; 7467 7468 },{"../../component.js":67,"../../utils/dom.js":134,"../../utils/format-time.js":137}],93:[function(_dereq_,module,exports){ 7469 /** 7470 * @file duration-display.js 7471 */ 7472 'use strict'; 7473 7474 exports.__esModule = true; 7475 7476 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; } } 7477 7478 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7479 7480 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7481 7482 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; } 7483 7484 var _componentJs = _dereq_('../../component.js'); 7485 7486 var _componentJs2 = _interopRequireDefault(_componentJs); 7487 7488 var _utilsDomJs = _dereq_('../../utils/dom.js'); 7489 7490 var Dom = _interopRequireWildcard(_utilsDomJs); 7491 7492 var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js'); 7493 7494 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 7495 7496 /** 7497 * Displays the duration 7498 * 7499 * @param {Player|Object} player 7500 * @param {Object=} options 7501 * @extends Component 7502 * @class DurationDisplay 7503 */ 7504 7505 var DurationDisplay = (function (_Component) { 7506 _inherits(DurationDisplay, _Component); 7507 7508 function DurationDisplay(player, options) { 7509 _classCallCheck(this, DurationDisplay); 7510 7511 _Component.call(this, player, options); 7512 7513 // this might need to be changed to 'durationchange' instead of 'timeupdate' eventually, 7514 // however the durationchange event fires before this.player_.duration() is set, 7515 // so the value cannot be written out using this method. 7516 // Once the order of durationchange and this.player_.duration() being set is figured out, 7517 // this can be updated. 7518 this.on(player, 'timeupdate', this.updateContent); 7519 this.on(player, 'loadedmetadata', this.updateContent); 7520 } 7521 7522 /** 7523 * Create the component's DOM element 7524 * 7525 * @return {Element} 7526 * @method createEl 7527 */ 7528 7529 DurationDisplay.prototype.createEl = function createEl() { 7530 var el = _Component.prototype.createEl.call(this, 'div', { 7531 className: 'vjs-duration vjs-time-control vjs-control' 7532 }); 7533 7534 this.contentEl_ = Dom.createEl('div', { 7535 className: 'vjs-duration-display', 7536 // label the duration time for screen reader users 7537 innerHTML: '<span class="vjs-control-text">' + this.localize('Duration Time') + '</span> 0:00' 7538 }, { 7539 // tell screen readers not to automatically read the time as it changes 7540 'aria-live': 'off' 7541 }); 7542 7543 el.appendChild(this.contentEl_); 7544 return el; 7545 }; 7546 7547 /** 7548 * Update duration time display 7549 * 7550 * @method updateContent 7551 */ 7552 7553 DurationDisplay.prototype.updateContent = function updateContent() { 7554 var duration = this.player_.duration(); 7555 if (duration && this.duration_ !== duration) { 7556 this.duration_ = duration; 7557 var localizedText = this.localize('Duration Time'); 7558 var formattedTime = _utilsFormatTimeJs2['default'](duration); 7559 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> ' + formattedTime; // label the duration time for screen reader users 7560 } 7561 }; 7562 7563 return DurationDisplay; 7564 })(_componentJs2['default']); 7565 7566 _componentJs2['default'].registerComponent('DurationDisplay', DurationDisplay); 7567 exports['default'] = DurationDisplay; 7568 module.exports = exports['default']; 7569 7570 },{"../../component.js":67,"../../utils/dom.js":134,"../../utils/format-time.js":137}],94:[function(_dereq_,module,exports){ 7571 /** 7572 * @file remaining-time-display.js 7573 */ 7574 'use strict'; 7575 7576 exports.__esModule = true; 7577 7578 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; } } 7579 7580 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7581 7582 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7583 7584 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; } 7585 7586 var _componentJs = _dereq_('../../component.js'); 7587 7588 var _componentJs2 = _interopRequireDefault(_componentJs); 7589 7590 var _utilsDomJs = _dereq_('../../utils/dom.js'); 7591 7592 var Dom = _interopRequireWildcard(_utilsDomJs); 7593 7594 var _utilsFormatTimeJs = _dereq_('../../utils/format-time.js'); 7595 7596 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 7597 7598 /** 7599 * Displays the time left in the video 7600 * 7601 * @param {Player|Object} player 7602 * @param {Object=} options 7603 * @extends Component 7604 * @class RemainingTimeDisplay 7605 */ 7606 7607 var RemainingTimeDisplay = (function (_Component) { 7608 _inherits(RemainingTimeDisplay, _Component); 7609 7610 function RemainingTimeDisplay(player, options) { 7611 _classCallCheck(this, RemainingTimeDisplay); 7612 7613 _Component.call(this, player, options); 7614 7615 this.on(player, 'timeupdate', this.updateContent); 7616 } 7617 7618 /** 7619 * Create the component's DOM element 7620 * 7621 * @return {Element} 7622 * @method createEl 7623 */ 7624 7625 RemainingTimeDisplay.prototype.createEl = function createEl() { 7626 var el = _Component.prototype.createEl.call(this, 'div', { 7627 className: 'vjs-remaining-time vjs-time-control vjs-control' 7628 }); 7629 7630 this.contentEl_ = Dom.createEl('div', { 7631 className: 'vjs-remaining-time-display', 7632 // label the remaining time for screen reader users 7633 innerHTML: '<span class="vjs-control-text">' + this.localize('Remaining Time') + '</span> -0:00' 7634 }, { 7635 // tell screen readers not to automatically read the time as it changes 7636 'aria-live': 'off' 7637 }); 7638 7639 el.appendChild(this.contentEl_); 7640 return el; 7641 }; 7642 7643 /** 7644 * Update remaining time display 7645 * 7646 * @method updateContent 7647 */ 7648 7649 RemainingTimeDisplay.prototype.updateContent = function updateContent() { 7650 if (this.player_.duration()) { 7651 var localizedText = this.localize('Remaining Time'); 7652 var formattedTime = _utilsFormatTimeJs2['default'](this.player_.remainingTime()); 7653 if (formattedTime !== this.formattedTime_) { 7654 this.formattedTime_ = formattedTime; 7655 this.contentEl_.innerHTML = '<span class="vjs-control-text">' + localizedText + '</span> -' + formattedTime; 7656 } 7657 } 7658 7659 // Allows for smooth scrubbing, when player can't keep up. 7660 // var time = (this.player_.scrubbing()) ? this.player_.getCache().currentTime : this.player_.currentTime(); 7661 // this.contentEl_.innerHTML = vjs.formatTime(time, this.player_.duration()); 7662 }; 7663 7664 return RemainingTimeDisplay; 7665 })(_componentJs2['default']); 7666 7667 _componentJs2['default'].registerComponent('RemainingTimeDisplay', RemainingTimeDisplay); 7668 exports['default'] = RemainingTimeDisplay; 7669 module.exports = exports['default']; 7670 7671 },{"../../component.js":67,"../../utils/dom.js":134,"../../utils/format-time.js":137}],95:[function(_dereq_,module,exports){ 7672 /** 7673 * @file time-divider.js 7674 */ 7675 'use strict'; 7676 7677 exports.__esModule = true; 7678 7679 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7680 7681 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7682 7683 function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 7684 7685 var _componentJs = _dereq_('../../component.js'); 7686 7687 var _componentJs2 = _interopRequireDefault(_componentJs); 7688 7689 /** 7690 * The separator between the current time and duration. 7691 * Can be hidden if it's not needed in the design. 7692 * 7693 * @param {Player|Object} player 7694 * @param {Object=} options 7695 * @extends Component 7696 * @class TimeDivider 7697 */ 7698 7699 var TimeDivider = (function (_Component) { 7700 _inherits(TimeDivider, _Component); 7701 7702 function TimeDivider() { 7703 _classCallCheck(this, TimeDivider); 7704 7705 _Component.apply(this, arguments); 7706 } 7707 7708 /** 7709 * Create the component's DOM element 7710 * 7711 * @return {Element} 7712 * @method createEl 7713 */ 7714 7715 TimeDivider.prototype.createEl = function createEl() { 7716 return _Component.prototype.createEl.call(this, 'div', { 7717 className: 'vjs-time-control vjs-time-divider', 7718 innerHTML: '<div><span>/</span></div>' 7719 }); 7720 }; 7721 7722 return TimeDivider; 7723 })(_componentJs2['default']); 7724 7725 _componentJs2['default'].registerComponent('TimeDivider', TimeDivider); 7726 exports['default'] = TimeDivider; 7727 module.exports = exports['default']; 7728 7729 },{"../../component.js":67}],96:[function(_dereq_,module,exports){ 7730 /** 7731 * @file volume-bar.js 7732 */ 7733 'use strict'; 7734 7735 exports.__esModule = true; 7736 7737 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; } } 7738 7739 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7740 7741 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7742 7743 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; } 7744 7745 var _sliderSliderJs = _dereq_('../../slider/slider.js'); 7746 7747 var _sliderSliderJs2 = _interopRequireDefault(_sliderSliderJs); 7748 7749 var _componentJs = _dereq_('../../component.js'); 7750 7751 var _componentJs2 = _interopRequireDefault(_componentJs); 7752 7753 var _utilsFnJs = _dereq_('../../utils/fn.js'); 7754 7755 var Fn = _interopRequireWildcard(_utilsFnJs); 7756 7757 // Required children 7758 7759 var _volumeLevelJs = _dereq_('./volume-level.js'); 7760 7761 var _volumeLevelJs2 = _interopRequireDefault(_volumeLevelJs); 7762 7763 /** 7764 * The bar that contains the volume level and can be clicked on to adjust the level 7765 * 7766 * @param {Player|Object} player 7767 * @param {Object=} options 7768 * @extends Slider 7769 * @class VolumeBar 7770 */ 7771 7772 var VolumeBar = (function (_Slider) { 7773 _inherits(VolumeBar, _Slider); 7774 7775 function VolumeBar(player, options) { 7776 _classCallCheck(this, VolumeBar); 7777 7778 _Slider.call(this, player, options); 7779 this.on(player, 'volumechange', this.updateARIAAttributes); 7780 player.ready(Fn.bind(this, this.updateARIAAttributes)); 7781 } 7782 7783 /** 7784 * Create the component's DOM element 7785 * 7786 * @return {Element} 7787 * @method createEl 7788 */ 7789 7790 VolumeBar.prototype.createEl = function createEl() { 7791 return _Slider.prototype.createEl.call(this, 'div', { 7792 className: 'vjs-volume-bar vjs-slider-bar' 7793 }, { 7794 'aria-label': 'volume level' 7795 }); 7796 }; 7797 7798 /** 7799 * Handle mouse move on volume bar 7800 * 7801 * @method handleMouseMove 7802 */ 7803 7804 VolumeBar.prototype.handleMouseMove = function handleMouseMove(event) { 7805 this.checkMuted(); 7806 this.player_.volume(this.calculateDistance(event)); 7807 }; 7808 7809 VolumeBar.prototype.checkMuted = function checkMuted() { 7810 if (this.player_.muted()) { 7811 this.player_.muted(false); 7812 } 7813 }; 7814 7815 /** 7816 * Get percent of volume level 7817 * 7818 * @retun {Number} Volume level percent 7819 * @method getPercent 7820 */ 7821 7822 VolumeBar.prototype.getPercent = function getPercent() { 7823 if (this.player_.muted()) { 7824 return 0; 7825 } else { 7826 return this.player_.volume(); 7827 } 7828 }; 7829 7830 /** 7831 * Increase volume level for keyboard users 7832 * 7833 * @method stepForward 7834 */ 7835 7836 VolumeBar.prototype.stepForward = function stepForward() { 7837 this.checkMuted(); 7838 this.player_.volume(this.player_.volume() + 0.1); 7839 }; 7840 7841 /** 7842 * Decrease volume level for keyboard users 7843 * 7844 * @method stepBack 7845 */ 7846 7847 VolumeBar.prototype.stepBack = function stepBack() { 7848 this.checkMuted(); 7849 this.player_.volume(this.player_.volume() - 0.1); 7850 }; 7851 7852 /** 7853 * Update ARIA accessibility attributes 7854 * 7855 * @method updateARIAAttributes 7856 */ 7857 7858 VolumeBar.prototype.updateARIAAttributes = function updateARIAAttributes() { 7859 // Current value of volume bar as a percentage 7860 var volume = (this.player_.volume() * 100).toFixed(2); 7861 this.el_.setAttribute('aria-valuenow', volume); 7862 this.el_.setAttribute('aria-valuetext', volume + '%'); 7863 }; 7864 7865 return VolumeBar; 7866 })(_sliderSliderJs2['default']); 7867 7868 VolumeBar.prototype.options_ = { 7869 children: ['volumeLevel'], 7870 'barName': 'volumeLevel' 7871 }; 7872 7873 VolumeBar.prototype.playerEvent = 'volumechange'; 7874 7875 _componentJs2['default'].registerComponent('VolumeBar', VolumeBar); 7876 exports['default'] = VolumeBar; 7877 module.exports = exports['default']; 7878 7879 },{"../../component.js":67,"../../slider/slider.js":116,"../../utils/fn.js":136,"./volume-level.js":98}],97:[function(_dereq_,module,exports){ 7880 /** 7881 * @file volume-control.js 7882 */ 7883 'use strict'; 7884 7885 exports.__esModule = true; 7886 7887 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7888 7889 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7890 7891 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; } 7892 7893 var _componentJs = _dereq_('../../component.js'); 7894 7895 var _componentJs2 = _interopRequireDefault(_componentJs); 7896 7897 // Required children 7898 7899 var _volumeBarJs = _dereq_('./volume-bar.js'); 7900 7901 var _volumeBarJs2 = _interopRequireDefault(_volumeBarJs); 7902 7903 /** 7904 * The component for controlling the volume level 7905 * 7906 * @param {Player|Object} player 7907 * @param {Object=} options 7908 * @extends Component 7909 * @class VolumeControl 7910 */ 7911 7912 var VolumeControl = (function (_Component) { 7913 _inherits(VolumeControl, _Component); 7914 7915 function VolumeControl(player, options) { 7916 _classCallCheck(this, VolumeControl); 7917 7918 _Component.call(this, player, options); 7919 7920 // hide volume controls when they're not supported by the current tech 7921 if (player.tech_ && player.tech_['featuresVolumeControl'] === false) { 7922 this.addClass('vjs-hidden'); 7923 } 7924 this.on(player, 'loadstart', function () { 7925 if (player.tech_['featuresVolumeControl'] === false) { 7926 this.addClass('vjs-hidden'); 7927 } else { 7928 this.removeClass('vjs-hidden'); 7929 } 7930 }); 7931 } 7932 7933 /** 7934 * Create the component's DOM element 7935 * 7936 * @return {Element} 7937 * @method createEl 7938 */ 7939 7940 VolumeControl.prototype.createEl = function createEl() { 7941 return _Component.prototype.createEl.call(this, 'div', { 7942 className: 'vjs-volume-control vjs-control' 7943 }); 7944 }; 7945 7946 return VolumeControl; 7947 })(_componentJs2['default']); 7948 7949 VolumeControl.prototype.options_ = { 7950 children: ['volumeBar'] 7951 }; 7952 7953 _componentJs2['default'].registerComponent('VolumeControl', VolumeControl); 7954 exports['default'] = VolumeControl; 7955 module.exports = exports['default']; 7956 7957 },{"../../component.js":67,"./volume-bar.js":96}],98:[function(_dereq_,module,exports){ 7958 /** 7959 * @file volume-level.js 7960 */ 7961 'use strict'; 7962 7963 exports.__esModule = true; 7964 7965 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 7966 7967 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 7968 7969 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; } 7970 7971 var _componentJs = _dereq_('../../component.js'); 7972 7973 var _componentJs2 = _interopRequireDefault(_componentJs); 7974 7975 /** 7976 * Shows volume level 7977 * 7978 * @param {Player|Object} player 7979 * @param {Object=} options 7980 * @extends Component 7981 * @class VolumeLevel 7982 */ 7983 7984 var VolumeLevel = (function (_Component) { 7985 _inherits(VolumeLevel, _Component); 7986 7987 function VolumeLevel() { 7988 _classCallCheck(this, VolumeLevel); 7989 7990 _Component.apply(this, arguments); 7991 } 7992 7993 /** 7994 * Create the component's DOM element 7995 * 7996 * @return {Element} 7997 * @method createEl 7998 */ 7999 8000 VolumeLevel.prototype.createEl = function createEl() { 8001 return _Component.prototype.createEl.call(this, 'div', { 8002 className: 'vjs-volume-level', 8003 innerHTML: '<span class="vjs-control-text"></span>' 8004 }); 8005 }; 8006 8007 return VolumeLevel; 8008 })(_componentJs2['default']); 8009 8010 _componentJs2['default'].registerComponent('VolumeLevel', VolumeLevel); 8011 exports['default'] = VolumeLevel; 8012 module.exports = exports['default']; 8013 8014 },{"../../component.js":67}],99:[function(_dereq_,module,exports){ 8015 /** 8016 * @file volume-menu-button.js 8017 */ 8018 'use strict'; 8019 8020 exports.__esModule = true; 8021 8022 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8023 8024 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; } } 8025 8026 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8027 8028 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; } 8029 8030 var _utilsFnJs = _dereq_('../utils/fn.js'); 8031 8032 var Fn = _interopRequireWildcard(_utilsFnJs); 8033 8034 var _componentJs = _dereq_('../component.js'); 8035 8036 var _componentJs2 = _interopRequireDefault(_componentJs); 8037 8038 var _popupPopupJs = _dereq_('../popup/popup.js'); 8039 8040 var _popupPopupJs2 = _interopRequireDefault(_popupPopupJs); 8041 8042 var _popupPopupButtonJs = _dereq_('../popup/popup-button.js'); 8043 8044 var _popupPopupButtonJs2 = _interopRequireDefault(_popupPopupButtonJs); 8045 8046 var _muteToggleJs = _dereq_('./mute-toggle.js'); 8047 8048 var _muteToggleJs2 = _interopRequireDefault(_muteToggleJs); 8049 8050 var _volumeControlVolumeBarJs = _dereq_('./volume-control/volume-bar.js'); 8051 8052 var _volumeControlVolumeBarJs2 = _interopRequireDefault(_volumeControlVolumeBarJs); 8053 8054 /** 8055 * Button for volume popup 8056 * 8057 * @param {Player|Object} player 8058 * @param {Object=} options 8059 * @extends PopupButton 8060 * @class VolumeMenuButton 8061 */ 8062 8063 var VolumeMenuButton = (function (_PopupButton) { 8064 _inherits(VolumeMenuButton, _PopupButton); 8065 8066 function VolumeMenuButton(player) { 8067 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 8068 8069 _classCallCheck(this, VolumeMenuButton); 8070 8071 // Default to inline 8072 if (options.inline === undefined) { 8073 options.inline = true; 8074 } 8075 8076 // If the vertical option isn't passed at all, default to true. 8077 if (options.vertical === undefined) { 8078 // If an inline volumeMenuButton is used, we should default to using 8079 // a horizontal slider for obvious reasons. 8080 if (options.inline) { 8081 options.vertical = false; 8082 } else { 8083 options.vertical = true; 8084 } 8085 } 8086 8087 // The vertical option needs to be set on the volumeBar as well, 8088 // since that will need to be passed along to the VolumeBar constructor 8089 options.volumeBar = options.volumeBar || {}; 8090 options.volumeBar.vertical = !!options.vertical; 8091 8092 _PopupButton.call(this, player, options); 8093 8094 // Same listeners as MuteToggle 8095 this.on(player, 'volumechange', this.volumeUpdate); 8096 this.on(player, 'loadstart', this.volumeUpdate); 8097 8098 // hide mute toggle if the current tech doesn't support volume control 8099 function updateVisibility() { 8100 if (player.tech_ && player.tech_['featuresVolumeControl'] === false) { 8101 this.addClass('vjs-hidden'); 8102 } else { 8103 this.removeClass('vjs-hidden'); 8104 } 8105 } 8106 8107 updateVisibility.call(this); 8108 this.on(player, 'loadstart', updateVisibility); 8109 8110 this.on(this.volumeBar, ['slideractive', 'focus'], function () { 8111 this.addClass('vjs-slider-active'); 8112 }); 8113 8114 this.on(this.volumeBar, ['sliderinactive', 'blur'], function () { 8115 this.removeClass('vjs-slider-active'); 8116 }); 8117 8118 this.on(this.volumeBar, ['focus'], function () { 8119 this.addClass('vjs-lock-showing'); 8120 }); 8121 8122 this.on(this.volumeBar, ['blur'], function () { 8123 this.removeClass('vjs-lock-showing'); 8124 }); 8125 } 8126 8127 /** 8128 * Allow sub components to stack CSS class names 8129 * 8130 * @return {String} The constructed class name 8131 * @method buildCSSClass 8132 */ 8133 8134 VolumeMenuButton.prototype.buildCSSClass = function buildCSSClass() { 8135 var orientationClass = ''; 8136 if (!!this.options_.vertical) { 8137 orientationClass = 'vjs-volume-menu-button-vertical'; 8138 } else { 8139 orientationClass = 'vjs-volume-menu-button-horizontal'; 8140 } 8141 8142 return 'vjs-volume-menu-button ' + _PopupButton.prototype.buildCSSClass.call(this) + ' ' + orientationClass; 8143 }; 8144 8145 /** 8146 * Allow sub components to stack CSS class names 8147 * 8148 * @return {Popup} The volume popup button 8149 * @method createPopup 8150 */ 8151 8152 VolumeMenuButton.prototype.createPopup = function createPopup() { 8153 var popup = new _popupPopupJs2['default'](this.player_, { 8154 contentElType: 'div' 8155 }); 8156 8157 var vb = new _volumeControlVolumeBarJs2['default'](this.player_, this.options_.volumeBar); 8158 8159 popup.addChild(vb); 8160 8161 this.menuContent = popup; 8162 this.volumeBar = vb; 8163 8164 this.attachVolumeBarEvents(); 8165 8166 return popup; 8167 }; 8168 8169 /** 8170 * Handle click on volume popup and calls super 8171 * 8172 * @method handleClick 8173 */ 8174 8175 VolumeMenuButton.prototype.handleClick = function handleClick() { 8176 _muteToggleJs2['default'].prototype.handleClick.call(this); 8177 _PopupButton.prototype.handleClick.call(this); 8178 }; 8179 8180 VolumeMenuButton.prototype.attachVolumeBarEvents = function attachVolumeBarEvents() { 8181 this.menuContent.on(['mousedown', 'touchdown'], Fn.bind(this, this.handleMouseDown)); 8182 }; 8183 8184 VolumeMenuButton.prototype.handleMouseDown = function handleMouseDown(event) { 8185 this.on(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove)); 8186 this.on(this.el_.ownerDocument, ['mouseup', 'touchend'], this.handleMouseUp); 8187 }; 8188 8189 VolumeMenuButton.prototype.handleMouseUp = function handleMouseUp(event) { 8190 this.off(['mousemove', 'touchmove'], Fn.bind(this.volumeBar, this.volumeBar.handleMouseMove)); 8191 }; 8192 8193 return VolumeMenuButton; 8194 })(_popupPopupButtonJs2['default']); 8195 8196 VolumeMenuButton.prototype.volumeUpdate = _muteToggleJs2['default'].prototype.update; 8197 VolumeMenuButton.prototype.controlText_ = 'Mute'; 8198 8199 _componentJs2['default'].registerComponent('VolumeMenuButton', VolumeMenuButton); 8200 exports['default'] = VolumeMenuButton; 8201 module.exports = exports['default']; 8202 8203 },{"../component.js":67,"../popup/popup-button.js":112,"../popup/popup.js":113,"../utils/fn.js":136,"./mute-toggle.js":71,"./volume-control/volume-bar.js":96}],100:[function(_dereq_,module,exports){ 8204 /** 8205 * @file error-display.js 8206 */ 8207 'use strict'; 8208 8209 exports.__esModule = true; 8210 8211 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; } } 8212 8213 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8214 8215 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8216 8217 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; } 8218 8219 var _component = _dereq_('./component'); 8220 8221 var _component2 = _interopRequireDefault(_component); 8222 8223 var _modalDialog = _dereq_('./modal-dialog'); 8224 8225 var _modalDialog2 = _interopRequireDefault(_modalDialog); 8226 8227 var _utilsDom = _dereq_('./utils/dom'); 8228 8229 var Dom = _interopRequireWildcard(_utilsDom); 8230 8231 var _utilsMergeOptions = _dereq_('./utils/merge-options'); 8232 8233 var _utilsMergeOptions2 = _interopRequireDefault(_utilsMergeOptions); 8234 8235 /** 8236 * Display that an error has occurred making the video unplayable. 8237 * 8238 * @extends ModalDialog 8239 * @class ErrorDisplay 8240 */ 8241 8242 var ErrorDisplay = (function (_ModalDialog) { 8243 _inherits(ErrorDisplay, _ModalDialog); 8244 8245 /** 8246 * Constructor for error display modal. 8247 * 8248 * @param {Player} player 8249 * @param {Object} [options] 8250 */ 8251 8252 function ErrorDisplay(player, options) { 8253 _classCallCheck(this, ErrorDisplay); 8254 8255 _ModalDialog.call(this, player, options); 8256 this.on(player, 'error', this.open); 8257 } 8258 8259 /** 8260 * Include the old class for backward-compatibility. 8261 * 8262 * This can be removed in 6.0. 8263 * 8264 * @method buildCSSClass 8265 * @deprecated 8266 * @return {String} 8267 */ 8268 8269 ErrorDisplay.prototype.buildCSSClass = function buildCSSClass() { 8270 return 'vjs-error-display ' + _ModalDialog.prototype.buildCSSClass.call(this); 8271 }; 8272 8273 /** 8274 * Generates the modal content based on the player error. 8275 * 8276 * @return {String|Null} 8277 */ 8278 8279 ErrorDisplay.prototype.content = function content() { 8280 var error = this.player().error(); 8281 return error ? this.localize(error.message) : ''; 8282 }; 8283 8284 return ErrorDisplay; 8285 })(_modalDialog2['default']); 8286 8287 ErrorDisplay.prototype.options_ = _utilsMergeOptions2['default'](_modalDialog2['default'].prototype.options_, { 8288 fillAlways: true, 8289 temporary: false, 8290 uncloseable: true 8291 }); 8292 8293 _component2['default'].registerComponent('ErrorDisplay', ErrorDisplay); 8294 exports['default'] = ErrorDisplay; 8295 module.exports = exports['default']; 8296 8297 },{"./component":67,"./modal-dialog":109,"./utils/dom":134,"./utils/merge-options":140}],101:[function(_dereq_,module,exports){ 8298 /** 8299 * @file event-target.js 8300 */ 8301 'use strict'; 8302 8303 exports.__esModule = true; 8304 8305 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; } } 8306 8307 var _utilsEventsJs = _dereq_('./utils/events.js'); 8308 8309 var Events = _interopRequireWildcard(_utilsEventsJs); 8310 8311 var EventTarget = function EventTarget() {}; 8312 8313 EventTarget.prototype.allowedEvents_ = {}; 8314 8315 EventTarget.prototype.on = function (type, fn) { 8316 // Remove the addEventListener alias before calling Events.on 8317 // so we don't get into an infinite type loop 8318 var ael = this.addEventListener; 8319 this.addEventListener = Function.prototype; 8320 Events.on(this, type, fn); 8321 this.addEventListener = ael; 8322 }; 8323 EventTarget.prototype.addEventListener = EventTarget.prototype.on; 8324 8325 EventTarget.prototype.off = function (type, fn) { 8326 Events.off(this, type, fn); 8327 }; 8328 EventTarget.prototype.removeEventListener = EventTarget.prototype.off; 8329 8330 EventTarget.prototype.one = function (type, fn) { 8331 Events.one(this, type, fn); 8332 }; 8333 8334 EventTarget.prototype.trigger = function (event) { 8335 var type = event.type || event; 8336 8337 if (typeof event === 'string') { 8338 event = { 8339 type: type 8340 }; 8341 } 8342 event = Events.fixEvent(event); 8343 8344 if (this.allowedEvents_[type] && this['on' + type]) { 8345 this['on' + type](event); 8346 } 8347 8348 Events.trigger(this, event); 8349 }; 8350 // The standard DOM EventTarget.dispatchEvent() is aliased to trigger() 8351 EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger; 8352 8353 exports['default'] = EventTarget; 8354 module.exports = exports['default']; 8355 8356 },{"./utils/events.js":135}],102:[function(_dereq_,module,exports){ 8357 'use strict'; 8358 8359 exports.__esModule = true; 8360 8361 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8362 8363 var _utilsLog = _dereq_('./utils/log'); 8364 8365 var _utilsLog2 = _interopRequireDefault(_utilsLog); 8366 8367 /* 8368 * @file extend.js 8369 * 8370 * A combination of node inherits and babel's inherits (after transpile). 8371 * Both work the same but node adds `super_` to the subClass 8372 * and Bable adds the superClass as __proto__. Both seem useful. 8373 */ 8374 var _inherits = function _inherits(subClass, superClass) { 8375 if (typeof superClass !== 'function' && superClass !== null) { 8376 throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); 8377 } 8378 8379 subClass.prototype = Object.create(superClass && superClass.prototype, { 8380 constructor: { 8381 value: subClass, 8382 enumerable: false, 8383 writable: true, 8384 configurable: true 8385 } 8386 }); 8387 8388 if (superClass) { 8389 // node 8390 subClass.super_ = superClass; 8391 } 8392 }; 8393 8394 /* 8395 * Function for subclassing using the same inheritance that 8396 * videojs uses internally 8397 * ```js 8398 * var Button = videojs.getComponent('Button'); 8399 * ``` 8400 * ```js 8401 * var MyButton = videojs.extend(Button, { 8402 * constructor: function(player, options) { 8403 * Button.call(this, player, options); 8404 * }, 8405 * onClick: function() { 8406 * // doSomething 8407 * } 8408 * }); 8409 * ``` 8410 */ 8411 var extendFn = function extendFn(superClass) { 8412 var subClassMethods = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 8413 8414 var subClass = function subClass() { 8415 superClass.apply(this, arguments); 8416 }; 8417 var methods = {}; 8418 8419 if (typeof subClassMethods === 'object') { 8420 if (typeof subClassMethods.init === 'function') { 8421 _utilsLog2['default'].warn('Constructor logic via init() is deprecated; please use constructor() instead.'); 8422 subClassMethods.constructor = subClassMethods.init; 8423 } 8424 if (subClassMethods.constructor !== Object.prototype.constructor) { 8425 subClass = subClassMethods.constructor; 8426 } 8427 methods = subClassMethods; 8428 } else if (typeof subClassMethods === 'function') { 8429 subClass = subClassMethods; 8430 } 8431 8432 _inherits(subClass, superClass); 8433 8434 // Extend subObj's prototype with functions and other properties from props 8435 for (var name in methods) { 8436 if (methods.hasOwnProperty(name)) { 8437 subClass.prototype[name] = methods[name]; 8438 } 8439 } 8440 8441 return subClass; 8442 }; 8443 8444 exports['default'] = extendFn; 8445 module.exports = exports['default']; 8446 8447 },{"./utils/log":139}],103:[function(_dereq_,module,exports){ 8448 /** 8449 * @file fullscreen-api.js 8450 */ 8451 'use strict'; 8452 8453 exports.__esModule = true; 8454 8455 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8456 8457 var _globalDocument = _dereq_('global/document'); 8458 8459 var _globalDocument2 = _interopRequireDefault(_globalDocument); 8460 8461 /* 8462 * Store the browser-specific methods for the fullscreen API 8463 * @type {Object|undefined} 8464 * @private 8465 */ 8466 var FullscreenApi = {}; 8467 8468 // browser API methods 8469 // map approach from Screenful.js - https://github.com/sindresorhus/screenfull.js 8470 var apiMap = [ 8471 // Spec: https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html 8472 ['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'], 8473 // WebKit 8474 ['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror'], 8475 // Old WebKit (Safari 5.1) 8476 ['webkitRequestFullScreen', 'webkitCancelFullScreen', 'webkitCurrentFullScreenElement', 'webkitCancelFullScreen', 'webkitfullscreenchange', 'webkitfullscreenerror'], 8477 // Mozilla 8478 ['mozRequestFullScreen', 'mozCancelFullScreen', 'mozFullScreenElement', 'mozFullScreenEnabled', 'mozfullscreenchange', 'mozfullscreenerror'], 8479 // Microsoft 8480 ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError']]; 8481 8482 var specApi = apiMap[0]; 8483 var browserApi = undefined; 8484 8485 // determine the supported set of functions 8486 for (var i = 0; i < apiMap.length; i++) { 8487 // check for exitFullscreen function 8488 if (apiMap[i][1] in _globalDocument2['default']) { 8489 browserApi = apiMap[i]; 8490 break; 8491 } 8492 } 8493 8494 // map the browser API names to the spec API names 8495 if (browserApi) { 8496 for (var i = 0; i < browserApi.length; i++) { 8497 FullscreenApi[specApi[i]] = browserApi[i]; 8498 } 8499 } 8500 8501 exports['default'] = FullscreenApi; 8502 module.exports = exports['default']; 8503 8504 },{"global/document":1}],104:[function(_dereq_,module,exports){ 8505 /** 8506 * @file loading-spinner.js 8507 */ 8508 'use strict'; 8509 8510 exports.__esModule = true; 8511 8512 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8513 8514 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8515 8516 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; } 8517 8518 var _component = _dereq_('./component'); 8519 8520 var _component2 = _interopRequireDefault(_component); 8521 8522 /* Loading Spinner 8523 ================================================================================ */ 8524 /** 8525 * Loading spinner for waiting events 8526 * 8527 * @extends Component 8528 * @class LoadingSpinner 8529 */ 8530 8531 var LoadingSpinner = (function (_Component) { 8532 _inherits(LoadingSpinner, _Component); 8533 8534 function LoadingSpinner() { 8535 _classCallCheck(this, LoadingSpinner); 8536 8537 _Component.apply(this, arguments); 8538 } 8539 8540 /** 8541 * Create the component's DOM element 8542 * 8543 * @method createEl 8544 */ 8545 8546 LoadingSpinner.prototype.createEl = function createEl() { 8547 return _Component.prototype.createEl.call(this, 'div', { 8548 className: 'vjs-loading-spinner', 8549 dir: 'ltr' 8550 }); 8551 }; 8552 8553 return LoadingSpinner; 8554 })(_component2['default']); 8555 8556 _component2['default'].registerComponent('LoadingSpinner', LoadingSpinner); 8557 exports['default'] = LoadingSpinner; 8558 module.exports = exports['default']; 8559 8560 },{"./component":67}],105:[function(_dereq_,module,exports){ 8561 /** 8562 * @file media-error.js 8563 */ 8564 'use strict'; 8565 8566 exports.__esModule = true; 8567 8568 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8569 8570 var _objectAssign = _dereq_('object.assign'); 8571 8572 var _objectAssign2 = _interopRequireDefault(_objectAssign); 8573 8574 /* 8575 * Custom MediaError to mimic the HTML5 MediaError 8576 * 8577 * @param {Number} code The media error code 8578 */ 8579 var MediaError = function MediaError(code) { 8580 if (typeof code === 'number') { 8581 this.code = code; 8582 } else if (typeof code === 'string') { 8583 // default code is zero, so this is a custom error 8584 this.message = code; 8585 } else if (typeof code === 'object') { 8586 // object 8587 _objectAssign2['default'](this, code); 8588 } 8589 8590 if (!this.message) { 8591 this.message = MediaError.defaultMessages[this.code] || ''; 8592 } 8593 }; 8594 8595 /* 8596 * The error code that refers two one of the defined 8597 * MediaError types 8598 * 8599 * @type {Number} 8600 */ 8601 MediaError.prototype.code = 0; 8602 8603 /* 8604 * An optional message to be shown with the error. 8605 * Message is not part of the HTML5 video spec 8606 * but allows for more informative custom errors. 8607 * 8608 * @type {String} 8609 */ 8610 MediaError.prototype.message = ''; 8611 8612 /* 8613 * An optional status code that can be set by plugins 8614 * to allow even more detail about the error. 8615 * For example the HLS plugin might provide the specific 8616 * HTTP status code that was returned when the error 8617 * occurred, then allowing a custom error overlay 8618 * to display more information. 8619 * 8620 * @type {Array} 8621 */ 8622 MediaError.prototype.status = null; 8623 8624 MediaError.errorTypes = ['MEDIA_ERR_CUSTOM', // = 0 8625 'MEDIA_ERR_ABORTED', // = 1 8626 'MEDIA_ERR_NETWORK', // = 2 8627 'MEDIA_ERR_DECODE', // = 3 8628 'MEDIA_ERR_SRC_NOT_SUPPORTED', // = 4 8629 'MEDIA_ERR_ENCRYPTED' // = 5 8630 ]; 8631 8632 MediaError.defaultMessages = { 8633 1: 'You aborted the media playback', 8634 2: 'A network error caused the media download to fail part-way.', 8635 3: 'The media playback was aborted due to a corruption problem or because the media used features your browser did not support.', 8636 4: 'The media could not be loaded, either because the server or network failed or because the format is not supported.', 8637 5: 'The media is encrypted and we do not have the keys to decrypt it.' 8638 }; 8639 8640 // Add types as properties on MediaError 8641 // e.g. MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED = 4; 8642 for (var errNum = 0; errNum < MediaError.errorTypes.length; errNum++) { 8643 MediaError[MediaError.errorTypes[errNum]] = errNum; 8644 // values should be accessible on both the class and instance 8645 MediaError.prototype[MediaError.errorTypes[errNum]] = errNum; 8646 } 8647 8648 exports['default'] = MediaError; 8649 module.exports = exports['default']; 8650 8651 },{"object.assign":45}],106:[function(_dereq_,module,exports){ 8652 /** 8653 * @file menu-button.js 8654 */ 8655 'use strict'; 8656 8657 exports.__esModule = true; 8658 8659 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; } } 8660 8661 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8662 8663 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8664 8665 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; } 8666 8667 var _clickableComponentJs = _dereq_('../clickable-component.js'); 8668 8669 var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs); 8670 8671 var _componentJs = _dereq_('../component.js'); 8672 8673 var _componentJs2 = _interopRequireDefault(_componentJs); 8674 8675 var _menuJs = _dereq_('./menu.js'); 8676 8677 var _menuJs2 = _interopRequireDefault(_menuJs); 8678 8679 var _utilsDomJs = _dereq_('../utils/dom.js'); 8680 8681 var Dom = _interopRequireWildcard(_utilsDomJs); 8682 8683 var _utilsFnJs = _dereq_('../utils/fn.js'); 8684 8685 var Fn = _interopRequireWildcard(_utilsFnJs); 8686 8687 var _utilsToTitleCaseJs = _dereq_('../utils/to-title-case.js'); 8688 8689 var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs); 8690 8691 /** 8692 * A button class with a popup menu 8693 * 8694 * @param {Player|Object} player 8695 * @param {Object=} options 8696 * @extends Button 8697 * @class MenuButton 8698 */ 8699 8700 var MenuButton = (function (_ClickableComponent) { 8701 _inherits(MenuButton, _ClickableComponent); 8702 8703 function MenuButton(player) { 8704 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 8705 8706 _classCallCheck(this, MenuButton); 8707 8708 _ClickableComponent.call(this, player, options); 8709 8710 this.update(); 8711 8712 this.enabled_ = true; 8713 8714 this.el_.setAttribute('aria-haspopup', 'true'); 8715 this.el_.setAttribute('role', 'menuitem'); 8716 this.on('keydown', this.handleSubmenuKeyPress); 8717 } 8718 8719 /** 8720 * Update menu 8721 * 8722 * @method update 8723 */ 8724 8725 MenuButton.prototype.update = function update() { 8726 var menu = this.createMenu(); 8727 8728 if (this.menu) { 8729 this.removeChild(this.menu); 8730 } 8731 8732 this.menu = menu; 8733 this.addChild(menu); 8734 8735 /** 8736 * Track the state of the menu button 8737 * 8738 * @type {Boolean} 8739 * @private 8740 */ 8741 this.buttonPressed_ = false; 8742 this.el_.setAttribute('aria-expanded', 'false'); 8743 8744 if (this.items && this.items.length === 0) { 8745 this.hide(); 8746 } else if (this.items && this.items.length > 1) { 8747 this.show(); 8748 } 8749 }; 8750 8751 /** 8752 * Create menu 8753 * 8754 * @return {Menu} The constructed menu 8755 * @method createMenu 8756 */ 8757 8758 MenuButton.prototype.createMenu = function createMenu() { 8759 var menu = new _menuJs2['default'](this.player_); 8760 8761 // Add a title list item to the top 8762 if (this.options_.title) { 8763 var title = Dom.createEl('li', { 8764 className: 'vjs-menu-title', 8765 innerHTML: _utilsToTitleCaseJs2['default'](this.options_.title), 8766 tabIndex: -1 8767 }); 8768 menu.children_.unshift(title); 8769 Dom.insertElFirst(title, menu.contentEl()); 8770 } 8771 8772 this.items = this['createItems'](); 8773 8774 if (this.items) { 8775 // Add menu items to the menu 8776 for (var i = 0; i < this.items.length; i++) { 8777 menu.addItem(this.items[i]); 8778 } 8779 } 8780 8781 return menu; 8782 }; 8783 8784 /** 8785 * Create the list of menu items. Specific to each subclass. 8786 * 8787 * @method createItems 8788 */ 8789 8790 MenuButton.prototype.createItems = function createItems() {}; 8791 8792 /** 8793 * Create the component's DOM element 8794 * 8795 * @return {Element} 8796 * @method createEl 8797 */ 8798 8799 MenuButton.prototype.createEl = function createEl() { 8800 return _ClickableComponent.prototype.createEl.call(this, 'div', { 8801 className: this.buildCSSClass() 8802 }); 8803 }; 8804 8805 /** 8806 * Allow sub components to stack CSS class names 8807 * 8808 * @return {String} The constructed class name 8809 * @method buildCSSClass 8810 */ 8811 8812 MenuButton.prototype.buildCSSClass = function buildCSSClass() { 8813 var menuButtonClass = 'vjs-menu-button'; 8814 8815 // If the inline option is passed, we want to use different styles altogether. 8816 if (this.options_.inline === true) { 8817 menuButtonClass += '-inline'; 8818 } else { 8819 menuButtonClass += '-popup'; 8820 } 8821 8822 return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this); 8823 }; 8824 8825 /** 8826 * When you click the button it adds focus, which 8827 * will show the menu indefinitely. 8828 * So we'll remove focus when the mouse leaves the button. 8829 * Focus is needed for tab navigation. 8830 * Allow sub components to stack CSS class names 8831 * 8832 * @method handleClick 8833 */ 8834 8835 MenuButton.prototype.handleClick = function handleClick() { 8836 this.one('mouseout', Fn.bind(this, function () { 8837 this.menu.unlockShowing(); 8838 this.el_.blur(); 8839 })); 8840 if (this.buttonPressed_) { 8841 this.unpressButton(); 8842 } else { 8843 this.pressButton(); 8844 } 8845 }; 8846 8847 /** 8848 * Handle key press on menu 8849 * 8850 * @param {Object} event Key press event 8851 * @method handleKeyPress 8852 */ 8853 8854 MenuButton.prototype.handleKeyPress = function handleKeyPress(event) { 8855 8856 // Escape (27) key or Tab (9) key unpress the 'button' 8857 if (event.which === 27 || event.which === 9) { 8858 if (this.buttonPressed_) { 8859 this.unpressButton(); 8860 } 8861 // Don't preventDefault for Tab key - we still want to lose focus 8862 if (event.which !== 9) { 8863 event.preventDefault(); 8864 } 8865 // Up (38) key or Down (40) key press the 'button' 8866 } else if (event.which === 38 || event.which === 40) { 8867 if (!this.buttonPressed_) { 8868 this.pressButton(); 8869 event.preventDefault(); 8870 } 8871 } else { 8872 _ClickableComponent.prototype.handleKeyPress.call(this, event); 8873 } 8874 }; 8875 8876 /** 8877 * Handle key press on submenu 8878 * 8879 * @param {Object} event Key press event 8880 * @method handleSubmenuKeyPress 8881 */ 8882 8883 MenuButton.prototype.handleSubmenuKeyPress = function handleSubmenuKeyPress(event) { 8884 8885 // Escape (27) key or Tab (9) key unpress the 'button' 8886 if (event.which === 27 || event.which === 9) { 8887 if (this.buttonPressed_) { 8888 this.unpressButton(); 8889 } 8890 // Don't preventDefault for Tab key - we still want to lose focus 8891 if (event.which !== 9) { 8892 event.preventDefault(); 8893 } 8894 } 8895 }; 8896 8897 /** 8898 * Makes changes based on button pressed 8899 * 8900 * @method pressButton 8901 */ 8902 8903 MenuButton.prototype.pressButton = function pressButton() { 8904 if (this.enabled_) { 8905 this.buttonPressed_ = true; 8906 this.menu.lockShowing(); 8907 this.el_.setAttribute('aria-expanded', 'true'); 8908 this.menu.focus(); // set the focus into the submenu 8909 } 8910 }; 8911 8912 /** 8913 * Makes changes based on button unpressed 8914 * 8915 * @method unpressButton 8916 */ 8917 8918 MenuButton.prototype.unpressButton = function unpressButton() { 8919 if (this.enabled_) { 8920 this.buttonPressed_ = false; 8921 this.menu.unlockShowing(); 8922 this.el_.setAttribute('aria-expanded', 'false'); 8923 this.el_.focus(); // Set focus back to this menu button 8924 } 8925 }; 8926 8927 /** 8928 * Disable the menu button 8929 * 8930 * @return {Component} 8931 * @method disable 8932 */ 8933 8934 MenuButton.prototype.disable = function disable() { 8935 // Unpress, but don't force focus on this button 8936 this.buttonPressed_ = false; 8937 this.menu.unlockShowing(); 8938 this.el_.setAttribute('aria-expanded', 'false'); 8939 8940 this.enabled_ = false; 8941 8942 return _ClickableComponent.prototype.disable.call(this); 8943 }; 8944 8945 /** 8946 * Enable the menu button 8947 * 8948 * @return {Component} 8949 * @method disable 8950 */ 8951 8952 MenuButton.prototype.enable = function enable() { 8953 this.enabled_ = true; 8954 8955 return _ClickableComponent.prototype.enable.call(this); 8956 }; 8957 8958 return MenuButton; 8959 })(_clickableComponentJs2['default']); 8960 8961 _componentJs2['default'].registerComponent('MenuButton', MenuButton); 8962 exports['default'] = MenuButton; 8963 module.exports = exports['default']; 8964 8965 },{"../clickable-component.js":65,"../component.js":67,"../utils/dom.js":134,"../utils/fn.js":136,"../utils/to-title-case.js":143,"./menu.js":108}],107:[function(_dereq_,module,exports){ 8966 /** 8967 * @file menu-item.js 8968 */ 8969 'use strict'; 8970 8971 exports.__esModule = true; 8972 8973 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8974 8975 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 8976 8977 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; } 8978 8979 var _clickableComponentJs = _dereq_('../clickable-component.js'); 8980 8981 var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs); 8982 8983 var _componentJs = _dereq_('../component.js'); 8984 8985 var _componentJs2 = _interopRequireDefault(_componentJs); 8986 8987 var _objectAssign = _dereq_('object.assign'); 8988 8989 var _objectAssign2 = _interopRequireDefault(_objectAssign); 8990 8991 /** 8992 * The component for a menu item. `<li>` 8993 * 8994 * @param {Player|Object} player 8995 * @param {Object=} options 8996 * @extends Button 8997 * @class MenuItem 8998 */ 8999 9000 var MenuItem = (function (_ClickableComponent) { 9001 _inherits(MenuItem, _ClickableComponent); 9002 9003 function MenuItem(player, options) { 9004 _classCallCheck(this, MenuItem); 9005 9006 _ClickableComponent.call(this, player, options); 9007 9008 this.selectable = options['selectable']; 9009 9010 this.selected(options['selected']); 9011 9012 if (this.selectable) { 9013 // TODO: May need to be either menuitemcheckbox or menuitemradio, 9014 // and may need logical grouping of menu items. 9015 this.el_.setAttribute('role', 'menuitemcheckbox'); 9016 } else { 9017 this.el_.setAttribute('role', 'menuitem'); 9018 } 9019 } 9020 9021 /** 9022 * Create the component's DOM element 9023 * 9024 * @param {String=} type Desc 9025 * @param {Object=} props Desc 9026 * @return {Element} 9027 * @method createEl 9028 */ 9029 9030 MenuItem.prototype.createEl = function createEl(type, props, attrs) { 9031 return _ClickableComponent.prototype.createEl.call(this, 'li', _objectAssign2['default']({ 9032 className: 'vjs-menu-item', 9033 innerHTML: this.localize(this.options_['label']), 9034 tabIndex: -1 9035 }, props), attrs); 9036 }; 9037 9038 /** 9039 * Handle a click on the menu item, and set it to selected 9040 * 9041 * @method handleClick 9042 */ 9043 9044 MenuItem.prototype.handleClick = function handleClick() { 9045 this.selected(true); 9046 }; 9047 9048 /** 9049 * Set this menu item as selected or not 9050 * 9051 * @param {Boolean} selected 9052 * @method selected 9053 */ 9054 9055 MenuItem.prototype.selected = function selected(_selected) { 9056 if (this.selectable) { 9057 if (_selected) { 9058 this.addClass('vjs-selected'); 9059 this.el_.setAttribute('aria-checked', 'true'); 9060 // aria-checked isn't fully supported by browsers/screen readers, 9061 // so indicate selected state to screen reader in the control text. 9062 this.controlText(', selected'); 9063 } else { 9064 this.removeClass('vjs-selected'); 9065 this.el_.setAttribute('aria-checked', 'false'); 9066 // Indicate un-selected state to screen reader 9067 // Note that a space clears out the selected state text 9068 this.controlText(' '); 9069 } 9070 } 9071 }; 9072 9073 return MenuItem; 9074 })(_clickableComponentJs2['default']); 9075 9076 _componentJs2['default'].registerComponent('MenuItem', MenuItem); 9077 exports['default'] = MenuItem; 9078 module.exports = exports['default']; 9079 9080 },{"../clickable-component.js":65,"../component.js":67,"object.assign":45}],108:[function(_dereq_,module,exports){ 9081 /** 9082 * @file menu.js 9083 */ 9084 'use strict'; 9085 9086 exports.__esModule = true; 9087 9088 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; } } 9089 9090 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 9091 9092 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9093 9094 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; } 9095 9096 var _componentJs = _dereq_('../component.js'); 9097 9098 var _componentJs2 = _interopRequireDefault(_componentJs); 9099 9100 var _utilsDomJs = _dereq_('../utils/dom.js'); 9101 9102 var Dom = _interopRequireWildcard(_utilsDomJs); 9103 9104 var _utilsFnJs = _dereq_('../utils/fn.js'); 9105 9106 var Fn = _interopRequireWildcard(_utilsFnJs); 9107 9108 var _utilsEventsJs = _dereq_('../utils/events.js'); 9109 9110 var Events = _interopRequireWildcard(_utilsEventsJs); 9111 9112 /** 9113 * The Menu component is used to build pop up menus, including subtitle and 9114 * captions selection menus. 9115 * 9116 * @extends Component 9117 * @class Menu 9118 */ 9119 9120 var Menu = (function (_Component) { 9121 _inherits(Menu, _Component); 9122 9123 function Menu(player, options) { 9124 _classCallCheck(this, Menu); 9125 9126 _Component.call(this, player, options); 9127 9128 this.focusedChild_ = -1; 9129 9130 this.on('keydown', this.handleKeyPress); 9131 } 9132 9133 /** 9134 * Add a menu item to the menu 9135 * 9136 * @param {Object|String} component Component or component type to add 9137 * @method addItem 9138 */ 9139 9140 Menu.prototype.addItem = function addItem(component) { 9141 this.addChild(component); 9142 component.on('click', Fn.bind(this, function () { 9143 this.unlockShowing(); 9144 //TODO: Need to set keyboard focus back to the menuButton 9145 })); 9146 }; 9147 9148 /** 9149 * Create the component's DOM element 9150 * 9151 * @return {Element} 9152 * @method createEl 9153 */ 9154 9155 Menu.prototype.createEl = function createEl() { 9156 var contentElType = this.options_.contentElType || 'ul'; 9157 this.contentEl_ = Dom.createEl(contentElType, { 9158 className: 'vjs-menu-content' 9159 }); 9160 this.contentEl_.setAttribute('role', 'menu'); 9161 var el = _Component.prototype.createEl.call(this, 'div', { 9162 append: this.contentEl_, 9163 className: 'vjs-menu' 9164 }); 9165 el.setAttribute('role', 'presentation'); 9166 el.appendChild(this.contentEl_); 9167 9168 // Prevent clicks from bubbling up. Needed for Menu Buttons, 9169 // where a click on the parent is significant 9170 Events.on(el, 'click', function (event) { 9171 event.preventDefault(); 9172 event.stopImmediatePropagation(); 9173 }); 9174 9175 return el; 9176 }; 9177 9178 /** 9179 * Handle key press for menu 9180 * 9181 * @param {Object} event Event object 9182 * @method handleKeyPress 9183 */ 9184 9185 Menu.prototype.handleKeyPress = function handleKeyPress(event) { 9186 if (event.which === 37 || event.which === 40) { 9187 // Left and Down Arrows 9188 event.preventDefault(); 9189 this.stepForward(); 9190 } else if (event.which === 38 || event.which === 39) { 9191 // Up and Right Arrows 9192 event.preventDefault(); 9193 this.stepBack(); 9194 } 9195 }; 9196 9197 /** 9198 * Move to next (lower) menu item for keyboard users 9199 * 9200 * @method stepForward 9201 */ 9202 9203 Menu.prototype.stepForward = function stepForward() { 9204 var stepChild = 0; 9205 9206 if (this.focusedChild_ !== undefined) { 9207 stepChild = this.focusedChild_ + 1; 9208 } 9209 this.focus(stepChild); 9210 }; 9211 9212 /** 9213 * Move to previous (higher) menu item for keyboard users 9214 * 9215 * @method stepBack 9216 */ 9217 9218 Menu.prototype.stepBack = function stepBack() { 9219 var stepChild = 0; 9220 9221 if (this.focusedChild_ !== undefined) { 9222 stepChild = this.focusedChild_ - 1; 9223 } 9224 this.focus(stepChild); 9225 }; 9226 9227 /** 9228 * Set focus on a menu item in the menu 9229 * 9230 * @param {Object|String} item Index of child item set focus on 9231 * @method focus 9232 */ 9233 9234 Menu.prototype.focus = function focus() { 9235 var item = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0]; 9236 9237 var children = this.children().slice(); 9238 var haveTitle = children.length && children[0].className && /vjs-menu-title/.test(children[0].className); 9239 9240 if (haveTitle) { 9241 children.shift(); 9242 } 9243 9244 if (children.length > 0) { 9245 if (item < 0) { 9246 item = 0; 9247 } else if (item >= children.length) { 9248 item = children.length - 1; 9249 } 9250 9251 this.focusedChild_ = item; 9252 9253 children[item].el_.focus(); 9254 } 9255 }; 9256 9257 return Menu; 9258 })(_componentJs2['default']); 9259 9260 _componentJs2['default'].registerComponent('Menu', Menu); 9261 exports['default'] = Menu; 9262 module.exports = exports['default']; 9263 9264 },{"../component.js":67,"../utils/dom.js":134,"../utils/events.js":135,"../utils/fn.js":136}],109:[function(_dereq_,module,exports){ 9265 /** 9266 * @file modal-dialog.js 9267 */ 9268 'use strict'; 9269 9270 exports.__esModule = true; 9271 9272 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 9273 9274 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; } } 9275 9276 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9277 9278 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; } 9279 9280 var _utilsDom = _dereq_('./utils/dom'); 9281 9282 var Dom = _interopRequireWildcard(_utilsDom); 9283 9284 var _utilsFn = _dereq_('./utils/fn'); 9285 9286 var Fn = _interopRequireWildcard(_utilsFn); 9287 9288 var _utilsLog = _dereq_('./utils/log'); 9289 9290 var _utilsLog2 = _interopRequireDefault(_utilsLog); 9291 9292 var _component = _dereq_('./component'); 9293 9294 var _component2 = _interopRequireDefault(_component); 9295 9296 var _closeButton = _dereq_('./close-button'); 9297 9298 var _closeButton2 = _interopRequireDefault(_closeButton); 9299 9300 var MODAL_CLASS_NAME = 'vjs-modal-dialog'; 9301 var ESC = 27; 9302 9303 /** 9304 * The `ModalDialog` displays over the video and its controls, which blocks 9305 * interaction with the player until it is closed. 9306 * 9307 * Modal dialogs include a "Close" button and will close when that button 9308 * is activated - or when ESC is pressed anywhere. 9309 * 9310 * @extends Component 9311 * @class ModalDialog 9312 */ 9313 9314 var ModalDialog = (function (_Component) { 9315 _inherits(ModalDialog, _Component); 9316 9317 /** 9318 * Constructor for modals. 9319 * 9320 * @param {Player} player 9321 * @param {Object} [options] 9322 * @param {Mixed} [options.content=undefined] 9323 * Provide customized content for this modal. 9324 * 9325 * @param {String} [options.description] 9326 * A text description for the modal, primarily for accessibility. 9327 * 9328 * @param {Boolean} [options.fillAlways=false] 9329 * Normally, modals are automatically filled only the first time 9330 * they open. This tells the modal to refresh its content 9331 * every time it opens. 9332 * 9333 * @param {String} [options.label] 9334 * A text label for the modal, primarily for accessibility. 9335 * 9336 * @param {Boolean} [options.temporary=true] 9337 * If `true`, the modal can only be opened once; it will be 9338 * disposed as soon as it's closed. 9339 * 9340 * @param {Boolean} [options.uncloseable=false] 9341 * If `true`, the user will not be able to close the modal 9342 * through the UI in the normal ways. Programmatic closing is 9343 * still possible. 9344 * 9345 */ 9346 9347 function ModalDialog(player, options) { 9348 _classCallCheck(this, ModalDialog); 9349 9350 _Component.call(this, player, options); 9351 this.opened_ = this.hasBeenOpened_ = this.hasBeenFilled_ = false; 9352 9353 this.closeable(!this.options_.uncloseable); 9354 this.content(this.options_.content); 9355 9356 // Make sure the contentEl is defined AFTER any children are initialized 9357 // because we only want the contents of the modal in the contentEl 9358 // (not the UI elements like the close button). 9359 this.contentEl_ = Dom.createEl('div', { 9360 className: MODAL_CLASS_NAME + '-content' 9361 }, { 9362 role: 'document' 9363 }); 9364 9365 this.descEl_ = Dom.createEl('p', { 9366 className: MODAL_CLASS_NAME + '-description vjs-offscreen', 9367 id: this.el().getAttribute('aria-describedby') 9368 }); 9369 9370 Dom.textContent(this.descEl_, this.description()); 9371 this.el_.appendChild(this.descEl_); 9372 this.el_.appendChild(this.contentEl_); 9373 } 9374 9375 /* 9376 * Modal dialog default options. 9377 * 9378 * @type {Object} 9379 * @private 9380 */ 9381 9382 /** 9383 * Create the modal's DOM element 9384 * 9385 * @method createEl 9386 * @return {Element} 9387 */ 9388 9389 ModalDialog.prototype.createEl = function createEl() { 9390 return _Component.prototype.createEl.call(this, 'div', { 9391 className: this.buildCSSClass(), 9392 tabIndex: -1 9393 }, { 9394 'aria-describedby': this.id() + '_description', 9395 'aria-hidden': 'true', 9396 'aria-label': this.label(), 9397 role: 'dialog' 9398 }); 9399 }; 9400 9401 /** 9402 * Build the modal's CSS class. 9403 * 9404 * @method buildCSSClass 9405 * @return {String} 9406 */ 9407 9408 ModalDialog.prototype.buildCSSClass = function buildCSSClass() { 9409 return MODAL_CLASS_NAME + ' vjs-hidden ' + _Component.prototype.buildCSSClass.call(this); 9410 }; 9411 9412 /** 9413 * Handles key presses on the document, looking for ESC, which closes 9414 * the modal. 9415 * 9416 * @method handleKeyPress 9417 * @param {Event} e 9418 */ 9419 9420 ModalDialog.prototype.handleKeyPress = function handleKeyPress(e) { 9421 if (e.which === ESC && this.closeable()) { 9422 this.close(); 9423 } 9424 }; 9425 9426 /** 9427 * Returns the label string for this modal. Primarily used for accessibility. 9428 * 9429 * @return {String} 9430 */ 9431 9432 ModalDialog.prototype.label = function label() { 9433 return this.options_.label || this.localize('Modal Window'); 9434 }; 9435 9436 /** 9437 * Returns the description string for this modal. Primarily used for 9438 * accessibility. 9439 * 9440 * @return {String} 9441 */ 9442 9443 ModalDialog.prototype.description = function description() { 9444 var desc = this.options_.description || this.localize('This is a modal window.'); 9445 9446 // Append a universal closeability message if the modal is closeable. 9447 if (this.closeable()) { 9448 desc += ' ' + this.localize('This modal can be closed by pressing the Escape key or activating the close button.'); 9449 } 9450 9451 return desc; 9452 }; 9453 9454 /** 9455 * Opens the modal. 9456 * 9457 * @method open 9458 * @return {ModalDialog} 9459 */ 9460 9461 ModalDialog.prototype.open = function open() { 9462 if (!this.opened_) { 9463 var player = this.player(); 9464 9465 this.trigger('beforemodalopen'); 9466 this.opened_ = true; 9467 9468 // Fill content if the modal has never opened before and 9469 // never been filled. 9470 if (this.options_.fillAlways || !this.hasBeenOpened_ && !this.hasBeenFilled_) { 9471 this.fill(); 9472 } 9473 9474 // If the player was playing, pause it and take note of its previously 9475 // playing state. 9476 this.wasPlaying_ = !player.paused(); 9477 9478 if (this.wasPlaying_) { 9479 player.pause(); 9480 } 9481 9482 if (this.closeable()) { 9483 this.on(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress)); 9484 } 9485 9486 player.controls(false); 9487 this.show(); 9488 this.el().setAttribute('aria-hidden', 'false'); 9489 this.trigger('modalopen'); 9490 this.hasBeenOpened_ = true; 9491 } 9492 return this; 9493 }; 9494 9495 /** 9496 * Whether or not the modal is opened currently. 9497 * 9498 * @method opened 9499 * @param {Boolean} [value] 9500 * If given, it will open (`true`) or close (`false`) the modal. 9501 * 9502 * @return {Boolean} 9503 */ 9504 9505 ModalDialog.prototype.opened = function opened(value) { 9506 if (typeof value === 'boolean') { 9507 this[value ? 'open' : 'close'](); 9508 } 9509 return this.opened_; 9510 }; 9511 9512 /** 9513 * Closes the modal. 9514 * 9515 * @method close 9516 * @return {ModalDialog} 9517 */ 9518 9519 ModalDialog.prototype.close = function close() { 9520 if (this.opened_) { 9521 var player = this.player(); 9522 9523 this.trigger('beforemodalclose'); 9524 this.opened_ = false; 9525 9526 if (this.wasPlaying_) { 9527 player.play(); 9528 } 9529 9530 if (this.closeable()) { 9531 this.off(this.el_.ownerDocument, 'keydown', Fn.bind(this, this.handleKeyPress)); 9532 } 9533 9534 player.controls(true); 9535 this.hide(); 9536 this.el().setAttribute('aria-hidden', 'true'); 9537 this.trigger('modalclose'); 9538 9539 if (this.options_.temporary) { 9540 this.dispose(); 9541 } 9542 } 9543 return this; 9544 }; 9545 9546 /** 9547 * Whether or not the modal is closeable via the UI. 9548 * 9549 * @method closeable 9550 * @param {Boolean} [value] 9551 * If given as a Boolean, it will set the `closeable` option. 9552 * 9553 * @return {Boolean} 9554 */ 9555 9556 ModalDialog.prototype.closeable = function closeable(value) { 9557 if (typeof value === 'boolean') { 9558 var closeable = this.closeable_ = !!value; 9559 var _close = this.getChild('closeButton'); 9560 9561 // If this is being made closeable and has no close button, add one. 9562 if (closeable && !_close) { 9563 9564 // The close button should be a child of the modal - not its 9565 // content element, so temporarily change the content element. 9566 var temp = this.contentEl_; 9567 this.contentEl_ = this.el_; 9568 _close = this.addChild('closeButton'); 9569 this.contentEl_ = temp; 9570 this.on(_close, 'close', this.close); 9571 } 9572 9573 // If this is being made uncloseable and has a close button, remove it. 9574 if (!closeable && _close) { 9575 this.off(_close, 'close', this.close); 9576 this.removeChild(_close); 9577 _close.dispose(); 9578 } 9579 } 9580 return this.closeable_; 9581 }; 9582 9583 /** 9584 * Fill the modal's content element with the modal's "content" option. 9585 * 9586 * The content element will be emptied before this change takes place. 9587 * 9588 * @method fill 9589 * @return {ModalDialog} 9590 */ 9591 9592 ModalDialog.prototype.fill = function fill() { 9593 return this.fillWith(this.content()); 9594 }; 9595 9596 /** 9597 * Fill the modal's content element with arbitrary content. 9598 * 9599 * The content element will be emptied before this change takes place. 9600 * 9601 * @method fillWith 9602 * @param {Mixed} [content] 9603 * The same rules apply to this as apply to the `content` option. 9604 * 9605 * @return {ModalDialog} 9606 */ 9607 9608 ModalDialog.prototype.fillWith = function fillWith(content) { 9609 var contentEl = this.contentEl(); 9610 var parentEl = contentEl.parentNode; 9611 var nextSiblingEl = contentEl.nextSibling; 9612 9613 this.trigger('beforemodalfill'); 9614 this.hasBeenFilled_ = true; 9615 9616 // Detach the content element from the DOM before performing 9617 // manipulation to avoid modifying the live DOM multiple times. 9618 parentEl.removeChild(contentEl); 9619 this.empty(); 9620 Dom.insertContent(contentEl, content); 9621 this.trigger('modalfill'); 9622 9623 // Re-inject the re-filled content element. 9624 if (nextSiblingEl) { 9625 parentEl.insertBefore(contentEl, nextSiblingEl); 9626 } else { 9627 parentEl.appendChild(contentEl); 9628 } 9629 9630 return this; 9631 }; 9632 9633 /** 9634 * Empties the content element. 9635 * 9636 * This happens automatically anytime the modal is filled. 9637 * 9638 * @method empty 9639 * @return {ModalDialog} 9640 */ 9641 9642 ModalDialog.prototype.empty = function empty() { 9643 this.trigger('beforemodalempty'); 9644 Dom.emptyEl(this.contentEl()); 9645 this.trigger('modalempty'); 9646 return this; 9647 }; 9648 9649 /** 9650 * Gets or sets the modal content, which gets normalized before being 9651 * rendered into the DOM. 9652 * 9653 * This does not update the DOM or fill the modal, but it is called during 9654 * that process. 9655 * 9656 * @method content 9657 * @param {Mixed} [value] 9658 * If defined, sets the internal content value to be used on the 9659 * next call(s) to `fill`. This value is normalized before being 9660 * inserted. To "clear" the internal content value, pass `null`. 9661 * 9662 * @return {Mixed} 9663 */ 9664 9665 ModalDialog.prototype.content = function content(value) { 9666 if (typeof value !== 'undefined') { 9667 this.content_ = value; 9668 } 9669 return this.content_; 9670 }; 9671 9672 return ModalDialog; 9673 })(_component2['default']); 9674 9675 ModalDialog.prototype.options_ = { 9676 temporary: true 9677 }; 9678 9679 _component2['default'].registerComponent('ModalDialog', ModalDialog); 9680 exports['default'] = ModalDialog; 9681 module.exports = exports['default']; 9682 9683 },{"./close-button":66,"./component":67,"./utils/dom":134,"./utils/fn":136,"./utils/log":139}],110:[function(_dereq_,module,exports){ 9684 /** 9685 * @file player.js 9686 */ 9687 // Subclasses Component 9688 'use strict'; 9689 9690 exports.__esModule = true; 9691 9692 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; } } 9693 9694 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 9695 9696 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 9697 9698 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; } 9699 9700 var _componentJs = _dereq_('./component.js'); 9701 9702 var _componentJs2 = _interopRequireDefault(_componentJs); 9703 9704 var _globalDocument = _dereq_('global/document'); 9705 9706 var _globalDocument2 = _interopRequireDefault(_globalDocument); 9707 9708 var _globalWindow = _dereq_('global/window'); 9709 9710 var _globalWindow2 = _interopRequireDefault(_globalWindow); 9711 9712 var _utilsEventsJs = _dereq_('./utils/events.js'); 9713 9714 var Events = _interopRequireWildcard(_utilsEventsJs); 9715 9716 var _utilsDomJs = _dereq_('./utils/dom.js'); 9717 9718 var Dom = _interopRequireWildcard(_utilsDomJs); 9719 9720 var _utilsFnJs = _dereq_('./utils/fn.js'); 9721 9722 var Fn = _interopRequireWildcard(_utilsFnJs); 9723 9724 var _utilsGuidJs = _dereq_('./utils/guid.js'); 9725 9726 var Guid = _interopRequireWildcard(_utilsGuidJs); 9727 9728 var _utilsBrowserJs = _dereq_('./utils/browser.js'); 9729 9730 var browser = _interopRequireWildcard(_utilsBrowserJs); 9731 9732 var _utilsLogJs = _dereq_('./utils/log.js'); 9733 9734 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 9735 9736 var _utilsToTitleCaseJs = _dereq_('./utils/to-title-case.js'); 9737 9738 var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs); 9739 9740 var _utilsTimeRangesJs = _dereq_('./utils/time-ranges.js'); 9741 9742 var _utilsBufferJs = _dereq_('./utils/buffer.js'); 9743 9744 var _utilsStylesheetJs = _dereq_('./utils/stylesheet.js'); 9745 9746 var stylesheet = _interopRequireWildcard(_utilsStylesheetJs); 9747 9748 var _fullscreenApiJs = _dereq_('./fullscreen-api.js'); 9749 9750 var _fullscreenApiJs2 = _interopRequireDefault(_fullscreenApiJs); 9751 9752 var _mediaErrorJs = _dereq_('./media-error.js'); 9753 9754 var _mediaErrorJs2 = _interopRequireDefault(_mediaErrorJs); 9755 9756 var _safeJsonParseTuple = _dereq_('safe-json-parse/tuple'); 9757 9758 var _safeJsonParseTuple2 = _interopRequireDefault(_safeJsonParseTuple); 9759 9760 var _objectAssign = _dereq_('object.assign'); 9761 9762 var _objectAssign2 = _interopRequireDefault(_objectAssign); 9763 9764 var _utilsMergeOptionsJs = _dereq_('./utils/merge-options.js'); 9765 9766 var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs); 9767 9768 var _tracksTextTrackListConverterJs = _dereq_('./tracks/text-track-list-converter.js'); 9769 9770 var _tracksTextTrackListConverterJs2 = _interopRequireDefault(_tracksTextTrackListConverterJs); 9771 9772 // Include required child components (importing also registers them) 9773 9774 var _techLoaderJs = _dereq_('./tech/loader.js'); 9775 9776 var _techLoaderJs2 = _interopRequireDefault(_techLoaderJs); 9777 9778 var _posterImageJs = _dereq_('./poster-image.js'); 9779 9780 var _posterImageJs2 = _interopRequireDefault(_posterImageJs); 9781 9782 var _tracksTextTrackDisplayJs = _dereq_('./tracks/text-track-display.js'); 9783 9784 var _tracksTextTrackDisplayJs2 = _interopRequireDefault(_tracksTextTrackDisplayJs); 9785 9786 var _loadingSpinnerJs = _dereq_('./loading-spinner.js'); 9787 9788 var _loadingSpinnerJs2 = _interopRequireDefault(_loadingSpinnerJs); 9789 9790 var _bigPlayButtonJs = _dereq_('./big-play-button.js'); 9791 9792 var _bigPlayButtonJs2 = _interopRequireDefault(_bigPlayButtonJs); 9793 9794 var _controlBarControlBarJs = _dereq_('./control-bar/control-bar.js'); 9795 9796 var _controlBarControlBarJs2 = _interopRequireDefault(_controlBarControlBarJs); 9797 9798 var _errorDisplayJs = _dereq_('./error-display.js'); 9799 9800 var _errorDisplayJs2 = _interopRequireDefault(_errorDisplayJs); 9801 9802 var _tracksTextTrackSettingsJs = _dereq_('./tracks/text-track-settings.js'); 9803 9804 var _tracksTextTrackSettingsJs2 = _interopRequireDefault(_tracksTextTrackSettingsJs); 9805 9806 var _modalDialog = _dereq_('./modal-dialog'); 9807 9808 var _modalDialog2 = _interopRequireDefault(_modalDialog); 9809 9810 // Require html5 tech, at least for disposing the original video tag 9811 9812 var _techTechJs = _dereq_('./tech/tech.js'); 9813 9814 var _techTechJs2 = _interopRequireDefault(_techTechJs); 9815 9816 var _techHtml5Js = _dereq_('./tech/html5.js'); 9817 9818 var _techHtml5Js2 = _interopRequireDefault(_techHtml5Js); 9819 9820 /** 9821 * An instance of the `Player` class is created when any of the Video.js setup methods are used to initialize a video. 9822 * ```js 9823 * var myPlayer = videojs('example_video_1'); 9824 * ``` 9825 * In the following example, the `data-setup` attribute tells the Video.js library to create a player instance when the library is ready. 9826 * ```html 9827 * <video id="example_video_1" data-setup='{}' controls> 9828 * <source src="my-source.mp4" type="video/mp4"> 9829 * </video> 9830 * ``` 9831 * After an instance has been created it can be accessed globally using `Video('example_video_1')`. 9832 * 9833 * @param {Element} tag The original video tag used for configuring options 9834 * @param {Object=} options Object of option names and values 9835 * @param {Function=} ready Ready callback function 9836 * @extends Component 9837 * @class Player 9838 */ 9839 9840 var Player = (function (_Component) { 9841 _inherits(Player, _Component); 9842 9843 /** 9844 * player's constructor function 9845 * 9846 * @constructs 9847 * @method init 9848 * @param {Element} tag The original video tag used for configuring options 9849 * @param {Object=} options Player options 9850 * @param {Function=} ready Ready callback function 9851 */ 9852 9853 function Player(tag, options, ready) { 9854 var _this = this; 9855 9856 _classCallCheck(this, Player); 9857 9858 // Make sure tag ID exists 9859 tag.id = tag.id || 'vjs_video_' + Guid.newGUID(); 9860 9861 // Set Options 9862 // The options argument overrides options set in the video tag 9863 // which overrides globally set options. 9864 // This latter part coincides with the load order 9865 // (tag must exist before Player) 9866 options = _objectAssign2['default'](Player.getTagSettings(tag), options); 9867 9868 // Delay the initialization of children because we need to set up 9869 // player properties first, and can't use `this` before `super()` 9870 options.initChildren = false; 9871 9872 // Same with creating the element 9873 options.createEl = false; 9874 9875 // we don't want the player to report touch activity on itself 9876 // see enableTouchActivity in Component 9877 options.reportTouchActivity = false; 9878 9879 // Run base component initializing with new options 9880 _Component.call(this, null, options, ready); 9881 9882 // if the global option object was accidentally blown away by 9883 // someone, bail early with an informative error 9884 if (!this.options_ || !this.options_.techOrder || !this.options_.techOrder.length) { 9885 throw new Error('No techOrder specified. Did you overwrite ' + 'videojs.options instead of just changing the ' + 'properties you want to override?'); 9886 } 9887 9888 this.tag = tag; // Store the original tag used to set options 9889 9890 // Store the tag attributes used to restore html5 element 9891 this.tagAttributes = tag && Dom.getElAttributes(tag); 9892 9893 // Update current language 9894 this.language(this.options_.language); 9895 9896 // Update Supported Languages 9897 if (options.languages) { 9898 (function () { 9899 // Normalise player option languages to lowercase 9900 var languagesToLower = {}; 9901 9902 Object.getOwnPropertyNames(options.languages).forEach(function (name) { 9903 languagesToLower[name.toLowerCase()] = options.languages[name]; 9904 }); 9905 _this.languages_ = languagesToLower; 9906 })(); 9907 } else { 9908 this.languages_ = Player.prototype.options_.languages; 9909 } 9910 9911 // Cache for video property values. 9912 this.cache_ = {}; 9913 9914 // Set poster 9915 this.poster_ = options.poster || ''; 9916 9917 // Set controls 9918 this.controls_ = !!options.controls; 9919 9920 // Original tag settings stored in options 9921 // now remove immediately so native controls don't flash. 9922 // May be turned back on by HTML5 tech if nativeControlsForTouch is true 9923 tag.controls = false; 9924 9925 /* 9926 * Store the internal state of scrubbing 9927 * 9928 * @private 9929 * @return {Boolean} True if the user is scrubbing 9930 */ 9931 this.scrubbing_ = false; 9932 9933 this.el_ = this.createEl(); 9934 9935 // We also want to pass the original player options to each component and plugin 9936 // as well so they don't need to reach back into the player for options later. 9937 // We also need to do another copy of this.options_ so we don't end up with 9938 // an infinite loop. 9939 var playerOptionsCopy = _utilsMergeOptionsJs2['default'](this.options_); 9940 9941 // Load plugins 9942 if (options.plugins) { 9943 (function () { 9944 var plugins = options.plugins; 9945 9946 Object.getOwnPropertyNames(plugins).forEach(function (name) { 9947 if (typeof this[name] === 'function') { 9948 this[name](plugins[name]); 9949 } else { 9950 _utilsLogJs2['default'].error('Unable to find plugin:', name); 9951 } 9952 }, _this); 9953 })(); 9954 } 9955 9956 this.options_.playerOptions = playerOptionsCopy; 9957 9958 this.initChildren(); 9959 9960 // Set isAudio based on whether or not an audio tag was used 9961 this.isAudio(tag.nodeName.toLowerCase() === 'audio'); 9962 9963 // Update controls className. Can't do this when the controls are initially 9964 // set because the element doesn't exist yet. 9965 if (this.controls()) { 9966 this.addClass('vjs-controls-enabled'); 9967 } else { 9968 this.addClass('vjs-controls-disabled'); 9969 } 9970 9971 // Set ARIA label and region role depending on player type 9972 this.el_.setAttribute('role', 'region'); 9973 if (this.isAudio()) { 9974 this.el_.setAttribute('aria-label', 'audio player'); 9975 } else { 9976 this.el_.setAttribute('aria-label', 'video player'); 9977 } 9978 9979 if (this.isAudio()) { 9980 this.addClass('vjs-audio'); 9981 } 9982 9983 if (this.flexNotSupported_()) { 9984 this.addClass('vjs-no-flex'); 9985 } 9986 9987 // TODO: Make this smarter. Toggle user state between touching/mousing 9988 // using events, since devices can have both touch and mouse events. 9989 // if (browser.TOUCH_ENABLED) { 9990 // this.addClass('vjs-touch-enabled'); 9991 // } 9992 9993 // iOS Safari has broken hover handling 9994 if (!browser.IS_IOS) { 9995 this.addClass('vjs-workinghover'); 9996 } 9997 9998 // Make player easily findable by ID 9999 Player.players[this.id_] = this; 10000 10001 // When the player is first initialized, trigger activity so components 10002 // like the control bar show themselves if needed 10003 this.userActive(true); 10004 this.reportUserActivity(); 10005 this.listenForUserActivity_(); 10006 10007 this.on('fullscreenchange', this.handleFullscreenChange_); 10008 this.on('stageclick', this.handleStageClick_); 10009 } 10010 10011 /* 10012 * Global player list 10013 * 10014 * @type {Object} 10015 */ 10016 10017 /** 10018 * Destroys the video player and does any necessary cleanup 10019 * ```js 10020 * myPlayer.dispose(); 10021 * ``` 10022 * This is especially helpful if you are dynamically adding and removing videos 10023 * to/from the DOM. 10024 * 10025 * @method dispose 10026 */ 10027 10028 Player.prototype.dispose = function dispose() { 10029 this.trigger('dispose'); 10030 // prevent dispose from being called twice 10031 this.off('dispose'); 10032 10033 if (this.styleEl_ && this.styleEl_.parentNode) { 10034 this.styleEl_.parentNode.removeChild(this.styleEl_); 10035 } 10036 10037 // Kill reference to this player 10038 Player.players[this.id_] = null; 10039 if (this.tag && this.tag.player) { 10040 this.tag.player = null; 10041 } 10042 if (this.el_ && this.el_.player) { 10043 this.el_.player = null; 10044 } 10045 10046 if (this.tech_) { 10047 this.tech_.dispose(); 10048 } 10049 10050 _Component.prototype.dispose.call(this); 10051 }; 10052 10053 /** 10054 * Create the component's DOM element 10055 * 10056 * @return {Element} 10057 * @method createEl 10058 */ 10059 10060 Player.prototype.createEl = function createEl() { 10061 var el = this.el_ = _Component.prototype.createEl.call(this, 'div'); 10062 var tag = this.tag; 10063 10064 // Remove width/height attrs from tag so CSS can make it 100% width/height 10065 tag.removeAttribute('width'); 10066 tag.removeAttribute('height'); 10067 10068 // Copy over all the attributes from the tag, including ID and class 10069 // ID will now reference player box, not the video tag 10070 var attrs = Dom.getElAttributes(tag); 10071 10072 Object.getOwnPropertyNames(attrs).forEach(function (attr) { 10073 // workaround so we don't totally break IE7 10074 // http://stackoverflow.com/questions/3653444/css-styles-not-applied-on-dynamic-elements-in-internet-explorer-7 10075 if (attr === 'class') { 10076 el.className = attrs[attr]; 10077 } else { 10078 el.setAttribute(attr, attrs[attr]); 10079 } 10080 }); 10081 10082 // Update tag id/class for use as HTML5 playback tech 10083 // Might think we should do this after embedding in container so .vjs-tech class 10084 // doesn't flash 100% width/height, but class only applies with .video-js parent 10085 tag.playerId = tag.id; 10086 tag.id += '_html5_api'; 10087 tag.className = 'vjs-tech'; 10088 10089 // Make player findable on elements 10090 tag.player = el.player = this; 10091 // Default state of video is paused 10092 this.addClass('vjs-paused'); 10093 10094 // Add a style element in the player that we'll use to set the width/height 10095 // of the player in a way that's still overrideable by CSS, just like the 10096 // video element 10097 if (_globalWindow2['default'].VIDEOJS_NO_DYNAMIC_STYLE !== true) { 10098 this.styleEl_ = stylesheet.createStyleElement('vjs-styles-dimensions'); 10099 var defaultsStyleEl = Dom.$('.vjs-styles-defaults'); 10100 var head = Dom.$('head'); 10101 head.insertBefore(this.styleEl_, defaultsStyleEl ? defaultsStyleEl.nextSibling : head.firstChild); 10102 } 10103 10104 // Pass in the width/height/aspectRatio options which will update the style el 10105 this.width(this.options_.width); 10106 this.height(this.options_.height); 10107 this.fluid(this.options_.fluid); 10108 this.aspectRatio(this.options_.aspectRatio); 10109 10110 // Hide any links within the video/audio tag, because IE doesn't hide them completely. 10111 var links = tag.getElementsByTagName('a'); 10112 for (var i = 0; i < links.length; i++) { 10113 var linkEl = links.item(i); 10114 Dom.addElClass(linkEl, 'vjs-hidden'); 10115 linkEl.setAttribute('hidden', 'hidden'); 10116 } 10117 10118 // insertElFirst seems to cause the networkState to flicker from 3 to 2, so 10119 // keep track of the original for later so we can know if the source originally failed 10120 tag.initNetworkState_ = tag.networkState; 10121 10122 // Wrap video tag in div (el/box) container 10123 if (tag.parentNode) { 10124 tag.parentNode.insertBefore(el, tag); 10125 } 10126 10127 // insert the tag as the first child of the player element 10128 // then manually add it to the children array so that this.addChild 10129 // will work properly for other components 10130 Dom.insertElFirst(tag, el); // Breaks iPhone, fixed in HTML5 setup. 10131 this.children_.unshift(tag); 10132 10133 this.el_ = el; 10134 10135 return el; 10136 }; 10137 10138 /** 10139 * Get/set player width 10140 * 10141 * @param {Number=} value Value for width 10142 * @return {Number} Width when getting 10143 * @method width 10144 */ 10145 10146 Player.prototype.width = function width(value) { 10147 return this.dimension('width', value); 10148 }; 10149 10150 /** 10151 * Get/set player height 10152 * 10153 * @param {Number=} value Value for height 10154 * @return {Number} Height when getting 10155 * @method height 10156 */ 10157 10158 Player.prototype.height = function height(value) { 10159 return this.dimension('height', value); 10160 }; 10161 10162 /** 10163 * Get/set dimension for player 10164 * 10165 * @param {String} dimension Either width or height 10166 * @param {Number=} value Value for dimension 10167 * @return {Component} 10168 * @method dimension 10169 */ 10170 10171 Player.prototype.dimension = function dimension(_dimension, value) { 10172 var privDimension = _dimension + '_'; 10173 10174 if (value === undefined) { 10175 return this[privDimension] || 0; 10176 } 10177 10178 if (value === '') { 10179 // If an empty string is given, reset the dimension to be automatic 10180 this[privDimension] = undefined; 10181 } else { 10182 var parsedVal = parseFloat(value); 10183 10184 if (isNaN(parsedVal)) { 10185 _utilsLogJs2['default'].error('Improper value "' + value + '" supplied for for ' + _dimension); 10186 return this; 10187 } 10188 10189 this[privDimension] = parsedVal; 10190 } 10191 10192 this.updateStyleEl_(); 10193 return this; 10194 }; 10195 10196 /** 10197 * Add/remove the vjs-fluid class 10198 * 10199 * @param {Boolean} bool Value of true adds the class, value of false removes the class 10200 * @method fluid 10201 */ 10202 10203 Player.prototype.fluid = function fluid(bool) { 10204 if (bool === undefined) { 10205 return !!this.fluid_; 10206 } 10207 10208 this.fluid_ = !!bool; 10209 10210 if (bool) { 10211 this.addClass('vjs-fluid'); 10212 } else { 10213 this.removeClass('vjs-fluid'); 10214 } 10215 }; 10216 10217 /** 10218 * Get/Set the aspect ratio 10219 * 10220 * @param {String=} ratio Aspect ratio for player 10221 * @return aspectRatio 10222 * @method aspectRatio 10223 */ 10224 10225 Player.prototype.aspectRatio = function aspectRatio(ratio) { 10226 if (ratio === undefined) { 10227 return this.aspectRatio_; 10228 } 10229 10230 // Check for width:height format 10231 if (!/^\d+\:\d+$/.test(ratio)) { 10232 throw new Error('Improper value supplied for aspect ratio. The format should be width:height, for example 16:9.'); 10233 } 10234 this.aspectRatio_ = ratio; 10235 10236 // We're assuming if you set an aspect ratio you want fluid mode, 10237 // because in fixed mode you could calculate width and height yourself. 10238 this.fluid(true); 10239 10240 this.updateStyleEl_(); 10241 }; 10242 10243 /** 10244 * Update styles of the player element (height, width and aspect ratio) 10245 * 10246 * @method updateStyleEl_ 10247 */ 10248 10249 Player.prototype.updateStyleEl_ = function updateStyleEl_() { 10250 if (_globalWindow2['default'].VIDEOJS_NO_DYNAMIC_STYLE === true) { 10251 var _width = typeof this.width_ === 'number' ? this.width_ : this.options_.width; 10252 var _height = typeof this.height_ === 'number' ? this.height_ : this.options_.height; 10253 var techEl = this.tech_ && this.tech_.el(); 10254 10255 if (techEl) { 10256 if (_width >= 0) { 10257 techEl.width = _width; 10258 } 10259 if (_height >= 0) { 10260 techEl.height = _height; 10261 } 10262 } 10263 10264 return; 10265 } 10266 10267 var width = undefined; 10268 var height = undefined; 10269 var aspectRatio = undefined; 10270 var idClass = undefined; 10271 10272 // The aspect ratio is either used directly or to calculate width and height. 10273 if (this.aspectRatio_ !== undefined && this.aspectRatio_ !== 'auto') { 10274 // Use any aspectRatio that's been specifically set 10275 aspectRatio = this.aspectRatio_; 10276 } else if (this.videoWidth()) { 10277 // Otherwise try to get the aspect ratio from the video metadata 10278 aspectRatio = this.videoWidth() + ':' + this.videoHeight(); 10279 } else { 10280 // Or use a default. The video element's is 2:1, but 16:9 is more common. 10281 aspectRatio = '16:9'; 10282 } 10283 10284 // Get the ratio as a decimal we can use to calculate dimensions 10285 var ratioParts = aspectRatio.split(':'); 10286 var ratioMultiplier = ratioParts[1] / ratioParts[0]; 10287 10288 if (this.width_ !== undefined) { 10289 // Use any width that's been specifically set 10290 width = this.width_; 10291 } else if (this.height_ !== undefined) { 10292 // Or calulate the width from the aspect ratio if a height has been set 10293 width = this.height_ / ratioMultiplier; 10294 } else { 10295 // Or use the video's metadata, or use the video el's default of 300 10296 width = this.videoWidth() || 300; 10297 } 10298 10299 if (this.height_ !== undefined) { 10300 // Use any height that's been specifically set 10301 height = this.height_; 10302 } else { 10303 // Otherwise calculate the height from the ratio and the width 10304 height = width * ratioMultiplier; 10305 } 10306 10307 // Ensure the CSS class is valid by starting with an alpha character 10308 if (/^[^a-zA-Z]/.test(this.id())) { 10309 idClass = 'dimensions-' + this.id(); 10310 } else { 10311 idClass = this.id() + '-dimensions'; 10312 } 10313 10314 // Ensure the right class is still on the player for the style element 10315 this.addClass(idClass); 10316 10317 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 '); 10318 }; 10319 10320 /** 10321 * Load the Media Playback Technology (tech) 10322 * Load/Create an instance of playback technology including element and API methods 10323 * And append playback element in player div. 10324 * 10325 * @param {String} techName Name of the playback technology 10326 * @param {String} source Video source 10327 * @method loadTech_ 10328 * @private 10329 */ 10330 10331 Player.prototype.loadTech_ = function loadTech_(techName, source) { 10332 10333 // Pause and remove current playback technology 10334 if (this.tech_) { 10335 this.unloadTech_(); 10336 } 10337 10338 // get rid of the HTML5 video tag as soon as we are using another tech 10339 if (techName !== 'Html5' && this.tag) { 10340 _techTechJs2['default'].getTech('Html5').disposeMediaElement(this.tag); 10341 this.tag.player = null; 10342 this.tag = null; 10343 } 10344 10345 this.techName_ = techName; 10346 10347 // Turn off API access because we're loading a new tech that might load asynchronously 10348 this.isReady_ = false; 10349 10350 // Grab tech-specific options from player options and add source and parent element to use. 10351 var techOptions = _objectAssign2['default']({ 10352 'nativeControlsForTouch': this.options_.nativeControlsForTouch, 10353 'source': source, 10354 'playerId': this.id(), 10355 'techId': this.id() + '_' + techName + '_api', 10356 'textTracks': this.textTracks_, 10357 'autoplay': this.options_.autoplay, 10358 'preload': this.options_.preload, 10359 'loop': this.options_.loop, 10360 'muted': this.options_.muted, 10361 'poster': this.poster(), 10362 'language': this.language(), 10363 'vtt.js': this.options_['vtt.js'] 10364 }, this.options_[techName.toLowerCase()]); 10365 10366 if (this.tag) { 10367 techOptions.tag = this.tag; 10368 } 10369 10370 if (source) { 10371 this.currentType_ = source.type; 10372 if (source.src === this.cache_.src && this.cache_.currentTime > 0) { 10373 techOptions.startTime = this.cache_.currentTime; 10374 } 10375 10376 this.cache_.src = source.src; 10377 } 10378 10379 // Initialize tech instance 10380 var techComponent = _techTechJs2['default'].getTech(techName); 10381 // Support old behavior of techs being registered as components. 10382 // Remove once that deprecated behavior is removed. 10383 if (!techComponent) { 10384 techComponent = _componentJs2['default'].getComponent(techName); 10385 } 10386 this.tech_ = new techComponent(techOptions); 10387 10388 // player.triggerReady is always async, so don't need this to be async 10389 this.tech_.ready(Fn.bind(this, this.handleTechReady_), true); 10390 10391 _tracksTextTrackListConverterJs2['default'].jsonToTextTracks(this.textTracksJson_ || [], this.tech_); 10392 10393 // Listen to all HTML5-defined events and trigger them on the player 10394 this.on(this.tech_, 'loadstart', this.handleTechLoadStart_); 10395 this.on(this.tech_, 'waiting', this.handleTechWaiting_); 10396 this.on(this.tech_, 'canplay', this.handleTechCanPlay_); 10397 this.on(this.tech_, 'canplaythrough', this.handleTechCanPlayThrough_); 10398 this.on(this.tech_, 'playing', this.handleTechPlaying_); 10399 this.on(this.tech_, 'ended', this.handleTechEnded_); 10400 this.on(this.tech_, 'seeking', this.handleTechSeeking_); 10401 this.on(this.tech_, 'seeked', this.handleTechSeeked_); 10402 this.on(this.tech_, 'play', this.handleTechPlay_); 10403 this.on(this.tech_, 'firstplay', this.handleTechFirstPlay_); 10404 this.on(this.tech_, 'pause', this.handleTechPause_); 10405 this.on(this.tech_, 'progress', this.handleTechProgress_); 10406 this.on(this.tech_, 'durationchange', this.handleTechDurationChange_); 10407 this.on(this.tech_, 'fullscreenchange', this.handleTechFullscreenChange_); 10408 this.on(this.tech_, 'error', this.handleTechError_); 10409 this.on(this.tech_, 'suspend', this.handleTechSuspend_); 10410 this.on(this.tech_, 'abort', this.handleTechAbort_); 10411 this.on(this.tech_, 'emptied', this.handleTechEmptied_); 10412 this.on(this.tech_, 'stalled', this.handleTechStalled_); 10413 this.on(this.tech_, 'loadedmetadata', this.handleTechLoadedMetaData_); 10414 this.on(this.tech_, 'loadeddata', this.handleTechLoadedData_); 10415 this.on(this.tech_, 'timeupdate', this.handleTechTimeUpdate_); 10416 this.on(this.tech_, 'ratechange', this.handleTechRateChange_); 10417 this.on(this.tech_, 'volumechange', this.handleTechVolumeChange_); 10418 this.on(this.tech_, 'texttrackchange', this.handleTechTextTrackChange_); 10419 this.on(this.tech_, 'loadedmetadata', this.updateStyleEl_); 10420 this.on(this.tech_, 'posterchange', this.handleTechPosterChange_); 10421 10422 this.usingNativeControls(this.techGet_('controls')); 10423 10424 if (this.controls() && !this.usingNativeControls()) { 10425 this.addTechControlsListeners_(); 10426 } 10427 10428 // Add the tech element in the DOM if it was not already there 10429 // Make sure to not insert the original video element if using Html5 10430 if (this.tech_.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) { 10431 Dom.insertElFirst(this.tech_.el(), this.el()); 10432 } 10433 10434 // Get rid of the original video tag reference after the first tech is loaded 10435 if (this.tag) { 10436 this.tag.player = null; 10437 this.tag = null; 10438 } 10439 }; 10440 10441 /** 10442 * Unload playback technology 10443 * 10444 * @method unloadTech_ 10445 * @private 10446 */ 10447 10448 Player.prototype.unloadTech_ = function unloadTech_() { 10449 // Save the current text tracks so that we can reuse the same text tracks with the next tech 10450 this.textTracks_ = this.textTracks(); 10451 this.textTracksJson_ = _tracksTextTrackListConverterJs2['default'].textTracksToJson(this.tech_); 10452 10453 this.isReady_ = false; 10454 10455 this.tech_.dispose(); 10456 10457 this.tech_ = false; 10458 }; 10459 10460 /** 10461 * Return a reference to the current tech. 10462 * It will only return a reference to the tech if given an object with the 10463 * `IWillNotUseThisInPlugins` property on it. This is try and prevent misuse 10464 * of techs by plugins. 10465 * 10466 * @param {Object} 10467 * @return {Object} The Tech 10468 * @method tech 10469 */ 10470 10471 Player.prototype.tech = function tech(safety) { 10472 if (safety && safety.IWillNotUseThisInPlugins) { 10473 return this.tech_; 10474 } 10475 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 '; 10476 _globalWindow2['default'].alert(errorText); 10477 throw new Error(errorText); 10478 }; 10479 10480 /** 10481 * Set up click and touch listeners for the playback element 10482 * 10483 * On desktops, a click on the video itself will toggle playback, 10484 * on a mobile device a click on the video toggles controls. 10485 * (toggling controls is done by toggling the user state between active and 10486 * inactive) 10487 * A tap can signal that a user has become active, or has become inactive 10488 * e.g. a quick tap on an iPhone movie should reveal the controls. Another 10489 * quick tap should hide them again (signaling the user is in an inactive 10490 * viewing state) 10491 * In addition to this, we still want the user to be considered inactive after 10492 * a few seconds of inactivity. 10493 * Note: the only part of iOS interaction we can't mimic with this setup 10494 * is a touch and hold on the video element counting as activity in order to 10495 * keep the controls showing, but that shouldn't be an issue. A touch and hold 10496 * on any controls will still keep the user active 10497 * 10498 * @private 10499 * @method addTechControlsListeners_ 10500 */ 10501 10502 Player.prototype.addTechControlsListeners_ = function addTechControlsListeners_() { 10503 // Make sure to remove all the previous listeners in case we are called multiple times. 10504 this.removeTechControlsListeners_(); 10505 10506 // Some browsers (Chrome & IE) don't trigger a click on a flash swf, but do 10507 // trigger mousedown/up. 10508 // http://stackoverflow.com/questions/1444562/javascript-onclick-event-over-flash-object 10509 // Any touch events are set to block the mousedown event from happening 10510 this.on(this.tech_, 'mousedown', this.handleTechClick_); 10511 10512 // If the controls were hidden we don't want that to change without a tap event 10513 // so we'll check if the controls were already showing before reporting user 10514 // activity 10515 this.on(this.tech_, 'touchstart', this.handleTechTouchStart_); 10516 this.on(this.tech_, 'touchmove', this.handleTechTouchMove_); 10517 this.on(this.tech_, 'touchend', this.handleTechTouchEnd_); 10518 10519 // The tap listener needs to come after the touchend listener because the tap 10520 // listener cancels out any reportedUserActivity when setting userActive(false) 10521 this.on(this.tech_, 'tap', this.handleTechTap_); 10522 }; 10523 10524 /** 10525 * Remove the listeners used for click and tap controls. This is needed for 10526 * toggling to controls disabled, where a tap/touch should do nothing. 10527 * 10528 * @method removeTechControlsListeners_ 10529 * @private 10530 */ 10531 10532 Player.prototype.removeTechControlsListeners_ = function removeTechControlsListeners_() { 10533 // We don't want to just use `this.off()` because there might be other needed 10534 // listeners added by techs that extend this. 10535 this.off(this.tech_, 'tap', this.handleTechTap_); 10536 this.off(this.tech_, 'touchstart', this.handleTechTouchStart_); 10537 this.off(this.tech_, 'touchmove', this.handleTechTouchMove_); 10538 this.off(this.tech_, 'touchend', this.handleTechTouchEnd_); 10539 this.off(this.tech_, 'mousedown', this.handleTechClick_); 10540 }; 10541 10542 /** 10543 * Player waits for the tech to be ready 10544 * 10545 * @method handleTechReady_ 10546 * @private 10547 */ 10548 10549 Player.prototype.handleTechReady_ = function handleTechReady_() { 10550 this.triggerReady(); 10551 10552 // Keep the same volume as before 10553 if (this.cache_.volume) { 10554 this.techCall_('setVolume', this.cache_.volume); 10555 } 10556 10557 // Look if the tech found a higher resolution poster while loading 10558 this.handleTechPosterChange_(); 10559 10560 // Update the duration if available 10561 this.handleTechDurationChange_(); 10562 10563 // Chrome and Safari both have issues with autoplay. 10564 // In Safari (5.1.1), when we move the video element into the container div, autoplay doesn't work. 10565 // In Chrome (15), if you have autoplay + a poster + no controls, the video gets hidden (but audio plays) 10566 // This fixes both issues. Need to wait for API, so it updates displays correctly 10567 if (this.src() && this.tag && this.options_.autoplay && this.paused()) { 10568 delete this.tag.poster; // Chrome Fix. Fixed in Chrome v16. 10569 this.play(); 10570 } 10571 }; 10572 10573 /** 10574 * Fired when the user agent begins looking for media data 10575 * 10576 * @private 10577 * @method handleTechLoadStart_ 10578 */ 10579 10580 Player.prototype.handleTechLoadStart_ = function handleTechLoadStart_() { 10581 // TODO: Update to use `emptied` event instead. See #1277. 10582 10583 this.removeClass('vjs-ended'); 10584 10585 // reset the error state 10586 this.error(null); 10587 10588 // If it's already playing we want to trigger a firstplay event now. 10589 // The firstplay event relies on both the play and loadstart events 10590 // which can happen in any order for a new source 10591 if (!this.paused()) { 10592 this.trigger('loadstart'); 10593 this.trigger('firstplay'); 10594 } else { 10595 // reset the hasStarted state 10596 this.hasStarted(false); 10597 this.trigger('loadstart'); 10598 } 10599 }; 10600 10601 /** 10602 * Add/remove the vjs-has-started class 10603 * 10604 * @param {Boolean} hasStarted The value of true adds the class the value of false remove the class 10605 * @return {Boolean} Boolean value if has started 10606 * @private 10607 * @method hasStarted 10608 */ 10609 10610 Player.prototype.hasStarted = function hasStarted(_hasStarted) { 10611 if (_hasStarted !== undefined) { 10612 // only update if this is a new value 10613 if (this.hasStarted_ !== _hasStarted) { 10614 this.hasStarted_ = _hasStarted; 10615 if (_hasStarted) { 10616 this.addClass('vjs-has-started'); 10617 // trigger the firstplay event if this newly has played 10618 this.trigger('firstplay'); 10619 } else { 10620 this.removeClass('vjs-has-started'); 10621 } 10622 } 10623 return this; 10624 } 10625 return !!this.hasStarted_; 10626 }; 10627 10628 /** 10629 * Fired whenever the media begins or resumes playback 10630 * 10631 * @private 10632 * @method handleTechPlay_ 10633 */ 10634 10635 Player.prototype.handleTechPlay_ = function handleTechPlay_() { 10636 this.removeClass('vjs-ended'); 10637 this.removeClass('vjs-paused'); 10638 this.addClass('vjs-playing'); 10639 10640 // hide the poster when the user hits play 10641 // https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-play 10642 this.hasStarted(true); 10643 10644 this.trigger('play'); 10645 }; 10646 10647 /** 10648 * Fired whenever the media begins waiting 10649 * 10650 * @private 10651 * @method handleTechWaiting_ 10652 */ 10653 10654 Player.prototype.handleTechWaiting_ = function handleTechWaiting_() { 10655 var _this2 = this; 10656 10657 this.addClass('vjs-waiting'); 10658 this.trigger('waiting'); 10659 this.one('timeupdate', function () { 10660 return _this2.removeClass('vjs-waiting'); 10661 }); 10662 }; 10663 10664 /** 10665 * A handler for events that signal that waiting has ended 10666 * which is not consistent between browsers. See #1351 10667 * 10668 * @private 10669 * @method handleTechCanPlay_ 10670 */ 10671 10672 Player.prototype.handleTechCanPlay_ = function handleTechCanPlay_() { 10673 this.removeClass('vjs-waiting'); 10674 this.trigger('canplay'); 10675 }; 10676 10677 /** 10678 * A handler for events that signal that waiting has ended 10679 * which is not consistent between browsers. See #1351 10680 * 10681 * @private 10682 * @method handleTechCanPlayThrough_ 10683 */ 10684 10685 Player.prototype.handleTechCanPlayThrough_ = function handleTechCanPlayThrough_() { 10686 this.removeClass('vjs-waiting'); 10687 this.trigger('canplaythrough'); 10688 }; 10689 10690 /** 10691 * A handler for events that signal that waiting has ended 10692 * which is not consistent between browsers. See #1351 10693 * 10694 * @private 10695 * @method handleTechPlaying_ 10696 */ 10697 10698 Player.prototype.handleTechPlaying_ = function handleTechPlaying_() { 10699 this.removeClass('vjs-waiting'); 10700 this.trigger('playing'); 10701 }; 10702 10703 /** 10704 * Fired whenever the player is jumping to a new time 10705 * 10706 * @private 10707 * @method handleTechSeeking_ 10708 */ 10709 10710 Player.prototype.handleTechSeeking_ = function handleTechSeeking_() { 10711 this.addClass('vjs-seeking'); 10712 this.trigger('seeking'); 10713 }; 10714 10715 /** 10716 * Fired when the player has finished jumping to a new time 10717 * 10718 * @private 10719 * @method handleTechSeeked_ 10720 */ 10721 10722 Player.prototype.handleTechSeeked_ = function handleTechSeeked_() { 10723 this.removeClass('vjs-seeking'); 10724 this.trigger('seeked'); 10725 }; 10726 10727 /** 10728 * Fired the first time a video is played 10729 * Not part of the HLS spec, and we're not sure if this is the best 10730 * implementation yet, so use sparingly. If you don't have a reason to 10731 * prevent playback, use `myPlayer.one('play');` instead. 10732 * 10733 * @private 10734 * @method handleTechFirstPlay_ 10735 */ 10736 10737 Player.prototype.handleTechFirstPlay_ = function handleTechFirstPlay_() { 10738 //If the first starttime attribute is specified 10739 //then we will start at the given offset in seconds 10740 if (this.options_.starttime) { 10741 this.currentTime(this.options_.starttime); 10742 } 10743 10744 this.addClass('vjs-has-started'); 10745 this.trigger('firstplay'); 10746 }; 10747 10748 /** 10749 * Fired whenever the media has been paused 10750 * 10751 * @private 10752 * @method handleTechPause_ 10753 */ 10754 10755 Player.prototype.handleTechPause_ = function handleTechPause_() { 10756 this.removeClass('vjs-playing'); 10757 this.addClass('vjs-paused'); 10758 this.trigger('pause'); 10759 }; 10760 10761 /** 10762 * Fired while the user agent is downloading media data 10763 * 10764 * @private 10765 * @method handleTechProgress_ 10766 */ 10767 10768 Player.prototype.handleTechProgress_ = function handleTechProgress_() { 10769 this.trigger('progress'); 10770 }; 10771 10772 /** 10773 * Fired when the end of the media resource is reached (currentTime == duration) 10774 * 10775 * @private 10776 * @method handleTechEnded_ 10777 */ 10778 10779 Player.prototype.handleTechEnded_ = function handleTechEnded_() { 10780 this.addClass('vjs-ended'); 10781 if (this.options_.loop) { 10782 this.currentTime(0); 10783 this.play(); 10784 } else if (!this.paused()) { 10785 this.pause(); 10786 } 10787 10788 this.trigger('ended'); 10789 }; 10790 10791 /** 10792 * Fired when the duration of the media resource is first known or changed 10793 * 10794 * @private 10795 * @method handleTechDurationChange_ 10796 */ 10797 10798 Player.prototype.handleTechDurationChange_ = function handleTechDurationChange_() { 10799 this.duration(this.techGet_('duration')); 10800 }; 10801 10802 /** 10803 * Handle a click on the media element to play/pause 10804 * 10805 * @param {Object=} event Event object 10806 * @private 10807 * @method handleTechClick_ 10808 */ 10809 10810 Player.prototype.handleTechClick_ = function handleTechClick_(event) { 10811 // We're using mousedown to detect clicks thanks to Flash, but mousedown 10812 // will also be triggered with right-clicks, so we need to prevent that 10813 if (event.button !== 0) return; 10814 10815 // When controls are disabled a click should not toggle playback because 10816 // the click is considered a control 10817 if (this.controls()) { 10818 if (this.paused()) { 10819 this.play(); 10820 } else { 10821 this.pause(); 10822 } 10823 } 10824 }; 10825 10826 /** 10827 * Handle a tap on the media element. It will toggle the user 10828 * activity state, which hides and shows the controls. 10829 * 10830 * @private 10831 * @method handleTechTap_ 10832 */ 10833 10834 Player.prototype.handleTechTap_ = function handleTechTap_() { 10835 this.userActive(!this.userActive()); 10836 }; 10837 10838 /** 10839 * Handle touch to start 10840 * 10841 * @private 10842 * @method handleTechTouchStart_ 10843 */ 10844 10845 Player.prototype.handleTechTouchStart_ = function handleTechTouchStart_() { 10846 this.userWasActive = this.userActive(); 10847 }; 10848 10849 /** 10850 * Handle touch to move 10851 * 10852 * @private 10853 * @method handleTechTouchMove_ 10854 */ 10855 10856 Player.prototype.handleTechTouchMove_ = function handleTechTouchMove_() { 10857 if (this.userWasActive) { 10858 this.reportUserActivity(); 10859 } 10860 }; 10861 10862 /** 10863 * Handle touch to end 10864 * 10865 * @private 10866 * @method handleTechTouchEnd_ 10867 */ 10868 10869 Player.prototype.handleTechTouchEnd_ = function handleTechTouchEnd_(event) { 10870 // Stop the mouse events from also happening 10871 event.preventDefault(); 10872 }; 10873 10874 /** 10875 * Fired when the player switches in or out of fullscreen mode 10876 * 10877 * @private 10878 * @method handleFullscreenChange_ 10879 */ 10880 10881 Player.prototype.handleFullscreenChange_ = function handleFullscreenChange_() { 10882 if (this.isFullscreen()) { 10883 this.addClass('vjs-fullscreen'); 10884 } else { 10885 this.removeClass('vjs-fullscreen'); 10886 } 10887 }; 10888 10889 /** 10890 * native click events on the SWF aren't triggered on IE11, Win8.1RT 10891 * use stageclick events triggered from inside the SWF instead 10892 * 10893 * @private 10894 * @method handleStageClick_ 10895 */ 10896 10897 Player.prototype.handleStageClick_ = function handleStageClick_() { 10898 this.reportUserActivity(); 10899 }; 10900 10901 /** 10902 * Handle Tech Fullscreen Change 10903 * 10904 * @private 10905 * @method handleTechFullscreenChange_ 10906 */ 10907 10908 Player.prototype.handleTechFullscreenChange_ = function handleTechFullscreenChange_(event, data) { 10909 if (data) { 10910 this.isFullscreen(data.isFullscreen); 10911 } 10912 this.trigger('fullscreenchange'); 10913 }; 10914 10915 /** 10916 * Fires when an error occurred during the loading of an audio/video 10917 * 10918 * @private 10919 * @method handleTechError_ 10920 */ 10921 10922 Player.prototype.handleTechError_ = function handleTechError_() { 10923 var error = this.tech_.error(); 10924 this.error(error && error.code); 10925 }; 10926 10927 /** 10928 * Fires when the browser is intentionally not getting media data 10929 * 10930 * @private 10931 * @method handleTechSuspend_ 10932 */ 10933 10934 Player.prototype.handleTechSuspend_ = function handleTechSuspend_() { 10935 this.trigger('suspend'); 10936 }; 10937 10938 /** 10939 * Fires when the loading of an audio/video is aborted 10940 * 10941 * @private 10942 * @method handleTechAbort_ 10943 */ 10944 10945 Player.prototype.handleTechAbort_ = function handleTechAbort_() { 10946 this.trigger('abort'); 10947 }; 10948 10949 /** 10950 * Fires when the current playlist is empty 10951 * 10952 * @private 10953 * @method handleTechEmptied_ 10954 */ 10955 10956 Player.prototype.handleTechEmptied_ = function handleTechEmptied_() { 10957 this.trigger('emptied'); 10958 }; 10959 10960 /** 10961 * Fires when the browser is trying to get media data, but data is not available 10962 * 10963 * @private 10964 * @method handleTechStalled_ 10965 */ 10966 10967 Player.prototype.handleTechStalled_ = function handleTechStalled_() { 10968 this.trigger('stalled'); 10969 }; 10970 10971 /** 10972 * Fires when the browser has loaded meta data for the audio/video 10973 * 10974 * @private 10975 * @method handleTechLoadedMetaData_ 10976 */ 10977 10978 Player.prototype.handleTechLoadedMetaData_ = function handleTechLoadedMetaData_() { 10979 this.trigger('loadedmetadata'); 10980 }; 10981 10982 /** 10983 * Fires when the browser has loaded the current frame of the audio/video 10984 * 10985 * @private 10986 * @method handleTechLoadedData_ 10987 */ 10988 10989 Player.prototype.handleTechLoadedData_ = function handleTechLoadedData_() { 10990 this.trigger('loadeddata'); 10991 }; 10992 10993 /** 10994 * Fires when the current playback position has changed 10995 * 10996 * @private 10997 * @method handleTechTimeUpdate_ 10998 */ 10999 11000 Player.prototype.handleTechTimeUpdate_ = function handleTechTimeUpdate_() { 11001 this.trigger('timeupdate'); 11002 }; 11003 11004 /** 11005 * Fires when the playing speed of the audio/video is changed 11006 * 11007 * @private 11008 * @method handleTechRateChange_ 11009 */ 11010 11011 Player.prototype.handleTechRateChange_ = function handleTechRateChange_() { 11012 this.trigger('ratechange'); 11013 }; 11014 11015 /** 11016 * Fires when the volume has been changed 11017 * 11018 * @private 11019 * @method handleTechVolumeChange_ 11020 */ 11021 11022 Player.prototype.handleTechVolumeChange_ = function handleTechVolumeChange_() { 11023 this.trigger('volumechange'); 11024 }; 11025 11026 /** 11027 * Fires when the text track has been changed 11028 * 11029 * @private 11030 * @method handleTechTextTrackChange_ 11031 */ 11032 11033 Player.prototype.handleTechTextTrackChange_ = function handleTechTextTrackChange_() { 11034 this.trigger('texttrackchange'); 11035 }; 11036 11037 /** 11038 * Get object for cached values. 11039 * 11040 * @return {Object} 11041 * @method getCache 11042 */ 11043 11044 Player.prototype.getCache = function getCache() { 11045 return this.cache_; 11046 }; 11047 11048 /** 11049 * Pass values to the playback tech 11050 * 11051 * @param {String=} method Method 11052 * @param {Object=} arg Argument 11053 * @private 11054 * @method techCall_ 11055 */ 11056 11057 Player.prototype.techCall_ = function techCall_(method, arg) { 11058 // If it's not ready yet, call method when it is 11059 if (this.tech_ && !this.tech_.isReady_) { 11060 this.tech_.ready(function () { 11061 this[method](arg); 11062 }, true); 11063 11064 // Otherwise call method now 11065 } else { 11066 try { 11067 this.tech_[method](arg); 11068 } catch (e) { 11069 _utilsLogJs2['default'](e); 11070 throw e; 11071 } 11072 } 11073 }; 11074 11075 /** 11076 * Get calls can't wait for the tech, and sometimes don't need to. 11077 * 11078 * @param {String} method Tech method 11079 * @return {Method} 11080 * @private 11081 * @method techGet_ 11082 */ 11083 11084 Player.prototype.techGet_ = function techGet_(method) { 11085 if (this.tech_ && this.tech_.isReady_) { 11086 11087 // Flash likes to die and reload when you hide or reposition it. 11088 // In these cases the object methods go away and we get errors. 11089 // When that happens we'll catch the errors and inform tech that it's not ready any more. 11090 try { 11091 return this.tech_[method](); 11092 } catch (e) { 11093 // When building additional tech libs, an expected method may not be defined yet 11094 if (this.tech_[method] === undefined) { 11095 _utilsLogJs2['default']('Video.js: ' + method + ' method not defined for ' + this.techName_ + ' playback technology.', e); 11096 } else { 11097 // When a method isn't available on the object it throws a TypeError 11098 if (e.name === 'TypeError') { 11099 _utilsLogJs2['default']('Video.js: ' + method + ' unavailable on ' + this.techName_ + ' playback technology element.', e); 11100 this.tech_.isReady_ = false; 11101 } else { 11102 _utilsLogJs2['default'](e); 11103 } 11104 } 11105 throw e; 11106 } 11107 } 11108 11109 return; 11110 }; 11111 11112 /** 11113 * start media playback 11114 * ```js 11115 * myPlayer.play(); 11116 * ``` 11117 * 11118 * @return {Player} self 11119 * @method play 11120 */ 11121 11122 Player.prototype.play = function play() { 11123 this.techCall_('play'); 11124 return this; 11125 }; 11126 11127 /** 11128 * Pause the video playback 11129 * ```js 11130 * myPlayer.pause(); 11131 * ``` 11132 * 11133 * @return {Player} self 11134 * @method pause 11135 */ 11136 11137 Player.prototype.pause = function pause() { 11138 this.techCall_('pause'); 11139 return this; 11140 }; 11141 11142 /** 11143 * Check if the player is paused 11144 * ```js 11145 * var isPaused = myPlayer.paused(); 11146 * var isPlaying = !myPlayer.paused(); 11147 * ``` 11148 * 11149 * @return {Boolean} false if the media is currently playing, or true otherwise 11150 * @method paused 11151 */ 11152 11153 Player.prototype.paused = function paused() { 11154 // The initial state of paused should be true (in Safari it's actually false) 11155 return this.techGet_('paused') === false ? false : true; 11156 }; 11157 11158 /** 11159 * Returns whether or not the user is "scrubbing". Scrubbing is when the user 11160 * has clicked the progress bar handle and is dragging it along the progress bar. 11161 * 11162 * @param {Boolean} isScrubbing True/false the user is scrubbing 11163 * @return {Boolean} The scrubbing status when getting 11164 * @return {Object} The player when setting 11165 * @method scrubbing 11166 */ 11167 11168 Player.prototype.scrubbing = function scrubbing(isScrubbing) { 11169 if (isScrubbing !== undefined) { 11170 this.scrubbing_ = !!isScrubbing; 11171 11172 if (isScrubbing) { 11173 this.addClass('vjs-scrubbing'); 11174 } else { 11175 this.removeClass('vjs-scrubbing'); 11176 } 11177 11178 return this; 11179 } 11180 11181 return this.scrubbing_; 11182 }; 11183 11184 /** 11185 * Get or set the current time (in seconds) 11186 * ```js 11187 * // get 11188 * var whereYouAt = myPlayer.currentTime(); 11189 * // set 11190 * myPlayer.currentTime(120); // 2 minutes into the video 11191 * ``` 11192 * 11193 * @param {Number|String=} seconds The time to seek to 11194 * @return {Number} The time in seconds, when not setting 11195 * @return {Player} self, when the current time is set 11196 * @method currentTime 11197 */ 11198 11199 Player.prototype.currentTime = function currentTime(seconds) { 11200 if (seconds !== undefined) { 11201 11202 this.techCall_('setCurrentTime', seconds); 11203 11204 return this; 11205 } 11206 11207 // cache last currentTime and return. default to 0 seconds 11208 // 11209 // Caching the currentTime is meant to prevent a massive amount of reads on the tech's 11210 // currentTime when scrubbing, but may not provide much performance benefit afterall. 11211 // Should be tested. Also something has to read the actual current time or the cache will 11212 // never get updated. 11213 return this.cache_.currentTime = this.techGet_('currentTime') || 0; 11214 }; 11215 11216 /** 11217 * Get the length in time of the video in seconds 11218 * ```js 11219 * var lengthOfVideo = myPlayer.duration(); 11220 * ``` 11221 * **NOTE**: The video must have started loading before the duration can be 11222 * known, and in the case of Flash, may not be known until the video starts 11223 * playing. 11224 * 11225 * @param {Number} seconds Duration when setting 11226 * @return {Number} The duration of the video in seconds when getting 11227 * @method duration 11228 */ 11229 11230 Player.prototype.duration = function duration(seconds) { 11231 if (seconds === undefined) { 11232 return this.cache_.duration || 0; 11233 } 11234 11235 seconds = parseFloat(seconds) || 0; 11236 11237 // Standardize on Inifity for signaling video is live 11238 if (seconds < 0) { 11239 seconds = Infinity; 11240 } 11241 11242 if (seconds !== this.cache_.duration) { 11243 // Cache the last set value for optimized scrubbing (esp. Flash) 11244 this.cache_.duration = seconds; 11245 11246 if (seconds === Infinity) { 11247 this.addClass('vjs-live'); 11248 } else { 11249 this.removeClass('vjs-live'); 11250 } 11251 11252 this.trigger('durationchange'); 11253 } 11254 11255 return this; 11256 }; 11257 11258 /** 11259 * Calculates how much time is left. 11260 * ```js 11261 * var timeLeft = myPlayer.remainingTime(); 11262 * ``` 11263 * Not a native video element function, but useful 11264 * 11265 * @return {Number} The time remaining in seconds 11266 * @method remainingTime 11267 */ 11268 11269 Player.prototype.remainingTime = function remainingTime() { 11270 return this.duration() - this.currentTime(); 11271 }; 11272 11273 // http://dev.w3.org/html5/spec/video.html#dom-media-buffered 11274 // Buffered returns a timerange object. 11275 // Kind of like an array of portions of the video that have been downloaded. 11276 11277 /** 11278 * Get a TimeRange object with the times of the video that have been downloaded 11279 * If you just want the percent of the video that's been downloaded, 11280 * use bufferedPercent. 11281 * ```js 11282 * // Number of different ranges of time have been buffered. Usually 1. 11283 * numberOfRanges = bufferedTimeRange.length, 11284 * // Time in seconds when the first range starts. Usually 0. 11285 * firstRangeStart = bufferedTimeRange.start(0), 11286 * // Time in seconds when the first range ends 11287 * firstRangeEnd = bufferedTimeRange.end(0), 11288 * // Length in seconds of the first time range 11289 * firstRangeLength = firstRangeEnd - firstRangeStart; 11290 * ``` 11291 * 11292 * @return {Object} A mock TimeRange object (following HTML spec) 11293 * @method buffered 11294 */ 11295 11296 Player.prototype.buffered = function buffered() { 11297 var buffered = this.techGet_('buffered'); 11298 11299 if (!buffered || !buffered.length) { 11300 buffered = _utilsTimeRangesJs.createTimeRange(0, 0); 11301 } 11302 11303 return buffered; 11304 }; 11305 11306 /** 11307 * Get the percent (as a decimal) of the video that's been downloaded 11308 * ```js 11309 * var howMuchIsDownloaded = myPlayer.bufferedPercent(); 11310 * ``` 11311 * 0 means none, 1 means all. 11312 * (This method isn't in the HTML5 spec, but it's very convenient) 11313 * 11314 * @return {Number} A decimal between 0 and 1 representing the percent 11315 * @method bufferedPercent 11316 */ 11317 11318 Player.prototype.bufferedPercent = function bufferedPercent() { 11319 return _utilsBufferJs.bufferedPercent(this.buffered(), this.duration()); 11320 }; 11321 11322 /** 11323 * Get the ending time of the last buffered time range 11324 * This is used in the progress bar to encapsulate all time ranges. 11325 * 11326 * @return {Number} The end of the last buffered time range 11327 * @method bufferedEnd 11328 */ 11329 11330 Player.prototype.bufferedEnd = function bufferedEnd() { 11331 var buffered = this.buffered(), 11332 duration = this.duration(), 11333 end = buffered.end(buffered.length - 1); 11334 11335 if (end > duration) { 11336 end = duration; 11337 } 11338 11339 return end; 11340 }; 11341 11342 /** 11343 * Get or set the current volume of the media 11344 * ```js 11345 * // get 11346 * var howLoudIsIt = myPlayer.volume(); 11347 * // set 11348 * myPlayer.volume(0.5); // Set volume to half 11349 * ``` 11350 * 0 is off (muted), 1.0 is all the way up, 0.5 is half way. 11351 * 11352 * @param {Number} percentAsDecimal The new volume as a decimal percent 11353 * @return {Number} The current volume when getting 11354 * @return {Player} self when setting 11355 * @method volume 11356 */ 11357 11358 Player.prototype.volume = function volume(percentAsDecimal) { 11359 var vol = undefined; 11360 11361 if (percentAsDecimal !== undefined) { 11362 vol = Math.max(0, Math.min(1, parseFloat(percentAsDecimal))); // Force value to between 0 and 1 11363 this.cache_.volume = vol; 11364 this.techCall_('setVolume', vol); 11365 11366 return this; 11367 } 11368 11369 // Default to 1 when returning current volume. 11370 vol = parseFloat(this.techGet_('volume')); 11371 return isNaN(vol) ? 1 : vol; 11372 }; 11373 11374 /** 11375 * Get the current muted state, or turn mute on or off 11376 * ```js 11377 * // get 11378 * var isVolumeMuted = myPlayer.muted(); 11379 * // set 11380 * myPlayer.muted(true); // mute the volume 11381 * ``` 11382 * 11383 * @param {Boolean=} muted True to mute, false to unmute 11384 * @return {Boolean} True if mute is on, false if not when getting 11385 * @return {Player} self when setting mute 11386 * @method muted 11387 */ 11388 11389 Player.prototype.muted = function muted(_muted) { 11390 if (_muted !== undefined) { 11391 this.techCall_('setMuted', _muted); 11392 return this; 11393 } 11394 return this.techGet_('muted') || false; // Default to false 11395 }; 11396 11397 // Check if current tech can support native fullscreen 11398 // (e.g. with built in controls like iOS, so not our flash swf) 11399 /** 11400 * Check to see if fullscreen is supported 11401 * 11402 * @return {Boolean} 11403 * @method supportsFullScreen 11404 */ 11405 11406 Player.prototype.supportsFullScreen = function supportsFullScreen() { 11407 return this.techGet_('supportsFullScreen') || false; 11408 }; 11409 11410 /** 11411 * Check if the player is in fullscreen mode 11412 * ```js 11413 * // get 11414 * var fullscreenOrNot = myPlayer.isFullscreen(); 11415 * // set 11416 * myPlayer.isFullscreen(true); // tell the player it's in fullscreen 11417 * ``` 11418 * NOTE: As of the latest HTML5 spec, isFullscreen is no longer an official 11419 * property and instead document.fullscreenElement is used. But isFullscreen is 11420 * still a valuable property for internal player workings. 11421 * 11422 * @param {Boolean=} isFS Update the player's fullscreen state 11423 * @return {Boolean} true if fullscreen false if not when getting 11424 * @return {Player} self when setting 11425 * @method isFullscreen 11426 */ 11427 11428 Player.prototype.isFullscreen = function isFullscreen(isFS) { 11429 if (isFS !== undefined) { 11430 this.isFullscreen_ = !!isFS; 11431 return this; 11432 } 11433 return !!this.isFullscreen_; 11434 }; 11435 11436 /** 11437 * Increase the size of the video to full screen 11438 * ```js 11439 * myPlayer.requestFullscreen(); 11440 * ``` 11441 * In some browsers, full screen is not supported natively, so it enters 11442 * "full window mode", where the video fills the browser window. 11443 * In browsers and devices that support native full screen, sometimes the 11444 * browser's default controls will be shown, and not the Video.js custom skin. 11445 * This includes most mobile devices (iOS, Android) and older versions of 11446 * Safari. 11447 * 11448 * @return {Player} self 11449 * @method requestFullscreen 11450 */ 11451 11452 Player.prototype.requestFullscreen = function requestFullscreen() { 11453 var fsApi = _fullscreenApiJs2['default']; 11454 11455 this.isFullscreen(true); 11456 11457 if (fsApi.requestFullscreen) { 11458 // the browser supports going fullscreen at the element level so we can 11459 // take the controls fullscreen as well as the video 11460 11461 // Trigger fullscreenchange event after change 11462 // We have to specifically add this each time, and remove 11463 // when canceling fullscreen. Otherwise if there's multiple 11464 // players on a page, they would all be reacting to the same fullscreen 11465 // events 11466 Events.on(_globalDocument2['default'], fsApi.fullscreenchange, Fn.bind(this, function documentFullscreenChange(e) { 11467 this.isFullscreen(_globalDocument2['default'][fsApi.fullscreenElement]); 11468 11469 // If cancelling fullscreen, remove event listener. 11470 if (this.isFullscreen() === false) { 11471 Events.off(_globalDocument2['default'], fsApi.fullscreenchange, documentFullscreenChange); 11472 } 11473 11474 this.trigger('fullscreenchange'); 11475 })); 11476 11477 this.el_[fsApi.requestFullscreen](); 11478 } else if (this.tech_.supportsFullScreen()) { 11479 // we can't take the video.js controls fullscreen but we can go fullscreen 11480 // with native controls 11481 this.techCall_('enterFullScreen'); 11482 } else { 11483 // fullscreen isn't supported so we'll just stretch the video element to 11484 // fill the viewport 11485 this.enterFullWindow(); 11486 this.trigger('fullscreenchange'); 11487 } 11488 11489 return this; 11490 }; 11491 11492 /** 11493 * Return the video to its normal size after having been in full screen mode 11494 * ```js 11495 * myPlayer.exitFullscreen(); 11496 * ``` 11497 * 11498 * @return {Player} self 11499 * @method exitFullscreen 11500 */ 11501 11502 Player.prototype.exitFullscreen = function exitFullscreen() { 11503 var fsApi = _fullscreenApiJs2['default']; 11504 this.isFullscreen(false); 11505 11506 // Check for browser element fullscreen support 11507 if (fsApi.requestFullscreen) { 11508 _globalDocument2['default'][fsApi.exitFullscreen](); 11509 } else if (this.tech_.supportsFullScreen()) { 11510 this.techCall_('exitFullScreen'); 11511 } else { 11512 this.exitFullWindow(); 11513 this.trigger('fullscreenchange'); 11514 } 11515 11516 return this; 11517 }; 11518 11519 /** 11520 * When fullscreen isn't supported we can stretch the video container to as wide as the browser will let us. 11521 * 11522 * @method enterFullWindow 11523 */ 11524 11525 Player.prototype.enterFullWindow = function enterFullWindow() { 11526 this.isFullWindow = true; 11527 11528 // Storing original doc overflow value to return to when fullscreen is off 11529 this.docOrigOverflow = _globalDocument2['default'].documentElement.style.overflow; 11530 11531 // Add listener for esc key to exit fullscreen 11532 Events.on(_globalDocument2['default'], 'keydown', Fn.bind(this, this.fullWindowOnEscKey)); 11533 11534 // Hide any scroll bars 11535 _globalDocument2['default'].documentElement.style.overflow = 'hidden'; 11536 11537 // Apply fullscreen styles 11538 Dom.addElClass(_globalDocument2['default'].body, 'vjs-full-window'); 11539 11540 this.trigger('enterFullWindow'); 11541 }; 11542 11543 /** 11544 * Check for call to either exit full window or full screen on ESC key 11545 * 11546 * @param {String} event Event to check for key press 11547 * @method fullWindowOnEscKey 11548 */ 11549 11550 Player.prototype.fullWindowOnEscKey = function fullWindowOnEscKey(event) { 11551 if (event.keyCode === 27) { 11552 if (this.isFullscreen() === true) { 11553 this.exitFullscreen(); 11554 } else { 11555 this.exitFullWindow(); 11556 } 11557 } 11558 }; 11559 11560 /** 11561 * Exit full window 11562 * 11563 * @method exitFullWindow 11564 */ 11565 11566 Player.prototype.exitFullWindow = function exitFullWindow() { 11567 this.isFullWindow = false; 11568 Events.off(_globalDocument2['default'], 'keydown', this.fullWindowOnEscKey); 11569 11570 // Unhide scroll bars. 11571 _globalDocument2['default'].documentElement.style.overflow = this.docOrigOverflow; 11572 11573 // Remove fullscreen styles 11574 Dom.removeElClass(_globalDocument2['default'].body, 'vjs-full-window'); 11575 11576 // Resize the box, controller, and poster to original sizes 11577 // this.positionAll(); 11578 this.trigger('exitFullWindow'); 11579 }; 11580 11581 /** 11582 * Check whether the player can play a given mimetype 11583 * 11584 * @param {String} type The mimetype to check 11585 * @return {String} 'probably', 'maybe', or '' (empty string) 11586 * @method canPlayType 11587 */ 11588 11589 Player.prototype.canPlayType = function canPlayType(type) { 11590 var can = undefined; 11591 11592 // Loop through each playback technology in the options order 11593 for (var i = 0, j = this.options_.techOrder; i < j.length; i++) { 11594 var techName = _utilsToTitleCaseJs2['default'](j[i]); 11595 var tech = _techTechJs2['default'].getTech(techName); 11596 11597 // Support old behavior of techs being registered as components. 11598 // Remove once that deprecated behavior is removed. 11599 if (!tech) { 11600 tech = _componentJs2['default'].getComponent(techName); 11601 } 11602 11603 // Check if the current tech is defined before continuing 11604 if (!tech) { 11605 _utilsLogJs2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.'); 11606 continue; 11607 } 11608 11609 // Check if the browser supports this technology 11610 if (tech.isSupported()) { 11611 can = tech.canPlayType(type); 11612 11613 if (can) { 11614 return can; 11615 } 11616 } 11617 } 11618 11619 return ''; 11620 }; 11621 11622 /** 11623 * Select source based on tech-order or source-order 11624 * Uses source-order selection if `options.sourceOrder` is truthy. Otherwise, 11625 * defaults to tech-order selection 11626 * 11627 * @param {Array} sources The sources for a media asset 11628 * @return {Object|Boolean} Object of source and tech order, otherwise false 11629 * @method selectSource 11630 */ 11631 11632 Player.prototype.selectSource = function selectSource(sources) { 11633 // Get only the techs specified in `techOrder` that exist and are supported by the 11634 // current platform 11635 var techs = this.options_.techOrder.map(_utilsToTitleCaseJs2['default']).map(function (techName) { 11636 // `Component.getComponent(...)` is for support of old behavior of techs 11637 // being registered as components. 11638 // Remove once that deprecated behavior is removed. 11639 return [techName, _techTechJs2['default'].getTech(techName) || _componentJs2['default'].getComponent(techName)]; 11640 }).filter(function (_ref) { 11641 var techName = _ref[0]; 11642 var tech = _ref[1]; 11643 11644 // Check if the current tech is defined before continuing 11645 if (tech) { 11646 // Check if the browser supports this technology 11647 return tech.isSupported(); 11648 } 11649 11650 _utilsLogJs2['default'].error('The "' + techName + '" tech is undefined. Skipped browser support check for that tech.'); 11651 return false; 11652 }); 11653 11654 // Iterate over each `innerArray` element once per `outerArray` element and execute 11655 // `tester` with both. If `tester` returns a non-falsy value, exit early and return 11656 // that value. 11657 var findFirstPassingTechSourcePair = function findFirstPassingTechSourcePair(outerArray, innerArray, tester) { 11658 var found = undefined; 11659 11660 outerArray.some(function (outerChoice) { 11661 return innerArray.some(function (innerChoice) { 11662 found = tester(outerChoice, innerChoice); 11663 11664 if (found) { 11665 return true; 11666 } 11667 }); 11668 }); 11669 11670 return found; 11671 }; 11672 11673 var foundSourceAndTech = undefined; 11674 var flip = function flip(fn) { 11675 return function (a, b) { 11676 return fn(b, a); 11677 }; 11678 }; 11679 var finder = function finder(_ref2, source) { 11680 var techName = _ref2[0]; 11681 var tech = _ref2[1]; 11682 11683 if (tech.canPlaySource(source)) { 11684 return { source: source, tech: techName }; 11685 } 11686 }; 11687 11688 // Depending on the truthiness of `options.sourceOrder`, we swap the order of techs and sources 11689 // to select from them based on their priority. 11690 if (this.options_.sourceOrder) { 11691 // Source-first ordering 11692 foundSourceAndTech = findFirstPassingTechSourcePair(sources, techs, flip(finder)); 11693 } else { 11694 // Tech-first ordering 11695 foundSourceAndTech = findFirstPassingTechSourcePair(techs, sources, finder); 11696 } 11697 11698 return foundSourceAndTech || false; 11699 }; 11700 11701 /** 11702 * The source function updates the video source 11703 * There are three types of variables you can pass as the argument. 11704 * **URL String**: A URL to the the video file. Use this method if you are sure 11705 * the current playback technology (HTML5/Flash) can support the source you 11706 * provide. Currently only MP4 files can be used in both HTML5 and Flash. 11707 * ```js 11708 * myPlayer.src("http://www.example.com/path/to/video.mp4"); 11709 * ``` 11710 * **Source Object (or element):* * A javascript object containing information 11711 * about the source file. Use this method if you want the player to determine if 11712 * it can support the file using the type information. 11713 * ```js 11714 * myPlayer.src({ type: "video/mp4", src: "http://www.example.com/path/to/video.mp4" }); 11715 * ``` 11716 * **Array of Source Objects:* * To provide multiple versions of the source so 11717 * that it can be played using HTML5 across browsers you can use an array of 11718 * source objects. Video.js will detect which version is supported and load that 11719 * file. 11720 * ```js 11721 * myPlayer.src([ 11722 * { type: "video/mp4", src: "http://www.example.com/path/to/video.mp4" }, 11723 * { type: "video/webm", src: "http://www.example.com/path/to/video.webm" }, 11724 * { type: "video/ogg", src: "http://www.example.com/path/to/video.ogv" } 11725 * ]); 11726 * ``` 11727 * 11728 * @param {String|Object|Array=} source The source URL, object, or array of sources 11729 * @return {String} The current video source when getting 11730 * @return {String} The player when setting 11731 * @method src 11732 */ 11733 11734 Player.prototype.src = function src(source) { 11735 if (source === undefined) { 11736 return this.techGet_('src'); 11737 } 11738 11739 var currentTech = _techTechJs2['default'].getTech(this.techName_); 11740 // Support old behavior of techs being registered as components. 11741 // Remove once that deprecated behavior is removed. 11742 if (!currentTech) { 11743 currentTech = _componentJs2['default'].getComponent(this.techName_); 11744 } 11745 11746 // case: Array of source objects to choose from and pick the best to play 11747 if (Array.isArray(source)) { 11748 this.sourceList_(source); 11749 11750 // case: URL String (http://myvideo...) 11751 } else if (typeof source === 'string') { 11752 // create a source object from the string 11753 this.src({ src: source }); 11754 11755 // case: Source object { src: '', type: '' ... } 11756 } else if (source instanceof Object) { 11757 // check if the source has a type and the loaded tech cannot play the source 11758 // if there's no type we'll just try the current tech 11759 if (source.type && !currentTech.canPlaySource(source)) { 11760 // create a source list with the current source and send through 11761 // the tech loop to check for a compatible technology 11762 this.sourceList_([source]); 11763 } else { 11764 this.cache_.src = source.src; 11765 this.currentType_ = source.type || ''; 11766 11767 // wait until the tech is ready to set the source 11768 this.ready(function () { 11769 11770 // The setSource tech method was added with source handlers 11771 // so older techs won't support it 11772 // We need to check the direct prototype for the case where subclasses 11773 // of the tech do not support source handlers 11774 if (currentTech.prototype.hasOwnProperty('setSource')) { 11775 this.techCall_('setSource', source); 11776 } else { 11777 this.techCall_('src', source.src); 11778 } 11779 11780 if (this.options_.preload === 'auto') { 11781 this.load(); 11782 } 11783 11784 if (this.options_.autoplay) { 11785 this.play(); 11786 } 11787 11788 // Set the source synchronously if possible (#2326) 11789 }, true); 11790 } 11791 } 11792 11793 return this; 11794 }; 11795 11796 /** 11797 * Handle an array of source objects 11798 * 11799 * @param {Array} sources Array of source objects 11800 * @private 11801 * @method sourceList_ 11802 */ 11803 11804 Player.prototype.sourceList_ = function sourceList_(sources) { 11805 var sourceTech = this.selectSource(sources); 11806 11807 if (sourceTech) { 11808 if (sourceTech.tech === this.techName_) { 11809 // if this technology is already loaded, set the source 11810 this.src(sourceTech.source); 11811 } else { 11812 // load this technology with the chosen source 11813 this.loadTech_(sourceTech.tech, sourceTech.source); 11814 } 11815 } else { 11816 // We need to wrap this in a timeout to give folks a chance to add error event handlers 11817 this.setTimeout(function () { 11818 this.error({ code: 4, message: this.localize(this.options_.notSupportedMessage) }); 11819 }, 0); 11820 11821 // we could not find an appropriate tech, but let's still notify the delegate that this is it 11822 // this needs a better comment about why this is needed 11823 this.triggerReady(); 11824 } 11825 }; 11826 11827 /** 11828 * Begin loading the src data. 11829 * 11830 * @return {Player} Returns the player 11831 * @method load 11832 */ 11833 11834 Player.prototype.load = function load() { 11835 this.techCall_('load'); 11836 return this; 11837 }; 11838 11839 /** 11840 * Reset the player. Loads the first tech in the techOrder, 11841 * and calls `reset` on the tech`. 11842 * 11843 * @return {Player} Returns the player 11844 * @method reset 11845 */ 11846 11847 Player.prototype.reset = function reset() { 11848 this.loadTech_(_utilsToTitleCaseJs2['default'](this.options_.techOrder[0]), null); 11849 this.techCall_('reset'); 11850 return this; 11851 }; 11852 11853 /** 11854 * Returns the fully qualified URL of the current source value e.g. http://mysite.com/video.mp4 11855 * Can be used in conjuction with `currentType` to assist in rebuilding the current source object. 11856 * 11857 * @return {String} The current source 11858 * @method currentSrc 11859 */ 11860 11861 Player.prototype.currentSrc = function currentSrc() { 11862 return this.techGet_('currentSrc') || this.cache_.src || ''; 11863 }; 11864 11865 /** 11866 * Get the current source type e.g. video/mp4 11867 * This can allow you rebuild the current source object so that you could load the same 11868 * source and tech later 11869 * 11870 * @return {String} The source MIME type 11871 * @method currentType 11872 */ 11873 11874 Player.prototype.currentType = function currentType() { 11875 return this.currentType_ || ''; 11876 }; 11877 11878 /** 11879 * Get or set the preload attribute 11880 * 11881 * @param {Boolean} value Boolean to determine if preload should be used 11882 * @return {String} The preload attribute value when getting 11883 * @return {Player} Returns the player when setting 11884 * @method preload 11885 */ 11886 11887 Player.prototype.preload = function preload(value) { 11888 if (value !== undefined) { 11889 this.techCall_('setPreload', value); 11890 this.options_.preload = value; 11891 return this; 11892 } 11893 return this.techGet_('preload'); 11894 }; 11895 11896 /** 11897 * Get or set the autoplay attribute. 11898 * 11899 * @param {Boolean} value Boolean to determine if video should autoplay 11900 * @return {String} The autoplay attribute value when getting 11901 * @return {Player} Returns the player when setting 11902 * @method autoplay 11903 */ 11904 11905 Player.prototype.autoplay = function autoplay(value) { 11906 if (value !== undefined) { 11907 this.techCall_('setAutoplay', value); 11908 this.options_.autoplay = value; 11909 return this; 11910 } 11911 return this.techGet_('autoplay', value); 11912 }; 11913 11914 /** 11915 * Get or set the loop attribute on the video element. 11916 * 11917 * @param {Boolean} value Boolean to determine if video should loop 11918 * @return {String} The loop attribute value when getting 11919 * @return {Player} Returns the player when setting 11920 * @method loop 11921 */ 11922 11923 Player.prototype.loop = function loop(value) { 11924 if (value !== undefined) { 11925 this.techCall_('setLoop', value); 11926 this.options_['loop'] = value; 11927 return this; 11928 } 11929 return this.techGet_('loop'); 11930 }; 11931 11932 /** 11933 * Get or set the poster image source url 11934 * 11935 * ##### EXAMPLE: 11936 * ```js 11937 * // get 11938 * var currentPoster = myPlayer.poster(); 11939 * // set 11940 * myPlayer.poster('http://example.com/myImage.jpg'); 11941 * ``` 11942 * 11943 * @param {String=} src Poster image source URL 11944 * @return {String} poster URL when getting 11945 * @return {Player} self when setting 11946 * @method poster 11947 */ 11948 11949 Player.prototype.poster = function poster(src) { 11950 if (src === undefined) { 11951 return this.poster_; 11952 } 11953 11954 // The correct way to remove a poster is to set as an empty string 11955 // other falsey values will throw errors 11956 if (!src) { 11957 src = ''; 11958 } 11959 11960 // update the internal poster variable 11961 this.poster_ = src; 11962 11963 // update the tech's poster 11964 this.techCall_('setPoster', src); 11965 11966 // alert components that the poster has been set 11967 this.trigger('posterchange'); 11968 11969 return this; 11970 }; 11971 11972 /** 11973 * Some techs (e.g. YouTube) can provide a poster source in an 11974 * asynchronous way. We want the poster component to use this 11975 * poster source so that it covers up the tech's controls. 11976 * (YouTube's play button). However we only want to use this 11977 * soruce if the player user hasn't set a poster through 11978 * the normal APIs. 11979 * 11980 * @private 11981 * @method handleTechPosterChange_ 11982 */ 11983 11984 Player.prototype.handleTechPosterChange_ = function handleTechPosterChange_() { 11985 if (!this.poster_ && this.tech_ && this.tech_.poster) { 11986 this.poster_ = this.tech_.poster() || ''; 11987 11988 // Let components know the poster has changed 11989 this.trigger('posterchange'); 11990 } 11991 }; 11992 11993 /** 11994 * Get or set whether or not the controls are showing. 11995 * 11996 * @param {Boolean} bool Set controls to showing or not 11997 * @return {Boolean} Controls are showing 11998 * @method controls 11999 */ 12000 12001 Player.prototype.controls = function controls(bool) { 12002 if (bool !== undefined) { 12003 bool = !!bool; // force boolean 12004 // Don't trigger a change event unless it actually changed 12005 if (this.controls_ !== bool) { 12006 this.controls_ = bool; 12007 12008 if (this.usingNativeControls()) { 12009 this.techCall_('setControls', bool); 12010 } 12011 12012 if (bool) { 12013 this.removeClass('vjs-controls-disabled'); 12014 this.addClass('vjs-controls-enabled'); 12015 this.trigger('controlsenabled'); 12016 12017 if (!this.usingNativeControls()) { 12018 this.addTechControlsListeners_(); 12019 } 12020 } else { 12021 this.removeClass('vjs-controls-enabled'); 12022 this.addClass('vjs-controls-disabled'); 12023 this.trigger('controlsdisabled'); 12024 12025 if (!this.usingNativeControls()) { 12026 this.removeTechControlsListeners_(); 12027 } 12028 } 12029 } 12030 return this; 12031 } 12032 return !!this.controls_; 12033 }; 12034 12035 /** 12036 * Toggle native controls on/off. Native controls are the controls built into 12037 * devices (e.g. default iPhone controls), Flash, or other techs 12038 * (e.g. Vimeo Controls) 12039 * **This should only be set by the current tech, because only the tech knows 12040 * if it can support native controls** 12041 * 12042 * @param {Boolean} bool True signals that native controls are on 12043 * @return {Player} Returns the player 12044 * @private 12045 * @method usingNativeControls 12046 */ 12047 12048 Player.prototype.usingNativeControls = function usingNativeControls(bool) { 12049 if (bool !== undefined) { 12050 bool = !!bool; // force boolean 12051 // Don't trigger a change event unless it actually changed 12052 if (this.usingNativeControls_ !== bool) { 12053 this.usingNativeControls_ = bool; 12054 if (bool) { 12055 this.addClass('vjs-using-native-controls'); 12056 12057 /** 12058 * player is using the native device controls 12059 * 12060 * @event usingnativecontrols 12061 * @memberof Player 12062 * @instance 12063 * @private 12064 */ 12065 this.trigger('usingnativecontrols'); 12066 } else { 12067 this.removeClass('vjs-using-native-controls'); 12068 12069 /** 12070 * player is using the custom HTML controls 12071 * 12072 * @event usingcustomcontrols 12073 * @memberof Player 12074 * @instance 12075 * @private 12076 */ 12077 this.trigger('usingcustomcontrols'); 12078 } 12079 } 12080 return this; 12081 } 12082 return !!this.usingNativeControls_; 12083 }; 12084 12085 /** 12086 * Set or get the current MediaError 12087 * 12088 * @param {*} err A MediaError or a String/Number to be turned into a MediaError 12089 * @return {MediaError|null} when getting 12090 * @return {Player} when setting 12091 * @method error 12092 */ 12093 12094 Player.prototype.error = function error(err) { 12095 if (err === undefined) { 12096 return this.error_ || null; 12097 } 12098 12099 // restoring to default 12100 if (err === null) { 12101 this.error_ = err; 12102 this.removeClass('vjs-error'); 12103 this.errorDisplay.close(); 12104 return this; 12105 } 12106 12107 // error instance 12108 if (err instanceof _mediaErrorJs2['default']) { 12109 this.error_ = err; 12110 } else { 12111 this.error_ = new _mediaErrorJs2['default'](err); 12112 } 12113 12114 // add the vjs-error classname to the player 12115 this.addClass('vjs-error'); 12116 12117 // log the name of the error type and any message 12118 // ie8 just logs "[object object]" if you just log the error object 12119 _utilsLogJs2['default'].error('(CODE:' + this.error_.code + ' ' + _mediaErrorJs2['default'].errorTypes[this.error_.code] + ')', this.error_.message, this.error_); 12120 12121 // fire an error event on the player 12122 this.trigger('error'); 12123 12124 return this; 12125 }; 12126 12127 /** 12128 * Returns whether or not the player is in the "ended" state. 12129 * 12130 * @return {Boolean} True if the player is in the ended state, false if not. 12131 * @method ended 12132 */ 12133 12134 Player.prototype.ended = function ended() { 12135 return this.techGet_('ended'); 12136 }; 12137 12138 /** 12139 * Returns whether or not the player is in the "seeking" state. 12140 * 12141 * @return {Boolean} True if the player is in the seeking state, false if not. 12142 * @method seeking 12143 */ 12144 12145 Player.prototype.seeking = function seeking() { 12146 return this.techGet_('seeking'); 12147 }; 12148 12149 /** 12150 * Returns the TimeRanges of the media that are currently available 12151 * for seeking to. 12152 * 12153 * @return {TimeRanges} the seekable intervals of the media timeline 12154 * @method seekable 12155 */ 12156 12157 Player.prototype.seekable = function seekable() { 12158 return this.techGet_('seekable'); 12159 }; 12160 12161 /** 12162 * Report user activity 12163 * 12164 * @param {Object} event Event object 12165 * @method reportUserActivity 12166 */ 12167 12168 Player.prototype.reportUserActivity = function reportUserActivity(event) { 12169 this.userActivity_ = true; 12170 }; 12171 12172 /** 12173 * Get/set if user is active 12174 * 12175 * @param {Boolean} bool Value when setting 12176 * @return {Boolean} Value if user is active user when getting 12177 * @method userActive 12178 */ 12179 12180 Player.prototype.userActive = function userActive(bool) { 12181 if (bool !== undefined) { 12182 bool = !!bool; 12183 if (bool !== this.userActive_) { 12184 this.userActive_ = bool; 12185 if (bool) { 12186 // If the user was inactive and is now active we want to reset the 12187 // inactivity timer 12188 this.userActivity_ = true; 12189 this.removeClass('vjs-user-inactive'); 12190 this.addClass('vjs-user-active'); 12191 this.trigger('useractive'); 12192 } else { 12193 // We're switching the state to inactive manually, so erase any other 12194 // activity 12195 this.userActivity_ = false; 12196 12197 // Chrome/Safari/IE have bugs where when you change the cursor it can 12198 // trigger a mousemove event. This causes an issue when you're hiding 12199 // the cursor when the user is inactive, and a mousemove signals user 12200 // activity. Making it impossible to go into inactive mode. Specifically 12201 // this happens in fullscreen when we really need to hide the cursor. 12202 // 12203 // When this gets resolved in ALL browsers it can be removed 12204 // https://code.google.com/p/chromium/issues/detail?id=103041 12205 if (this.tech_) { 12206 this.tech_.one('mousemove', function (e) { 12207 e.stopPropagation(); 12208 e.preventDefault(); 12209 }); 12210 } 12211 12212 this.removeClass('vjs-user-active'); 12213 this.addClass('vjs-user-inactive'); 12214 this.trigger('userinactive'); 12215 } 12216 } 12217 return this; 12218 } 12219 return this.userActive_; 12220 }; 12221 12222 /** 12223 * Listen for user activity based on timeout value 12224 * 12225 * @private 12226 * @method listenForUserActivity_ 12227 */ 12228 12229 Player.prototype.listenForUserActivity_ = function listenForUserActivity_() { 12230 var mouseInProgress = undefined, 12231 lastMoveX = undefined, 12232 lastMoveY = undefined; 12233 12234 var handleActivity = Fn.bind(this, this.reportUserActivity); 12235 12236 var handleMouseMove = function handleMouseMove(e) { 12237 // #1068 - Prevent mousemove spamming 12238 // Chrome Bug: https://code.google.com/p/chromium/issues/detail?id=366970 12239 if (e.screenX !== lastMoveX || e.screenY !== lastMoveY) { 12240 lastMoveX = e.screenX; 12241 lastMoveY = e.screenY; 12242 handleActivity(); 12243 } 12244 }; 12245 12246 var handleMouseDown = function handleMouseDown() { 12247 handleActivity(); 12248 // For as long as the they are touching the device or have their mouse down, 12249 // we consider them active even if they're not moving their finger or mouse. 12250 // So we want to continue to update that they are active 12251 this.clearInterval(mouseInProgress); 12252 // Setting userActivity=true now and setting the interval to the same time 12253 // as the activityCheck interval (250) should ensure we never miss the 12254 // next activityCheck 12255 mouseInProgress = this.setInterval(handleActivity, 250); 12256 }; 12257 12258 var handleMouseUp = function handleMouseUp(event) { 12259 handleActivity(); 12260 // Stop the interval that maintains activity if the mouse/touch is down 12261 this.clearInterval(mouseInProgress); 12262 }; 12263 12264 // Any mouse movement will be considered user activity 12265 this.on('mousedown', handleMouseDown); 12266 this.on('mousemove', handleMouseMove); 12267 this.on('mouseup', handleMouseUp); 12268 12269 // Listen for keyboard navigation 12270 // Shouldn't need to use inProgress interval because of key repeat 12271 this.on('keydown', handleActivity); 12272 this.on('keyup', handleActivity); 12273 12274 // Run an interval every 250 milliseconds instead of stuffing everything into 12275 // the mousemove/touchmove function itself, to prevent performance degradation. 12276 // `this.reportUserActivity` simply sets this.userActivity_ to true, which 12277 // then gets picked up by this loop 12278 // http://ejohn.org/blog/learning-from-twitter/ 12279 var inactivityTimeout = undefined; 12280 var activityCheck = this.setInterval(function () { 12281 // Check to see if mouse/touch activity has happened 12282 if (this.userActivity_) { 12283 // Reset the activity tracker 12284 this.userActivity_ = false; 12285 12286 // If the user state was inactive, set the state to active 12287 this.userActive(true); 12288 12289 // Clear any existing inactivity timeout to start the timer over 12290 this.clearTimeout(inactivityTimeout); 12291 12292 var timeout = this.options_['inactivityTimeout']; 12293 if (timeout > 0) { 12294 // In <timeout> milliseconds, if no more activity has occurred the 12295 // user will be considered inactive 12296 inactivityTimeout = this.setTimeout(function () { 12297 // Protect against the case where the inactivityTimeout can trigger just 12298 // before the next user activity is picked up by the activityCheck loop 12299 // causing a flicker 12300 if (!this.userActivity_) { 12301 this.userActive(false); 12302 } 12303 }, timeout); 12304 } 12305 } 12306 }, 250); 12307 }; 12308 12309 /** 12310 * Gets or sets the current playback rate. A playback rate of 12311 * 1.0 represents normal speed and 0.5 would indicate half-speed 12312 * playback, for instance. 12313 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-playbackrate 12314 * 12315 * @param {Number} rate New playback rate to set. 12316 * @return {Number} Returns the new playback rate when setting 12317 * @return {Number} Returns the current playback rate when getting 12318 * @method playbackRate 12319 */ 12320 12321 Player.prototype.playbackRate = function playbackRate(rate) { 12322 if (rate !== undefined) { 12323 this.techCall_('setPlaybackRate', rate); 12324 return this; 12325 } 12326 12327 if (this.tech_ && this.tech_['featuresPlaybackRate']) { 12328 return this.techGet_('playbackRate'); 12329 } else { 12330 return 1.0; 12331 } 12332 }; 12333 12334 /** 12335 * Gets or sets the audio flag 12336 * 12337 * @param {Boolean} bool True signals that this is an audio player. 12338 * @return {Boolean} Returns true if player is audio, false if not when getting 12339 * @return {Player} Returns the player if setting 12340 * @private 12341 * @method isAudio 12342 */ 12343 12344 Player.prototype.isAudio = function isAudio(bool) { 12345 if (bool !== undefined) { 12346 this.isAudio_ = !!bool; 12347 return this; 12348 } 12349 12350 return !!this.isAudio_; 12351 }; 12352 12353 /** 12354 * Returns the current state of network activity for the element, from 12355 * the codes in the list below. 12356 * - NETWORK_EMPTY (numeric value 0) 12357 * The element has not yet been initialised. All attributes are in 12358 * their initial states. 12359 * - NETWORK_IDLE (numeric value 1) 12360 * The element's resource selection algorithm is active and has 12361 * selected a resource, but it is not actually using the network at 12362 * this time. 12363 * - NETWORK_LOADING (numeric value 2) 12364 * The user agent is actively trying to download data. 12365 * - NETWORK_NO_SOURCE (numeric value 3) 12366 * The element's resource selection algorithm is active, but it has 12367 * not yet found a resource to use. 12368 * 12369 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#network-states 12370 * @return {Number} the current network activity state 12371 * @method networkState 12372 */ 12373 12374 Player.prototype.networkState = function networkState() { 12375 return this.techGet_('networkState'); 12376 }; 12377 12378 /** 12379 * Returns a value that expresses the current state of the element 12380 * with respect to rendering the current playback position, from the 12381 * codes in the list below. 12382 * - HAVE_NOTHING (numeric value 0) 12383 * No information regarding the media resource is available. 12384 * - HAVE_METADATA (numeric value 1) 12385 * Enough of the resource has been obtained that the duration of the 12386 * resource is available. 12387 * - HAVE_CURRENT_DATA (numeric value 2) 12388 * Data for the immediate current playback position is available. 12389 * - HAVE_FUTURE_DATA (numeric value 3) 12390 * Data for the immediate current playback position is available, as 12391 * well as enough data for the user agent to advance the current 12392 * playback position in the direction of playback. 12393 * - HAVE_ENOUGH_DATA (numeric value 4) 12394 * The user agent estimates that enough data is available for 12395 * playback to proceed uninterrupted. 12396 * 12397 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-readystate 12398 * @return {Number} the current playback rendering state 12399 * @method readyState 12400 */ 12401 12402 Player.prototype.readyState = function readyState() { 12403 return this.techGet_('readyState'); 12404 }; 12405 12406 /** 12407 * Text tracks are tracks of timed text events. 12408 * Captions - text displayed over the video for the hearing impaired 12409 * Subtitles - text displayed over the video for those who don't understand language in the video 12410 * Chapters - text displayed in a menu allowing the user to jump to particular points (chapters) in the video 12411 * Descriptions - audio descriptions that are read back to the user by a screen reading device 12412 */ 12413 12414 /** 12415 * Get an array of associated text tracks. captions, subtitles, chapters, descriptions 12416 * http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-texttracks 12417 * 12418 * @return {Array} Array of track objects 12419 * @method textTracks 12420 */ 12421 12422 Player.prototype.textTracks = function textTracks() { 12423 // cannot use techGet_ directly because it checks to see whether the tech is ready. 12424 // Flash is unlikely to be ready in time but textTracks should still work. 12425 return this.tech_ && this.tech_['textTracks'](); 12426 }; 12427 12428 /** 12429 * Get an array of remote text tracks 12430 * 12431 * @return {Array} 12432 * @method remoteTextTracks 12433 */ 12434 12435 Player.prototype.remoteTextTracks = function remoteTextTracks() { 12436 return this.tech_ && this.tech_['remoteTextTracks'](); 12437 }; 12438 12439 /** 12440 * Get an array of remote html track elements 12441 * 12442 * @return {HTMLTrackElement[]} 12443 * @method remoteTextTrackEls 12444 */ 12445 12446 Player.prototype.remoteTextTrackEls = function remoteTextTrackEls() { 12447 return this.tech_ && this.tech_['remoteTextTrackEls'](); 12448 }; 12449 12450 /** 12451 * Add a text track 12452 * In addition to the W3C settings we allow adding additional info through options. 12453 * http://www.w3.org/html/wg/drafts/html/master/embedded-content-0.html#dom-media-addtexttrack 12454 * 12455 * @param {String} kind Captions, subtitles, chapters, descriptions, or metadata 12456 * @param {String=} label Optional label 12457 * @param {String=} language Optional language 12458 * @method addTextTrack 12459 */ 12460 12461 Player.prototype.addTextTrack = function addTextTrack(kind, label, language) { 12462 return this.tech_ && this.tech_['addTextTrack'](kind, label, language); 12463 }; 12464 12465 /** 12466 * Add a remote text track 12467 * 12468 * @param {Object} options Options for remote text track 12469 * @method addRemoteTextTrack 12470 */ 12471 12472 Player.prototype.addRemoteTextTrack = function addRemoteTextTrack(options) { 12473 return this.tech_ && this.tech_['addRemoteTextTrack'](options); 12474 }; 12475 12476 /** 12477 * Remove a remote text track 12478 * 12479 * @param {Object} track Remote text track to remove 12480 * @method removeRemoteTextTrack 12481 */ 12482 12483 Player.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) { 12484 this.tech_ && this.tech_['removeRemoteTextTrack'](track); 12485 }; 12486 12487 /** 12488 * Get video width 12489 * 12490 * @return {Number} Video width 12491 * @method videoWidth 12492 */ 12493 12494 Player.prototype.videoWidth = function videoWidth() { 12495 return this.tech_ && this.tech_.videoWidth && this.tech_.videoWidth() || 0; 12496 }; 12497 12498 /** 12499 * Get video height 12500 * 12501 * @return {Number} Video height 12502 * @method videoHeight 12503 */ 12504 12505 Player.prototype.videoHeight = function videoHeight() { 12506 return this.tech_ && this.tech_.videoHeight && this.tech_.videoHeight() || 0; 12507 }; 12508 12509 // Methods to add support for 12510 // initialTime: function(){ return this.techCall_('initialTime'); }, 12511 // startOffsetTime: function(){ return this.techCall_('startOffsetTime'); }, 12512 // played: function(){ return this.techCall_('played'); }, 12513 // videoTracks: function(){ return this.techCall_('videoTracks'); }, 12514 // audioTracks: function(){ return this.techCall_('audioTracks'); }, 12515 // defaultPlaybackRate: function(){ return this.techCall_('defaultPlaybackRate'); }, 12516 // defaultMuted: function(){ return this.techCall_('defaultMuted'); } 12517 12518 /** 12519 * The player's language code 12520 * NOTE: The language should be set in the player options if you want the 12521 * the controls to be built with a specific language. Changing the lanugage 12522 * later will not update controls text. 12523 * 12524 * @param {String} code The locale string 12525 * @return {String} The locale string when getting 12526 * @return {Player} self when setting 12527 * @method language 12528 */ 12529 12530 Player.prototype.language = function language(code) { 12531 if (code === undefined) { 12532 return this.language_; 12533 } 12534 12535 this.language_ = ('' + code).toLowerCase(); 12536 return this; 12537 }; 12538 12539 /** 12540 * Get the player's language dictionary 12541 * Merge every time, because a newly added plugin might call videojs.addLanguage() at any time 12542 * Languages specified directly in the player options have precedence 12543 * 12544 * @return {Array} Array of languages 12545 * @method languages 12546 */ 12547 12548 Player.prototype.languages = function languages() { 12549 return _utilsMergeOptionsJs2['default'](Player.prototype.options_.languages, this.languages_); 12550 }; 12551 12552 /** 12553 * Converts track info to JSON 12554 * 12555 * @return {Object} JSON object of options 12556 * @method toJSON 12557 */ 12558 12559 Player.prototype.toJSON = function toJSON() { 12560 var options = _utilsMergeOptionsJs2['default'](this.options_); 12561 var tracks = options.tracks; 12562 12563 options.tracks = []; 12564 12565 for (var i = 0; i < tracks.length; i++) { 12566 var track = tracks[i]; 12567 12568 // deep merge tracks and null out player so no circular references 12569 track = _utilsMergeOptionsJs2['default'](track); 12570 track.player = undefined; 12571 options.tracks[i] = track; 12572 } 12573 12574 return options; 12575 }; 12576 12577 /** 12578 * Creates a simple modal dialog (an instance of the `ModalDialog` 12579 * component) that immediately overlays the player with arbitrary 12580 * content and removes itself when closed. 12581 * 12582 * @param {String|Function|Element|Array|Null} content 12583 * Same as `ModalDialog#content`'s param of the same name. 12584 * 12585 * The most straight-forward usage is to provide a string or DOM 12586 * element. 12587 * 12588 * @param {Object} [options] 12589 * Extra options which will be passed on to the `ModalDialog`. 12590 * 12591 * @return {ModalDialog} 12592 */ 12593 12594 Player.prototype.createModal = function createModal(content, options) { 12595 var player = this; 12596 12597 options = options || {}; 12598 options.content = content || ''; 12599 12600 var modal = new _modalDialog2['default'](player, options); 12601 12602 player.addChild(modal); 12603 modal.on('dispose', function () { 12604 player.removeChild(modal); 12605 }); 12606 12607 return modal.open(); 12608 }; 12609 12610 /** 12611 * Gets tag settings 12612 * 12613 * @param {Element} tag The player tag 12614 * @return {Array} An array of sources and track objects 12615 * @static 12616 * @method getTagSettings 12617 */ 12618 12619 Player.getTagSettings = function getTagSettings(tag) { 12620 var baseOptions = { 12621 'sources': [], 12622 'tracks': [] 12623 }; 12624 12625 var tagOptions = Dom.getElAttributes(tag); 12626 var dataSetup = tagOptions['data-setup']; 12627 12628 // Check if data-setup attr exists. 12629 if (dataSetup !== null) { 12630 // Parse options JSON 12631 12632 var _safeParseTuple = _safeJsonParseTuple2['default'](dataSetup || '{}'); 12633 12634 var err = _safeParseTuple[0]; 12635 var data = _safeParseTuple[1]; 12636 12637 if (err) { 12638 _utilsLogJs2['default'].error(err); 12639 } 12640 _objectAssign2['default'](tagOptions, data); 12641 } 12642 12643 _objectAssign2['default'](baseOptions, tagOptions); 12644 12645 // Get tag children settings 12646 if (tag.hasChildNodes()) { 12647 var children = tag.childNodes; 12648 12649 for (var i = 0, j = children.length; i < j; i++) { 12650 var child = children[i]; 12651 // Change case needed: http://ejohn.org/blog/nodename-case-sensitivity/ 12652 var childName = child.nodeName.toLowerCase(); 12653 if (childName === 'source') { 12654 baseOptions.sources.push(Dom.getElAttributes(child)); 12655 } else if (childName === 'track') { 12656 baseOptions.tracks.push(Dom.getElAttributes(child)); 12657 } 12658 } 12659 } 12660 12661 return baseOptions; 12662 }; 12663 12664 return Player; 12665 })(_componentJs2['default']); 12666 12667 Player.players = {}; 12668 12669 var navigator = _globalWindow2['default'].navigator; 12670 /* 12671 * Player instance options, surfaced using options 12672 * options = Player.prototype.options_ 12673 * Make changes in options, not here. 12674 * 12675 * @type {Object} 12676 * @private 12677 */ 12678 Player.prototype.options_ = { 12679 // Default order of fallback technology 12680 techOrder: ['html5', 'flash'], 12681 // techOrder: ['flash','html5'], 12682 12683 html5: {}, 12684 flash: {}, 12685 12686 // defaultVolume: 0.85, 12687 defaultVolume: 0.00, // The freakin seaguls are driving me crazy! 12688 12689 // default inactivity timeout 12690 inactivityTimeout: 2000, 12691 12692 // default playback rates 12693 playbackRates: [], 12694 // Add playback rate selection by adding rates 12695 // 'playbackRates': [0.5, 1, 1.5, 2], 12696 12697 // Included control sets 12698 children: ['mediaLoader', 'posterImage', 'textTrackDisplay', 'loadingSpinner', 'bigPlayButton', 'controlBar', 'errorDisplay', 'textTrackSettings'], 12699 12700 language: _globalDocument2['default'].getElementsByTagName('html')[0].getAttribute('lang') || navigator.languages && navigator.languages[0] || navigator.userLanguage || navigator.language || 'en', 12701 12702 // locales and their language translations 12703 languages: {}, 12704 12705 // Default message to show when a video cannot be played. 12706 notSupportedMessage: 'No compatible source was found for this media.' 12707 }; 12708 12709 /** 12710 * Fired when the player has initial duration and dimension information 12711 * 12712 * @event loadedmetadata 12713 */ 12714 Player.prototype.handleLoadedMetaData_; 12715 12716 /** 12717 * Fired when the player has downloaded data at the current playback position 12718 * 12719 * @event loadeddata 12720 */ 12721 Player.prototype.handleLoadedData_; 12722 12723 /** 12724 * Fired when the user is active, e.g. moves the mouse over the player 12725 * 12726 * @event useractive 12727 */ 12728 Player.prototype.handleUserActive_; 12729 12730 /** 12731 * Fired when the user is inactive, e.g. a short delay after the last mouse move or control interaction 12732 * 12733 * @event userinactive 12734 */ 12735 Player.prototype.handleUserInactive_; 12736 12737 /** 12738 * Fired when the current playback position has changed * 12739 * During playback this is fired every 15-250 milliseconds, depending on the 12740 * playback technology in use. 12741 * 12742 * @event timeupdate 12743 */ 12744 Player.prototype.handleTimeUpdate_; 12745 12746 /** 12747 * Fired when video playback ends 12748 * 12749 * @event ended 12750 */ 12751 Player.prototype.handleTechEnded_; 12752 12753 /** 12754 * Fired when the volume changes 12755 * 12756 * @event volumechange 12757 */ 12758 Player.prototype.handleVolumeChange_; 12759 12760 /** 12761 * Fired when an error occurs 12762 * 12763 * @event error 12764 */ 12765 Player.prototype.handleError_; 12766 12767 Player.prototype.flexNotSupported_ = function () { 12768 var elem = _globalDocument2['default'].createElement('i'); 12769 12770 // Note: We don't actually use flexBasis (or flexOrder), but it's one of the more 12771 // common flex features that we can rely on when checking for flex support. 12772 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) */; 12773 }; 12774 12775 _componentJs2['default'].registerComponent('Player', Player); 12776 exports['default'] = Player; 12777 module.exports = exports['default']; 12778 // If empty string, make it a parsable json object. 12779 12780 },{"./big-play-button.js":63,"./component.js":67,"./control-bar/control-bar.js":68,"./error-display.js":100,"./fullscreen-api.js":103,"./loading-spinner.js":104,"./media-error.js":105,"./modal-dialog":109,"./poster-image.js":114,"./tech/html5.js":119,"./tech/loader.js":120,"./tech/tech.js":121,"./tracks/text-track-display.js":125,"./tracks/text-track-list-converter.js":127,"./tracks/text-track-settings.js":129,"./utils/browser.js":131,"./utils/buffer.js":132,"./utils/dom.js":134,"./utils/events.js":135,"./utils/fn.js":136,"./utils/guid.js":138,"./utils/log.js":139,"./utils/merge-options.js":140,"./utils/stylesheet.js":141,"./utils/time-ranges.js":142,"./utils/to-title-case.js":143,"global/document":1,"global/window":2,"object.assign":45,"safe-json-parse/tuple":54}],111:[function(_dereq_,module,exports){ 12781 /** 12782 * @file plugins.js 12783 */ 12784 'use strict'; 12785 12786 exports.__esModule = true; 12787 12788 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12789 12790 var _playerJs = _dereq_('./player.js'); 12791 12792 var _playerJs2 = _interopRequireDefault(_playerJs); 12793 12794 /** 12795 * The method for registering a video.js plugin 12796 * 12797 * @param {String} name The name of the plugin 12798 * @param {Function} init The function that is run when the player inits 12799 * @method plugin 12800 */ 12801 var plugin = function plugin(name, init) { 12802 _playerJs2['default'].prototype[name] = init; 12803 }; 12804 12805 exports['default'] = plugin; 12806 module.exports = exports['default']; 12807 12808 },{"./player.js":110}],112:[function(_dereq_,module,exports){ 12809 /** 12810 * @file popup-button.js 12811 */ 12812 'use strict'; 12813 12814 exports.__esModule = true; 12815 12816 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; } } 12817 12818 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12819 12820 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 12821 12822 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; } 12823 12824 var _clickableComponentJs = _dereq_('../clickable-component.js'); 12825 12826 var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs); 12827 12828 var _componentJs = _dereq_('../component.js'); 12829 12830 var _componentJs2 = _interopRequireDefault(_componentJs); 12831 12832 var _popupJs = _dereq_('./popup.js'); 12833 12834 var _popupJs2 = _interopRequireDefault(_popupJs); 12835 12836 var _utilsDomJs = _dereq_('../utils/dom.js'); 12837 12838 var Dom = _interopRequireWildcard(_utilsDomJs); 12839 12840 var _utilsFnJs = _dereq_('../utils/fn.js'); 12841 12842 var Fn = _interopRequireWildcard(_utilsFnJs); 12843 12844 var _utilsToTitleCaseJs = _dereq_('../utils/to-title-case.js'); 12845 12846 var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs); 12847 12848 /** 12849 * A button class with a popup control 12850 * 12851 * @param {Player|Object} player 12852 * @param {Object=} options 12853 * @extends ClickableComponent 12854 * @class PopupButton 12855 */ 12856 12857 var PopupButton = (function (_ClickableComponent) { 12858 _inherits(PopupButton, _ClickableComponent); 12859 12860 function PopupButton(player) { 12861 var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 12862 12863 _classCallCheck(this, PopupButton); 12864 12865 _ClickableComponent.call(this, player, options); 12866 12867 this.update(); 12868 } 12869 12870 /** 12871 * Update popup 12872 * 12873 * @method update 12874 */ 12875 12876 PopupButton.prototype.update = function update() { 12877 var popup = this.createPopup(); 12878 12879 if (this.popup) { 12880 this.removeChild(this.popup); 12881 } 12882 12883 this.popup = popup; 12884 this.addChild(popup); 12885 12886 if (this.items && this.items.length === 0) { 12887 this.hide(); 12888 } else if (this.items && this.items.length > 1) { 12889 this.show(); 12890 } 12891 }; 12892 12893 /** 12894 * Create popup - Override with specific functionality for component 12895 * 12896 * @return {Popup} The constructed popup 12897 * @method createPopup 12898 */ 12899 12900 PopupButton.prototype.createPopup = function createPopup() {}; 12901 12902 /** 12903 * Create the component's DOM element 12904 * 12905 * @return {Element} 12906 * @method createEl 12907 */ 12908 12909 PopupButton.prototype.createEl = function createEl() { 12910 return _ClickableComponent.prototype.createEl.call(this, 'div', { 12911 className: this.buildCSSClass() 12912 }); 12913 }; 12914 12915 /** 12916 * Allow sub components to stack CSS class names 12917 * 12918 * @return {String} The constructed class name 12919 * @method buildCSSClass 12920 */ 12921 12922 PopupButton.prototype.buildCSSClass = function buildCSSClass() { 12923 var menuButtonClass = 'vjs-menu-button'; 12924 12925 // If the inline option is passed, we want to use different styles altogether. 12926 if (this.options_.inline === true) { 12927 menuButtonClass += '-inline'; 12928 } else { 12929 menuButtonClass += '-popup'; 12930 } 12931 12932 return 'vjs-menu-button ' + menuButtonClass + ' ' + _ClickableComponent.prototype.buildCSSClass.call(this); 12933 }; 12934 12935 return PopupButton; 12936 })(_clickableComponentJs2['default']); 12937 12938 _componentJs2['default'].registerComponent('PopupButton', PopupButton); 12939 exports['default'] = PopupButton; 12940 module.exports = exports['default']; 12941 12942 },{"../clickable-component.js":65,"../component.js":67,"../utils/dom.js":134,"../utils/fn.js":136,"../utils/to-title-case.js":143,"./popup.js":113}],113:[function(_dereq_,module,exports){ 12943 /** 12944 * @file popup.js 12945 */ 12946 'use strict'; 12947 12948 exports.__esModule = true; 12949 12950 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; } } 12951 12952 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12953 12954 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 12955 12956 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; } 12957 12958 var _componentJs = _dereq_('../component.js'); 12959 12960 var _componentJs2 = _interopRequireDefault(_componentJs); 12961 12962 var _utilsDomJs = _dereq_('../utils/dom.js'); 12963 12964 var Dom = _interopRequireWildcard(_utilsDomJs); 12965 12966 var _utilsFnJs = _dereq_('../utils/fn.js'); 12967 12968 var Fn = _interopRequireWildcard(_utilsFnJs); 12969 12970 var _utilsEventsJs = _dereq_('../utils/events.js'); 12971 12972 var Events = _interopRequireWildcard(_utilsEventsJs); 12973 12974 /** 12975 * The Popup component is used to build pop up controls. 12976 * 12977 * @extends Component 12978 * @class Popup 12979 */ 12980 12981 var Popup = (function (_Component) { 12982 _inherits(Popup, _Component); 12983 12984 function Popup() { 12985 _classCallCheck(this, Popup); 12986 12987 _Component.apply(this, arguments); 12988 } 12989 12990 /** 12991 * Add a popup item to the popup 12992 * 12993 * @param {Object|String} component Component or component type to add 12994 * @method addItem 12995 */ 12996 12997 Popup.prototype.addItem = function addItem(component) { 12998 this.addChild(component); 12999 component.on('click', Fn.bind(this, function () { 13000 this.unlockShowing(); 13001 })); 13002 }; 13003 13004 /** 13005 * Create the component's DOM element 13006 * 13007 * @return {Element} 13008 * @method createEl 13009 */ 13010 13011 Popup.prototype.createEl = function createEl() { 13012 var contentElType = this.options_.contentElType || 'ul'; 13013 this.contentEl_ = Dom.createEl(contentElType, { 13014 className: 'vjs-menu-content' 13015 }); 13016 var el = _Component.prototype.createEl.call(this, 'div', { 13017 append: this.contentEl_, 13018 className: 'vjs-menu' 13019 }); 13020 el.appendChild(this.contentEl_); 13021 13022 // Prevent clicks from bubbling up. Needed for Popup Buttons, 13023 // where a click on the parent is significant 13024 Events.on(el, 'click', function (event) { 13025 event.preventDefault(); 13026 event.stopImmediatePropagation(); 13027 }); 13028 13029 return el; 13030 }; 13031 13032 return Popup; 13033 })(_componentJs2['default']); 13034 13035 _componentJs2['default'].registerComponent('Popup', Popup); 13036 exports['default'] = Popup; 13037 module.exports = exports['default']; 13038 13039 },{"../component.js":67,"../utils/dom.js":134,"../utils/events.js":135,"../utils/fn.js":136}],114:[function(_dereq_,module,exports){ 13040 /** 13041 * @file poster-image.js 13042 */ 13043 'use strict'; 13044 13045 exports.__esModule = true; 13046 13047 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; } } 13048 13049 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 13050 13051 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 13052 13053 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; } 13054 13055 var _clickableComponentJs = _dereq_('./clickable-component.js'); 13056 13057 var _clickableComponentJs2 = _interopRequireDefault(_clickableComponentJs); 13058 13059 var _componentJs = _dereq_('./component.js'); 13060 13061 var _componentJs2 = _interopRequireDefault(_componentJs); 13062 13063 var _utilsFnJs = _dereq_('./utils/fn.js'); 13064 13065 var Fn = _interopRequireWildcard(_utilsFnJs); 13066 13067 var _utilsDomJs = _dereq_('./utils/dom.js'); 13068 13069 var Dom = _interopRequireWildcard(_utilsDomJs); 13070 13071 var _utilsBrowserJs = _dereq_('./utils/browser.js'); 13072 13073 var browser = _interopRequireWildcard(_utilsBrowserJs); 13074 13075 /** 13076 * The component that handles showing the poster image. 13077 * 13078 * @param {Player|Object} player 13079 * @param {Object=} options 13080 * @extends Button 13081 * @class PosterImage 13082 */ 13083 13084 var PosterImage = (function (_ClickableComponent) { 13085 _inherits(PosterImage, _ClickableComponent); 13086 13087 function PosterImage(player, options) { 13088 _classCallCheck(this, PosterImage); 13089 13090 _ClickableComponent.call(this, player, options); 13091 13092 this.update(); 13093 player.on('posterchange', Fn.bind(this, this.update)); 13094 } 13095 13096 /** 13097 * Clean up the poster image 13098 * 13099 * @method dispose 13100 */ 13101 13102 PosterImage.prototype.dispose = function dispose() { 13103 this.player().off('posterchange', this.update); 13104 _ClickableComponent.prototype.dispose.call(this); 13105 }; 13106 13107 /** 13108 * Create the poster's image element 13109 * 13110 * @return {Element} 13111 * @method createEl 13112 */ 13113 13114 PosterImage.prototype.createEl = function createEl() { 13115 var el = Dom.createEl('div', { 13116 className: 'vjs-poster', 13117 13118 // Don't want poster to be tabbable. 13119 tabIndex: -1 13120 }); 13121 13122 // To ensure the poster image resizes while maintaining its original aspect 13123 // ratio, use a div with `background-size` when available. For browsers that 13124 // do not support `background-size` (e.g. IE8), fall back on using a regular 13125 // img element. 13126 if (!browser.BACKGROUND_SIZE_SUPPORTED) { 13127 this.fallbackImg_ = Dom.createEl('img'); 13128 el.appendChild(this.fallbackImg_); 13129 } 13130 13131 return el; 13132 }; 13133 13134 /** 13135 * Event handler for updates to the player's poster source 13136 * 13137 * @method update 13138 */ 13139 13140 PosterImage.prototype.update = function update() { 13141 var url = this.player().poster(); 13142 13143 this.setSrc(url); 13144 13145 // If there's no poster source we should display:none on this component 13146 // so it's not still clickable or right-clickable 13147 if (url) { 13148 this.show(); 13149 } else { 13150 this.hide(); 13151 } 13152 }; 13153 13154 /** 13155 * Set the poster source depending on the display method 13156 * 13157 * @param {String} url The URL to the poster source 13158 * @method setSrc 13159 */ 13160 13161 PosterImage.prototype.setSrc = function setSrc(url) { 13162 if (this.fallbackImg_) { 13163 this.fallbackImg_.src = url; 13164 } else { 13165 var backgroundImage = ''; 13166 // Any falsey values should stay as an empty string, otherwise 13167 // this will throw an extra error 13168 if (url) { 13169 backgroundImage = 'url("' + url + '")'; 13170 } 13171 13172 this.el_.style.backgroundImage = backgroundImage; 13173 } 13174 }; 13175 13176 /** 13177 * Event handler for clicks on the poster image 13178 * 13179 * @method handleClick 13180 */ 13181 13182 PosterImage.prototype.handleClick = function handleClick() { 13183 // We don't want a click to trigger playback when controls are disabled 13184 // but CSS should be hiding the poster to prevent that from happening 13185 if (this.player_.paused()) { 13186 this.player_.play(); 13187 } else { 13188 this.player_.pause(); 13189 } 13190 }; 13191 13192 return PosterImage; 13193 })(_clickableComponentJs2['default']); 13194 13195 _componentJs2['default'].registerComponent('PosterImage', PosterImage); 13196 exports['default'] = PosterImage; 13197 module.exports = exports['default']; 13198 13199 },{"./clickable-component.js":65,"./component.js":67,"./utils/browser.js":131,"./utils/dom.js":134,"./utils/fn.js":136}],115:[function(_dereq_,module,exports){ 13200 /** 13201 * @file setup.js 13202 * 13203 * Functions for automatically setting up a player 13204 * based on the data-setup attribute of the video tag 13205 */ 13206 'use strict'; 13207 13208 exports.__esModule = true; 13209 13210 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 13211 13212 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; } } 13213 13214 var _utilsEventsJs = _dereq_('./utils/events.js'); 13215 13216 var Events = _interopRequireWildcard(_utilsEventsJs); 13217 13218 var _globalDocument = _dereq_('global/document'); 13219 13220 var _globalDocument2 = _interopRequireDefault(_globalDocument); 13221 13222 var _globalWindow = _dereq_('global/window'); 13223 13224 var _globalWindow2 = _interopRequireDefault(_globalWindow); 13225 13226 var _windowLoaded = false; 13227 var videojs = undefined; 13228 13229 // Automatically set up any tags that have a data-setup attribute 13230 var autoSetup = function autoSetup() { 13231 // One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack* 13232 // var vids = Array.prototype.slice.call(document.getElementsByTagName('video')); 13233 // var audios = Array.prototype.slice.call(document.getElementsByTagName('audio')); 13234 // var mediaEls = vids.concat(audios); 13235 13236 // Because IE8 doesn't support calling slice on a node list, we need to loop through each list of elements 13237 // to build up a new, combined list of elements. 13238 var vids = _globalDocument2['default'].getElementsByTagName('video'); 13239 var audios = _globalDocument2['default'].getElementsByTagName('audio'); 13240 var mediaEls = []; 13241 if (vids && vids.length > 0) { 13242 for (var i = 0, e = vids.length; i < e; i++) { 13243 mediaEls.push(vids[i]); 13244 } 13245 } 13246 if (audios && audios.length > 0) { 13247 for (var i = 0, e = audios.length; i < e; i++) { 13248 mediaEls.push(audios[i]); 13249 } 13250 } 13251 13252 // Check if any media elements exist 13253 if (mediaEls && mediaEls.length > 0) { 13254 13255 for (var i = 0, e = mediaEls.length; i < e; i++) { 13256 var mediaEl = mediaEls[i]; 13257 13258 // Check if element exists, has getAttribute func. 13259 // IE seems to consider typeof el.getAttribute == 'object' instead of 'function' like expected, at least when loading the player immediately. 13260 if (mediaEl && mediaEl.getAttribute) { 13261 13262 // Make sure this player hasn't already been set up. 13263 if (mediaEl['player'] === undefined) { 13264 var options = mediaEl.getAttribute('data-setup'); 13265 13266 // Check if data-setup attr exists. 13267 // We only auto-setup if they've added the data-setup attr. 13268 if (options !== null) { 13269 // Create new video.js instance. 13270 var player = videojs(mediaEl); 13271 } 13272 } 13273 13274 // If getAttribute isn't defined, we need to wait for the DOM. 13275 } else { 13276 autoSetupTimeout(1); 13277 break; 13278 } 13279 } 13280 13281 // No videos were found, so keep looping unless page is finished loading. 13282 } else if (!_windowLoaded) { 13283 autoSetupTimeout(1); 13284 } 13285 }; 13286 13287 // Pause to let the DOM keep processing 13288 var autoSetupTimeout = function autoSetupTimeout(wait, vjs) { 13289 if (vjs) { 13290 videojs = vjs; 13291 } 13292 13293 setTimeout(autoSetup, wait); 13294 }; 13295 13296 if (_globalDocument2['default'].readyState === 'complete') { 13297 _windowLoaded = true; 13298 } else { 13299 Events.one(_globalWindow2['default'], 'load', function () { 13300 _windowLoaded = true; 13301 }); 13302 } 13303 13304 var hasLoaded = function hasLoaded() { 13305 return _windowLoaded; 13306 }; 13307 13308 exports.autoSetup = autoSetup; 13309 exports.autoSetupTimeout = autoSetupTimeout; 13310 exports.hasLoaded = hasLoaded; 13311 13312 },{"./utils/events.js":135,"global/document":1,"global/window":2}],116:[function(_dereq_,module,exports){ 13313 /** 13314 * @file slider.js 13315 */ 13316 'use strict'; 13317 13318 exports.__esModule = true; 13319 13320 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; } } 13321 13322 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 13323 13324 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 13325 13326 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; } 13327 13328 var _componentJs = _dereq_('../component.js'); 13329 13330 var _componentJs2 = _interopRequireDefault(_componentJs); 13331 13332 var _utilsDomJs = _dereq_('../utils/dom.js'); 13333 13334 var Dom = _interopRequireWildcard(_utilsDomJs); 13335 13336 var _objectAssign = _dereq_('object.assign'); 13337 13338 var _objectAssign2 = _interopRequireDefault(_objectAssign); 13339 13340 /** 13341 * The base functionality for sliders like the volume bar and seek bar 13342 * 13343 * @param {Player|Object} player 13344 * @param {Object=} options 13345 * @extends Component 13346 * @class Slider 13347 */ 13348 13349 var Slider = (function (_Component) { 13350 _inherits(Slider, _Component); 13351 13352 function Slider(player, options) { 13353 _classCallCheck(this, Slider); 13354 13355 _Component.call(this, player, options); 13356 13357 // Set property names to bar to match with the child Slider class is looking for 13358 this.bar = this.getChild(this.options_.barName); 13359 13360 // Set a horizontal or vertical class on the slider depending on the slider type 13361 this.vertical(!!this.options_.vertical); 13362 13363 this.on('mousedown', this.handleMouseDown); 13364 this.on('touchstart', this.handleMouseDown); 13365 this.on('focus', this.handleFocus); 13366 this.on('blur', this.handleBlur); 13367 this.on('click', this.handleClick); 13368 13369 this.on(player, 'controlsvisible', this.update); 13370 this.on(player, this.playerEvent, this.update); 13371 } 13372 13373 /** 13374 * Create the component's DOM element 13375 * 13376 * @param {String} type Type of element to create 13377 * @param {Object=} props List of properties in Object form 13378 * @return {Element} 13379 * @method createEl 13380 */ 13381 13382 Slider.prototype.createEl = function createEl(type) { 13383 var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 13384 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; 13385 13386 // Add the slider element class to all sub classes 13387 props.className = props.className + ' vjs-slider'; 13388 props = _objectAssign2['default']({ 13389 tabIndex: 0 13390 }, props); 13391 13392 attributes = _objectAssign2['default']({ 13393 'role': 'slider', 13394 'aria-valuenow': 0, 13395 'aria-valuemin': 0, 13396 'aria-valuemax': 100, 13397 tabIndex: 0 13398 }, attributes); 13399 13400 return _Component.prototype.createEl.call(this, type, props, attributes); 13401 }; 13402 13403 /** 13404 * Handle mouse down on slider 13405 * 13406 * @param {Object} event Mouse down event object 13407 * @method handleMouseDown 13408 */ 13409 13410 Slider.prototype.handleMouseDown = function handleMouseDown(event) { 13411 var doc = this.bar.el_.ownerDocument; 13412 13413 event.preventDefault(); 13414 Dom.blockTextSelection(); 13415 13416 this.addClass('vjs-sliding'); 13417 this.trigger('slideractive'); 13418 13419 this.on(doc, 'mousemove', this.handleMouseMove); 13420 this.on(doc, 'mouseup', this.handleMouseUp); 13421 this.on(doc, 'touchmove', this.handleMouseMove); 13422 this.on(doc, 'touchend', this.handleMouseUp); 13423 13424 this.handleMouseMove(event); 13425 }; 13426 13427 /** 13428 * To be overridden by a subclass 13429 * 13430 * @method handleMouseMove 13431 */ 13432 13433 Slider.prototype.handleMouseMove = function handleMouseMove() {}; 13434 13435 /** 13436 * Handle mouse up on Slider 13437 * 13438 * @method handleMouseUp 13439 */ 13440 13441 Slider.prototype.handleMouseUp = function handleMouseUp() { 13442 var doc = this.bar.el_.ownerDocument; 13443 13444 Dom.unblockTextSelection(); 13445 13446 this.removeClass('vjs-sliding'); 13447 this.trigger('sliderinactive'); 13448 13449 this.off(doc, 'mousemove', this.handleMouseMove); 13450 this.off(doc, 'mouseup', this.handleMouseUp); 13451 this.off(doc, 'touchmove', this.handleMouseMove); 13452 this.off(doc, 'touchend', this.handleMouseUp); 13453 13454 this.update(); 13455 }; 13456 13457 /** 13458 * Update slider 13459 * 13460 * @method update 13461 */ 13462 13463 Slider.prototype.update = function update() { 13464 // In VolumeBar init we have a setTimeout for update that pops and update to the end of the 13465 // execution stack. The player is destroyed before then update will cause an error 13466 if (!this.el_) return; 13467 13468 // If scrubbing, we could use a cached value to make the handle keep up with the user's mouse. 13469 // On HTML5 browsers scrubbing is really smooth, but some flash players are slow, so we might want to utilize this later. 13470 // var progress = (this.player_.scrubbing()) ? this.player_.getCache().currentTime / this.player_.duration() : this.player_.currentTime() / this.player_.duration(); 13471 var progress = this.getPercent(); 13472 var bar = this.bar; 13473 13474 // If there's no bar... 13475 if (!bar) return; 13476 13477 // Protect against no duration and other division issues 13478 if (typeof progress !== 'number' || progress !== progress || progress < 0 || progress === Infinity) { 13479 progress = 0; 13480 } 13481 13482 // Convert to a percentage for setting 13483 var percentage = (progress * 100).toFixed(2) + '%'; 13484 13485 // Set the new bar width or height 13486 if (this.vertical()) { 13487 bar.el().style.height = percentage; 13488 } else { 13489 bar.el().style.width = percentage; 13490 } 13491 }; 13492 13493 /** 13494 * Calculate distance for slider 13495 * 13496 * @param {Object} event Event object 13497 * @method calculateDistance 13498 */ 13499 13500 Slider.prototype.calculateDistance = function calculateDistance(event) { 13501 var position = Dom.getPointerPosition(this.el_, event); 13502 if (this.vertical()) { 13503 return position.y; 13504 } 13505 return position.x; 13506 }; 13507 13508 /** 13509 * Handle on focus for slider 13510 * 13511 * @method handleFocus 13512 */ 13513 13514 Slider.prototype.handleFocus = function handleFocus() { 13515 this.on(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress); 13516 }; 13517 13518 /** 13519 * Handle key press for slider 13520 * 13521 * @param {Object} event Event object 13522 * @method handleKeyPress 13523 */ 13524 13525 Slider.prototype.handleKeyPress = function handleKeyPress(event) { 13526 if (event.which === 37 || event.which === 40) { 13527 // Left and Down Arrows 13528 event.preventDefault(); 13529 this.stepBack(); 13530 } else if (event.which === 38 || event.which === 39) { 13531 // Up and Right Arrows 13532 event.preventDefault(); 13533 this.stepForward(); 13534 } 13535 }; 13536 13537 /** 13538 * Handle on blur for slider 13539 * 13540 * @method handleBlur 13541 */ 13542 13543 Slider.prototype.handleBlur = function handleBlur() { 13544 this.off(this.bar.el_.ownerDocument, 'keydown', this.handleKeyPress); 13545 }; 13546 13547 /** 13548 * Listener for click events on slider, used to prevent clicks 13549 * from bubbling up to parent elements like button menus. 13550 * 13551 * @param {Object} event Event object 13552 * @method handleClick 13553 */ 13554 13555 Slider.prototype.handleClick = function handleClick(event) { 13556 event.stopImmediatePropagation(); 13557 event.preventDefault(); 13558 }; 13559 13560 /** 13561 * Get/set if slider is horizontal for vertical 13562 * 13563 * @param {Boolean} bool True if slider is vertical, false is horizontal 13564 * @return {Boolean} True if slider is vertical, false is horizontal 13565 * @method vertical 13566 */ 13567 13568 Slider.prototype.vertical = function vertical(bool) { 13569 if (bool === undefined) { 13570 return this.vertical_ || false; 13571 } 13572 13573 this.vertical_ = !!bool; 13574 13575 if (this.vertical_) { 13576 this.addClass('vjs-slider-vertical'); 13577 } else { 13578 this.addClass('vjs-slider-horizontal'); 13579 } 13580 13581 return this; 13582 }; 13583 13584 return Slider; 13585 })(_componentJs2['default']); 13586 13587 _componentJs2['default'].registerComponent('Slider', Slider); 13588 exports['default'] = Slider; 13589 module.exports = exports['default']; 13590 13591 },{"../component.js":67,"../utils/dom.js":134,"object.assign":45}],117:[function(_dereq_,module,exports){ 13592 /** 13593 * @file flash-rtmp.js 13594 */ 13595 'use strict'; 13596 13597 exports.__esModule = true; 13598 function FlashRtmpDecorator(Flash) { 13599 Flash.streamingFormats = { 13600 'rtmp/mp4': 'MP4', 13601 'rtmp/flv': 'FLV' 13602 }; 13603 13604 Flash.streamFromParts = function (connection, stream) { 13605 return connection + '&' + stream; 13606 }; 13607 13608 Flash.streamToParts = function (src) { 13609 var parts = { 13610 connection: '', 13611 stream: '' 13612 }; 13613 13614 if (!src) return parts; 13615 13616 // Look for the normal URL separator we expect, '&'. 13617 // If found, we split the URL into two pieces around the 13618 // first '&'. 13619 var connEnd = src.search(/&(?!\w+=)/); 13620 var streamBegin = undefined; 13621 if (connEnd !== -1) { 13622 streamBegin = connEnd + 1; 13623 } else { 13624 // If there's not a '&', we use the last '/' as the delimiter. 13625 connEnd = streamBegin = src.lastIndexOf('/') + 1; 13626 if (connEnd === 0) { 13627 // really, there's not a '/'? 13628 connEnd = streamBegin = src.length; 13629 } 13630 } 13631 parts.connection = src.substring(0, connEnd); 13632 parts.stream = src.substring(streamBegin, src.length); 13633 13634 return parts; 13635 }; 13636 13637 Flash.isStreamingType = function (srcType) { 13638 return srcType in Flash.streamingFormats; 13639 }; 13640 13641 // RTMP has four variations, any string starting 13642 // with one of these protocols should be valid 13643 Flash.RTMP_RE = /^rtmp[set]?:\/\//i; 13644 13645 Flash.isStreamingSrc = function (src) { 13646 return Flash.RTMP_RE.test(src); 13647 }; 13648 13649 /** 13650 * A source handler for RTMP urls 13651 * @type {Object} 13652 */ 13653 Flash.rtmpSourceHandler = {}; 13654 13655 /** 13656 * Check if Flash can play the given videotype 13657 * @param {String} type The mimetype to check 13658 * @return {String} 'probably', 'maybe', or '' (empty string) 13659 */ 13660 Flash.rtmpSourceHandler.canPlayType = function (type) { 13661 if (Flash.isStreamingType(type)) { 13662 return 'maybe'; 13663 } 13664 13665 return ''; 13666 }; 13667 13668 /** 13669 * Check if Flash can handle the source natively 13670 * @param {Object} source The source object 13671 * @return {String} 'probably', 'maybe', or '' (empty string) 13672 */ 13673 Flash.rtmpSourceHandler.canHandleSource = function (source) { 13674 var can = Flash.rtmpSourceHandler.canPlayType(source.type); 13675 13676 if (can) { 13677 return can; 13678 } 13679 13680 if (Flash.isStreamingSrc(source.src)) { 13681 return 'maybe'; 13682 } 13683 13684 return ''; 13685 }; 13686 13687 /** 13688 * Pass the source to the flash object 13689 * Adaptive source handlers will have more complicated workflows before passing 13690 * video data to the video element 13691 * @param {Object} source The source object 13692 * @param {Flash} tech The instance of the Flash tech 13693 */ 13694 Flash.rtmpSourceHandler.handleSource = function (source, tech) { 13695 var srcParts = Flash.streamToParts(source.src); 13696 13697 tech['setRtmpConnection'](srcParts.connection); 13698 tech['setRtmpStream'](srcParts.stream); 13699 }; 13700 13701 // Register the native source handler 13702 Flash.registerSourceHandler(Flash.rtmpSourceHandler); 13703 13704 return Flash; 13705 } 13706 13707 exports['default'] = FlashRtmpDecorator; 13708 module.exports = exports['default']; 13709 13710 },{}],118:[function(_dereq_,module,exports){ 13711 /** 13712 * @file flash.js 13713 * VideoJS-SWF - Custom Flash Player with HTML5-ish API 13714 * https://github.com/zencoder/video-js-swf 13715 * Not using setupTriggers. Using global onEvent func to distribute events 13716 */ 13717 13718 'use strict'; 13719 13720 exports.__esModule = true; 13721 13722 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; } } 13723 13724 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 13725 13726 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 13727 13728 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; } 13729 13730 var _tech = _dereq_('./tech'); 13731 13732 var _tech2 = _interopRequireDefault(_tech); 13733 13734 var _utilsDomJs = _dereq_('../utils/dom.js'); 13735 13736 var Dom = _interopRequireWildcard(_utilsDomJs); 13737 13738 var _utilsUrlJs = _dereq_('../utils/url.js'); 13739 13740 var Url = _interopRequireWildcard(_utilsUrlJs); 13741 13742 var _utilsTimeRangesJs = _dereq_('../utils/time-ranges.js'); 13743 13744 var _flashRtmp = _dereq_('./flash-rtmp'); 13745 13746 var _flashRtmp2 = _interopRequireDefault(_flashRtmp); 13747 13748 var _component = _dereq_('../component'); 13749 13750 var _component2 = _interopRequireDefault(_component); 13751 13752 var _globalWindow = _dereq_('global/window'); 13753 13754 var _globalWindow2 = _interopRequireDefault(_globalWindow); 13755 13756 var _objectAssign = _dereq_('object.assign'); 13757 13758 var _objectAssign2 = _interopRequireDefault(_objectAssign); 13759 13760 var navigator = _globalWindow2['default'].navigator; 13761 /** 13762 * Flash Media Controller - Wrapper for fallback SWF API 13763 * 13764 * @param {Object=} options Object of option names and values 13765 * @param {Function=} ready Ready callback function 13766 * @extends Tech 13767 * @class Flash 13768 */ 13769 13770 var Flash = (function (_Tech) { 13771 _inherits(Flash, _Tech); 13772 13773 function Flash(options, ready) { 13774 _classCallCheck(this, Flash); 13775 13776 _Tech.call(this, options, ready); 13777 13778 // Set the source when ready 13779 if (options.source) { 13780 this.ready(function () { 13781 this.setSource(options.source); 13782 }, true); 13783 } 13784 13785 // Having issues with Flash reloading on certain page actions (hide/resize/fullscreen) in certain browsers 13786 // This allows resetting the playhead when we catch the reload 13787 if (options.startTime) { 13788 this.ready(function () { 13789 this.load(); 13790 this.play(); 13791 this.currentTime(options.startTime); 13792 }, true); 13793 } 13794 13795 // Add global window functions that the swf expects 13796 // A 4.x workflow we weren't able to solve for in 5.0 13797 // because of the need to hard code these functions 13798 // into the swf for security reasons 13799 _globalWindow2['default'].videojs = _globalWindow2['default'].videojs || {}; 13800 _globalWindow2['default'].videojs.Flash = _globalWindow2['default'].videojs.Flash || {}; 13801 _globalWindow2['default'].videojs.Flash.onReady = Flash.onReady; 13802 _globalWindow2['default'].videojs.Flash.onEvent = Flash.onEvent; 13803 _globalWindow2['default'].videojs.Flash.onError = Flash.onError; 13804 13805 this.on('seeked', function () { 13806 this.lastSeekTarget_ = undefined; 13807 }); 13808 } 13809 13810 // Create setters and getters for attributes 13811 13812 /** 13813 * Create the component's DOM element 13814 * 13815 * @return {Element} 13816 * @method createEl 13817 */ 13818 13819 Flash.prototype.createEl = function createEl() { 13820 var options = this.options_; 13821 13822 // If video.js is hosted locally you should also set the location 13823 // for the hosted swf, which should be relative to the page (not video.js) 13824 // Otherwise this adds a CDN url. 13825 // The CDN also auto-adds a swf URL for that specific version. 13826 if (!options.swf) { 13827 options.swf = '//vjs.zencdn.net/swf/5.0.1/video-js.swf'; 13828 } 13829 13830 // Generate ID for swf object 13831 var objId = options.techId; 13832 13833 // Merge default flashvars with ones passed in to init 13834 var flashVars = _objectAssign2['default']({ 13835 13836 // SWF Callback Functions 13837 'readyFunction': 'videojs.Flash.onReady', 13838 'eventProxyFunction': 'videojs.Flash.onEvent', 13839 'errorEventProxyFunction': 'videojs.Flash.onError', 13840 13841 // Player Settings 13842 'autoplay': options.autoplay, 13843 'preload': options.preload, 13844 'loop': options.loop, 13845 'muted': options.muted 13846 13847 }, options.flashVars); 13848 13849 // Merge default parames with ones passed in 13850 var params = _objectAssign2['default']({ 13851 'wmode': 'opaque', // Opaque is needed to overlay controls, but can affect playback performance 13852 'bgcolor': '#000000' // Using bgcolor prevents a white flash when the object is loading 13853 }, options.params); 13854 13855 // Merge default attributes with ones passed in 13856 var attributes = _objectAssign2['default']({ 13857 'id': objId, 13858 'name': objId, // Both ID and Name needed or swf to identify itself 13859 'class': 'vjs-tech' 13860 }, options.attributes); 13861 13862 this.el_ = Flash.embed(options.swf, flashVars, params, attributes); 13863 this.el_.tech = this; 13864 13865 return this.el_; 13866 }; 13867 13868 /** 13869 * Play for flash tech 13870 * 13871 * @method play 13872 */ 13873 13874 Flash.prototype.play = function play() { 13875 if (this.ended()) { 13876 this.setCurrentTime(0); 13877 } 13878 this.el_.vjs_play(); 13879 }; 13880 13881 /** 13882 * Pause for flash tech 13883 * 13884 * @method pause 13885 */ 13886 13887 Flash.prototype.pause = function pause() { 13888 this.el_.vjs_pause(); 13889 }; 13890 13891 /** 13892 * Get/set video 13893 * 13894 * @param {Object=} src Source object 13895 * @return {Object} 13896 * @method src 13897 */ 13898 13899 Flash.prototype.src = function src(_src) { 13900 if (_src === undefined) { 13901 return this.currentSrc(); 13902 } 13903 13904 // Setting src through `src` not `setSrc` will be deprecated 13905 return this.setSrc(_src); 13906 }; 13907 13908 /** 13909 * Set video 13910 * 13911 * @param {Object=} src Source object 13912 * @deprecated 13913 * @method setSrc 13914 */ 13915 13916 Flash.prototype.setSrc = function setSrc(src) { 13917 // Make sure source URL is absolute. 13918 src = Url.getAbsoluteURL(src); 13919 this.el_.vjs_src(src); 13920 13921 // Currently the SWF doesn't autoplay if you load a source later. 13922 // e.g. Load player w/ no source, wait 2s, set src. 13923 if (this.autoplay()) { 13924 var tech = this; 13925 this.setTimeout(function () { 13926 tech.play(); 13927 }, 0); 13928 } 13929 }; 13930 13931 /** 13932 * Returns true if the tech is currently seeking. 13933 * @return {boolean} true if seeking 13934 */ 13935 13936 Flash.prototype.seeking = function seeking() { 13937 return this.lastSeekTarget_ !== undefined; 13938 }; 13939 13940 /** 13941 * Set current time 13942 * 13943 * @param {Number} time Current time of video 13944 * @method setCurrentTime 13945 */ 13946 13947 Flash.prototype.setCurrentTime = function setCurrentTime(time) { 13948 var seekable = this.seekable(); 13949 if (seekable.length) { 13950 // clamp to the current seekable range 13951 time = time > seekable.start(0) ? time : seekable.start(0); 13952 time = time < seekable.end(seekable.length - 1) ? time : seekable.end(seekable.length - 1); 13953 13954 this.lastSeekTarget_ = time; 13955 this.trigger('seeking'); 13956 this.el_.vjs_setProperty('currentTime', time); 13957 _Tech.prototype.setCurrentTime.call(this); 13958 } 13959 }; 13960 13961 /** 13962 * Get current time 13963 * 13964 * @param {Number=} time Current time of video 13965 * @return {Number} Current time 13966 * @method currentTime 13967 */ 13968 13969 Flash.prototype.currentTime = function currentTime(time) { 13970 // when seeking make the reported time keep up with the requested time 13971 // by reading the time we're seeking to 13972 if (this.seeking()) { 13973 return this.lastSeekTarget_ || 0; 13974 } 13975 return this.el_.vjs_getProperty('currentTime'); 13976 }; 13977 13978 /** 13979 * Get current source 13980 * 13981 * @method currentSrc 13982 */ 13983 13984 Flash.prototype.currentSrc = function currentSrc() { 13985 if (this.currentSource_) { 13986 return this.currentSource_.src; 13987 } else { 13988 return this.el_.vjs_getProperty('currentSrc'); 13989 } 13990 }; 13991 13992 /** 13993 * Load media into player 13994 * 13995 * @method load 13996 */ 13997 13998 Flash.prototype.load = function load() { 13999 this.el_.vjs_load(); 14000 }; 14001 14002 /** 14003 * Get poster 14004 * 14005 * @method poster 14006 */ 14007 14008 Flash.prototype.poster = function poster() { 14009 this.el_.vjs_getProperty('poster'); 14010 }; 14011 14012 /** 14013 * Poster images are not handled by the Flash tech so make this a no-op 14014 * 14015 * @method setPoster 14016 */ 14017 14018 Flash.prototype.setPoster = function setPoster() {}; 14019 14020 /** 14021 * Determine if can seek in media 14022 * 14023 * @return {TimeRangeObject} 14024 * @method seekable 14025 */ 14026 14027 Flash.prototype.seekable = function seekable() { 14028 var duration = this.duration(); 14029 if (duration === 0) { 14030 return _utilsTimeRangesJs.createTimeRange(); 14031 } 14032 return _utilsTimeRangesJs.createTimeRange(0, duration); 14033 }; 14034 14035 /** 14036 * Get buffered time range 14037 * 14038 * @return {TimeRangeObject} 14039 * @method buffered 14040 */ 14041 14042 Flash.prototype.buffered = function buffered() { 14043 var ranges = this.el_.vjs_getProperty('buffered'); 14044 if (ranges.length === 0) { 14045 return _utilsTimeRangesJs.createTimeRange(); 14046 } 14047 return _utilsTimeRangesJs.createTimeRange(ranges[0][0], ranges[0][1]); 14048 }; 14049 14050 /** 14051 * Get fullscreen support - 14052 * Flash does not allow fullscreen through javascript 14053 * so always returns false 14054 * 14055 * @return {Boolean} false 14056 * @method supportsFullScreen 14057 */ 14058 14059 Flash.prototype.supportsFullScreen = function supportsFullScreen() { 14060 return false; // Flash does not allow fullscreen through javascript 14061 }; 14062 14063 /** 14064 * Request to enter fullscreen 14065 * Flash does not allow fullscreen through javascript 14066 * so always returns false 14067 * 14068 * @return {Boolean} false 14069 * @method enterFullScreen 14070 */ 14071 14072 Flash.prototype.enterFullScreen = function enterFullScreen() { 14073 return false; 14074 }; 14075 14076 return Flash; 14077 })(_tech2['default']); 14078 14079 var _api = Flash.prototype; 14080 var _readWrite = 'rtmpConnection,rtmpStream,preload,defaultPlaybackRate,playbackRate,autoplay,loop,mediaGroup,controller,controls,volume,muted,defaultMuted'.split(','); 14081 var _readOnly = 'networkState,readyState,initialTime,duration,startOffsetTime,paused,ended,videoTracks,audioTracks,videoWidth,videoHeight'.split(','); 14082 14083 function _createSetter(attr) { 14084 var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1); 14085 _api['set' + attrUpper] = function (val) { 14086 return this.el_.vjs_setProperty(attr, val); 14087 }; 14088 } 14089 function _createGetter(attr) { 14090 _api[attr] = function () { 14091 return this.el_.vjs_getProperty(attr); 14092 }; 14093 } 14094 14095 // Create getter and setters for all read/write attributes 14096 for (var i = 0; i < _readWrite.length; i++) { 14097 _createGetter(_readWrite[i]); 14098 _createSetter(_readWrite[i]); 14099 } 14100 14101 // Create getters for read-only attributes 14102 for (var i = 0; i < _readOnly.length; i++) { 14103 _createGetter(_readOnly[i]); 14104 } 14105 14106 /* Flash Support Testing -------------------------------------------------------- */ 14107 14108 Flash.isSupported = function () { 14109 return Flash.version()[0] >= 10; 14110 // return swfobject.hasFlashPlayerVersion('10'); 14111 }; 14112 14113 // Add Source Handler pattern functions to this tech 14114 _tech2['default'].withSourceHandlers(Flash); 14115 14116 /* 14117 * The default native source handler. 14118 * This simply passes the source to the video element. Nothing fancy. 14119 * 14120 * @param {Object} source The source object 14121 * @param {Flash} tech The instance of the Flash tech 14122 */ 14123 Flash.nativeSourceHandler = {}; 14124 14125 /** 14126 * Check if Flash can play the given videotype 14127 * @param {String} type The mimetype to check 14128 * @return {String} 'probably', 'maybe', or '' (empty string) 14129 */ 14130 Flash.nativeSourceHandler.canPlayType = function (type) { 14131 if (type in Flash.formats) { 14132 return 'maybe'; 14133 } 14134 14135 return ''; 14136 }; 14137 14138 /* 14139 * Check Flash can handle the source natively 14140 * 14141 * @param {Object} source The source object 14142 * @return {String} 'probably', 'maybe', or '' (empty string) 14143 */ 14144 Flash.nativeSourceHandler.canHandleSource = function (source) { 14145 var type; 14146 14147 function guessMimeType(src) { 14148 var ext = Url.getFileExtension(src); 14149 if (ext) { 14150 return 'video/' + ext; 14151 } 14152 return ''; 14153 } 14154 14155 if (!source.type) { 14156 type = guessMimeType(source.src); 14157 } else { 14158 // Strip code information from the type because we don't get that specific 14159 type = source.type.replace(/;.*/, '').toLowerCase(); 14160 } 14161 14162 return Flash.nativeSourceHandler.canPlayType(type); 14163 }; 14164 14165 /* 14166 * Pass the source to the flash object 14167 * Adaptive source handlers will have more complicated workflows before passing 14168 * video data to the video element 14169 * 14170 * @param {Object} source The source object 14171 * @param {Flash} tech The instance of the Flash tech 14172 */ 14173 Flash.nativeSourceHandler.handleSource = function (source, tech) { 14174 tech.setSrc(source.src); 14175 }; 14176 14177 /* 14178 * Clean up the source handler when disposing the player or switching sources.. 14179 * (no cleanup is needed when supporting the format natively) 14180 */ 14181 Flash.nativeSourceHandler.dispose = function () {}; 14182 14183 // Register the native source handler 14184 Flash.registerSourceHandler(Flash.nativeSourceHandler); 14185 14186 Flash.formats = { 14187 'video/flv': 'FLV', 14188 'video/x-flv': 'FLV', 14189 'video/mp4': 'MP4', 14190 'video/m4v': 'MP4' 14191 }; 14192 14193 Flash.onReady = function (currSwf) { 14194 var el = Dom.getEl(currSwf); 14195 var tech = el && el.tech; 14196 14197 // if there is no el then the tech has been disposed 14198 // and the tech element was removed from the player div 14199 if (tech && tech.el()) { 14200 // check that the flash object is really ready 14201 Flash.checkReady(tech); 14202 } 14203 }; 14204 14205 // The SWF isn't always ready when it says it is. Sometimes the API functions still need to be added to the object. 14206 // If it's not ready, we set a timeout to check again shortly. 14207 Flash.checkReady = function (tech) { 14208 // stop worrying if the tech has been disposed 14209 if (!tech.el()) { 14210 return; 14211 } 14212 14213 // check if API property exists 14214 if (tech.el().vjs_getProperty) { 14215 // tell tech it's ready 14216 tech.triggerReady(); 14217 } else { 14218 // wait longer 14219 this.setTimeout(function () { 14220 Flash['checkReady'](tech); 14221 }, 50); 14222 } 14223 }; 14224 14225 // Trigger events from the swf on the player 14226 Flash.onEvent = function (swfID, eventName) { 14227 var tech = Dom.getEl(swfID).tech; 14228 tech.trigger(eventName); 14229 }; 14230 14231 // Log errors from the swf 14232 Flash.onError = function (swfID, err) { 14233 var tech = Dom.getEl(swfID).tech; 14234 14235 // trigger MEDIA_ERR_SRC_NOT_SUPPORTED 14236 if (err === 'srcnotfound') { 14237 return tech.error(4); 14238 } 14239 14240 // trigger a custom error 14241 tech.error('FLASH: ' + err); 14242 }; 14243 14244 // Flash Version Check 14245 Flash.version = function () { 14246 var version = '0,0,0'; 14247 14248 // IE 14249 try { 14250 version = new _globalWindow2['default'].ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1]; 14251 14252 // other browsers 14253 } catch (e) { 14254 try { 14255 if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) { 14256 version = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1]; 14257 } 14258 } catch (err) {} 14259 } 14260 return version.split(','); 14261 }; 14262 14263 // Flash embedding method. Only used in non-iframe mode 14264 Flash.embed = function (swf, flashVars, params, attributes) { 14265 var code = Flash.getEmbedCode(swf, flashVars, params, attributes); 14266 14267 // Get element by embedding code and retrieving created element 14268 var obj = Dom.createEl('div', { innerHTML: code }).childNodes[0]; 14269 14270 return obj; 14271 }; 14272 14273 Flash.getEmbedCode = function (swf, flashVars, params, attributes) { 14274 var objTag = '<object type="application/x-shockwave-flash" '; 14275 var flashVarsString = ''; 14276 var paramsString = ''; 14277 var attrsString = ''; 14278 14279 // Convert flash vars to string 14280 if (flashVars) { 14281 Object.getOwnPropertyNames(flashVars).forEach(function (key) { 14282 flashVarsString += key + '=' + flashVars[key] + '&'; 14283 }); 14284 } 14285 14286 // Add swf, flashVars, and other default params 14287 params = _objectAssign2['default']({ 14288 'movie': swf, 14289 'flashvars': flashVarsString, 14290 'allowScriptAccess': 'always', // Required to talk to swf 14291 'allowNetworking': 'all' // All should be default, but having security issues. 14292 }, params); 14293 14294 // Create param tags string 14295 Object.getOwnPropertyNames(params).forEach(function (key) { 14296 paramsString += '<param name="' + key + '" value="' + params[key] + '" />'; 14297 }); 14298 14299 attributes = _objectAssign2['default']({ 14300 // Add swf to attributes (need both for IE and Others to work) 14301 'data': swf, 14302 14303 // Default to 100% width/height 14304 'width': '100%', 14305 'height': '100%' 14306 14307 }, attributes); 14308 14309 // Create Attributes string 14310 Object.getOwnPropertyNames(attributes).forEach(function (key) { 14311 attrsString += key + '="' + attributes[key] + '" '; 14312 }); 14313 14314 return '' + objTag + attrsString + '>' + paramsString + '</object>'; 14315 }; 14316 14317 // Run Flash through the RTMP decorator 14318 _flashRtmp2['default'](Flash); 14319 14320 _component2['default'].registerComponent('Flash', Flash); 14321 _tech2['default'].registerTech('Flash', Flash); 14322 exports['default'] = Flash; 14323 module.exports = exports['default']; 14324 14325 },{"../component":67,"../utils/dom.js":134,"../utils/time-ranges.js":142,"../utils/url.js":144,"./flash-rtmp":117,"./tech":121,"global/window":2,"object.assign":45}],119:[function(_dereq_,module,exports){ 14326 /** 14327 * @file html5.js 14328 * HTML5 Media Controller - Wrapper for HTML5 Media API 14329 */ 14330 14331 'use strict'; 14332 14333 exports.__esModule = true; 14334 14335 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; } } 14336 14337 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 14338 14339 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 14340 14341 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; } 14342 14343 var _techJs = _dereq_('./tech.js'); 14344 14345 var _techJs2 = _interopRequireDefault(_techJs); 14346 14347 var _component = _dereq_('../component'); 14348 14349 var _component2 = _interopRequireDefault(_component); 14350 14351 var _utilsDomJs = _dereq_('../utils/dom.js'); 14352 14353 var Dom = _interopRequireWildcard(_utilsDomJs); 14354 14355 var _utilsUrlJs = _dereq_('../utils/url.js'); 14356 14357 var Url = _interopRequireWildcard(_utilsUrlJs); 14358 14359 var _utilsFnJs = _dereq_('../utils/fn.js'); 14360 14361 var Fn = _interopRequireWildcard(_utilsFnJs); 14362 14363 var _utilsLogJs = _dereq_('../utils/log.js'); 14364 14365 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 14366 14367 var _utilsBrowserJs = _dereq_('../utils/browser.js'); 14368 14369 var browser = _interopRequireWildcard(_utilsBrowserJs); 14370 14371 var _globalDocument = _dereq_('global/document'); 14372 14373 var _globalDocument2 = _interopRequireDefault(_globalDocument); 14374 14375 var _globalWindow = _dereq_('global/window'); 14376 14377 var _globalWindow2 = _interopRequireDefault(_globalWindow); 14378 14379 var _objectAssign = _dereq_('object.assign'); 14380 14381 var _objectAssign2 = _interopRequireDefault(_objectAssign); 14382 14383 var _utilsMergeOptionsJs = _dereq_('../utils/merge-options.js'); 14384 14385 var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs); 14386 14387 /** 14388 * HTML5 Media Controller - Wrapper for HTML5 Media API 14389 * 14390 * @param {Object=} options Object of option names and values 14391 * @param {Function=} ready Ready callback function 14392 * @extends Tech 14393 * @class Html5 14394 */ 14395 14396 var Html5 = (function (_Tech) { 14397 _inherits(Html5, _Tech); 14398 14399 function Html5(options, ready) { 14400 _classCallCheck(this, Html5); 14401 14402 _Tech.call(this, options, ready); 14403 14404 var source = options.source; 14405 14406 // Set the source if one is provided 14407 // 1) Check if the source is new (if not, we want to keep the original so playback isn't interrupted) 14408 // 2) Check to see if the network state of the tag was failed at init, and if so, reset the source 14409 // anyway so the error gets fired. 14410 if (source && (this.el_.currentSrc !== source.src || options.tag && options.tag.initNetworkState_ === 3)) { 14411 this.setSource(source); 14412 } else { 14413 this.handleLateInit_(this.el_); 14414 } 14415 14416 if (this.el_.hasChildNodes()) { 14417 14418 var nodes = this.el_.childNodes; 14419 var nodesLength = nodes.length; 14420 var removeNodes = []; 14421 14422 while (nodesLength--) { 14423 var node = nodes[nodesLength]; 14424 var nodeName = node.nodeName.toLowerCase(); 14425 14426 if (nodeName === 'track') { 14427 if (!this.featuresNativeTextTracks) { 14428 // Empty video tag tracks so the built-in player doesn't use them also. 14429 // This may not be fast enough to stop HTML5 browsers from reading the tags 14430 // so we'll need to turn off any default tracks if we're manually doing 14431 // captions and subtitles. videoElement.textTracks 14432 removeNodes.push(node); 14433 } else { 14434 // store HTMLTrackElement and TextTrack to remote list 14435 this.remoteTextTrackEls().addTrackElement_(node); 14436 this.remoteTextTracks().addTrack_(node.track); 14437 } 14438 } 14439 } 14440 14441 for (var i = 0; i < removeNodes.length; i++) { 14442 this.el_.removeChild(removeNodes[i]); 14443 } 14444 } 14445 14446 if (this.featuresNativeTextTracks) { 14447 this.handleTextTrackChange_ = Fn.bind(this, this.handleTextTrackChange); 14448 this.handleTextTrackAdd_ = Fn.bind(this, this.handleTextTrackAdd); 14449 this.handleTextTrackRemove_ = Fn.bind(this, this.handleTextTrackRemove); 14450 this.proxyNativeTextTracks_(); 14451 } 14452 14453 // Determine if native controls should be used 14454 // Our goal should be to get the custom controls on mobile solid everywhere 14455 // so we can remove this all together. Right now this will block custom 14456 // controls on touch enabled laptops like the Chrome Pixel 14457 if (browser.TOUCH_ENABLED && options.nativeControlsForTouch === true || browser.IS_IPHONE || browser.IS_NATIVE_ANDROID) { 14458 this.setControls(true); 14459 } 14460 14461 this.triggerReady(); 14462 } 14463 14464 /* HTML5 Support Testing ---------------------------------------------------- */ 14465 14466 /* 14467 * Element for testing browser HTML5 video capabilities 14468 * 14469 * @type {Element} 14470 * @constant 14471 * @private 14472 */ 14473 14474 /** 14475 * Dispose of html5 media element 14476 * 14477 * @method dispose 14478 */ 14479 14480 Html5.prototype.dispose = function dispose() { 14481 var tt = this.el().textTracks; 14482 var emulatedTt = this.textTracks(); 14483 14484 // remove native event listeners 14485 if (tt && tt.removeEventListener) { 14486 tt.removeEventListener('change', this.handleTextTrackChange_); 14487 tt.removeEventListener('addtrack', this.handleTextTrackAdd_); 14488 tt.removeEventListener('removetrack', this.handleTextTrackRemove_); 14489 } 14490 14491 // clearout the emulated text track list. 14492 var i = emulatedTt.length; 14493 14494 while (i--) { 14495 emulatedTt.removeTrack_(emulatedTt[i]); 14496 } 14497 14498 Html5.disposeMediaElement(this.el_); 14499 _Tech.prototype.dispose.call(this); 14500 }; 14501 14502 /** 14503 * Create the component's DOM element 14504 * 14505 * @return {Element} 14506 * @method createEl 14507 */ 14508 14509 Html5.prototype.createEl = function createEl() { 14510 var el = this.options_.tag; 14511 14512 // Check if this browser supports moving the element into the box. 14513 // On the iPhone video will break if you move the element, 14514 // So we have to create a brand new element. 14515 if (!el || this['movingMediaElementInDOM'] === false) { 14516 14517 // If the original tag is still there, clone and remove it. 14518 if (el) { 14519 var clone = el.cloneNode(true); 14520 el.parentNode.insertBefore(clone, el); 14521 Html5.disposeMediaElement(el); 14522 el = clone; 14523 } else { 14524 el = _globalDocument2['default'].createElement('video'); 14525 14526 // determine if native controls should be used 14527 var tagAttributes = this.options_.tag && Dom.getElAttributes(this.options_.tag); 14528 var attributes = _utilsMergeOptionsJs2['default']({}, tagAttributes); 14529 if (!browser.TOUCH_ENABLED || this.options_.nativeControlsForTouch !== true) { 14530 delete attributes.controls; 14531 } 14532 14533 Dom.setElAttributes(el, _objectAssign2['default'](attributes, { 14534 id: this.options_.techId, 14535 'class': 'vjs-tech' 14536 })); 14537 } 14538 } 14539 14540 // Update specific tag settings, in case they were overridden 14541 var settingsAttrs = ['autoplay', 'preload', 'loop', 'muted']; 14542 for (var i = settingsAttrs.length - 1; i >= 0; i--) { 14543 var attr = settingsAttrs[i]; 14544 var overwriteAttrs = {}; 14545 if (typeof this.options_[attr] !== 'undefined') { 14546 overwriteAttrs[attr] = this.options_[attr]; 14547 } 14548 Dom.setElAttributes(el, overwriteAttrs); 14549 } 14550 14551 return el; 14552 // jenniisawesome = true; 14553 }; 14554 14555 // If we're loading the playback object after it has started loading 14556 // or playing the video (often with autoplay on) then the loadstart event 14557 // has already fired and we need to fire it manually because many things 14558 // rely on it. 14559 14560 Html5.prototype.handleLateInit_ = function handleLateInit_(el) { 14561 var _this = this; 14562 14563 if (el.networkState === 0 || el.networkState === 3) { 14564 // The video element hasn't started loading the source yet 14565 // or didn't find a source 14566 return; 14567 } 14568 14569 if (el.readyState === 0) { 14570 var _ret = (function () { 14571 // NetworkState is set synchronously BUT loadstart is fired at the 14572 // end of the current stack, usually before setInterval(fn, 0). 14573 // So at this point we know loadstart may have already fired or is 14574 // about to fire, and either way the player hasn't seen it yet. 14575 // We don't want to fire loadstart prematurely here and cause a 14576 // double loadstart so we'll wait and see if it happens between now 14577 // and the next loop, and fire it if not. 14578 // HOWEVER, we also want to make sure it fires before loadedmetadata 14579 // which could also happen between now and the next loop, so we'll 14580 // watch for that also. 14581 var loadstartFired = false; 14582 var setLoadstartFired = function setLoadstartFired() { 14583 loadstartFired = true; 14584 }; 14585 _this.on('loadstart', setLoadstartFired); 14586 14587 var triggerLoadstart = function triggerLoadstart() { 14588 // We did miss the original loadstart. Make sure the player 14589 // sees loadstart before loadedmetadata 14590 if (!loadstartFired) { 14591 this.trigger('loadstart'); 14592 } 14593 }; 14594 _this.on('loadedmetadata', triggerLoadstart); 14595 14596 _this.ready(function () { 14597 this.off('loadstart', setLoadstartFired); 14598 this.off('loadedmetadata', triggerLoadstart); 14599 14600 if (!loadstartFired) { 14601 // We did miss the original native loadstart. Fire it now. 14602 this.trigger('loadstart'); 14603 } 14604 }); 14605 14606 return { 14607 v: undefined 14608 }; 14609 })(); 14610 14611 if (typeof _ret === 'object') return _ret.v; 14612 } 14613 14614 // From here on we know that loadstart already fired and we missed it. 14615 // The other readyState events aren't as much of a problem if we double 14616 // them, so not going to go to as much trouble as loadstart to prevent 14617 // that unless we find reason to. 14618 var eventsToTrigger = ['loadstart']; 14619 14620 // loadedmetadata: newly equal to HAVE_METADATA (1) or greater 14621 eventsToTrigger.push('loadedmetadata'); 14622 14623 // loadeddata: newly increased to HAVE_CURRENT_DATA (2) or greater 14624 if (el.readyState >= 2) { 14625 eventsToTrigger.push('loadeddata'); 14626 } 14627 14628 // canplay: newly increased to HAVE_FUTURE_DATA (3) or greater 14629 if (el.readyState >= 3) { 14630 eventsToTrigger.push('canplay'); 14631 } 14632 14633 // canplaythrough: newly equal to HAVE_ENOUGH_DATA (4) 14634 if (el.readyState >= 4) { 14635 eventsToTrigger.push('canplaythrough'); 14636 } 14637 14638 // We still need to give the player time to add event listeners 14639 this.ready(function () { 14640 eventsToTrigger.forEach(function (type) { 14641 this.trigger(type); 14642 }, this); 14643 }); 14644 }; 14645 14646 Html5.prototype.proxyNativeTextTracks_ = function proxyNativeTextTracks_() { 14647 var tt = this.el().textTracks; 14648 14649 if (tt) { 14650 // Add tracks - if player is initialised after DOM loaded, textTracks 14651 // will not trigger addtrack 14652 for (var i = 0; i < tt.length; i++) { 14653 this.textTracks().addTrack_(tt[i]); 14654 } 14655 14656 if (tt.addEventListener) { 14657 tt.addEventListener('change', this.handleTextTrackChange_); 14658 tt.addEventListener('addtrack', this.handleTextTrackAdd_); 14659 tt.addEventListener('removetrack', this.handleTextTrackRemove_); 14660 } 14661 } 14662 }; 14663 14664 Html5.prototype.handleTextTrackChange = function handleTextTrackChange(e) { 14665 var tt = this.textTracks(); 14666 this.textTracks().trigger({ 14667 type: 'change', 14668 target: tt, 14669 currentTarget: tt, 14670 srcElement: tt 14671 }); 14672 }; 14673 14674 Html5.prototype.handleTextTrackAdd = function handleTextTrackAdd(e) { 14675 this.textTracks().addTrack_(e.track); 14676 }; 14677 14678 Html5.prototype.handleTextTrackRemove = function handleTextTrackRemove(e) { 14679 this.textTracks().removeTrack_(e.track); 14680 }; 14681 14682 /** 14683 * Play for html5 tech 14684 * 14685 * @method play 14686 */ 14687 14688 Html5.prototype.play = function play() { 14689 this.el_.play(); 14690 }; 14691 14692 /** 14693 * Pause for html5 tech 14694 * 14695 * @method pause 14696 */ 14697 14698 Html5.prototype.pause = function pause() { 14699 this.el_.pause(); 14700 }; 14701 14702 /** 14703 * Paused for html5 tech 14704 * 14705 * @return {Boolean} 14706 * @method paused 14707 */ 14708 14709 Html5.prototype.paused = function paused() { 14710 return this.el_.paused; 14711 }; 14712 14713 /** 14714 * Get current time 14715 * 14716 * @return {Number} 14717 * @method currentTime 14718 */ 14719 14720 Html5.prototype.currentTime = function currentTime() { 14721 return this.el_.currentTime; 14722 }; 14723 14724 /** 14725 * Set current time 14726 * 14727 * @param {Number} seconds Current time of video 14728 * @method setCurrentTime 14729 */ 14730 14731 Html5.prototype.setCurrentTime = function setCurrentTime(seconds) { 14732 try { 14733 this.el_.currentTime = seconds; 14734 } catch (e) { 14735 _utilsLogJs2['default'](e, 'Video is not ready. (Video.js)'); 14736 // this.warning(VideoJS.warnings.videoNotReady); 14737 } 14738 }; 14739 14740 /** 14741 * Get duration 14742 * 14743 * @return {Number} 14744 * @method duration 14745 */ 14746 14747 Html5.prototype.duration = function duration() { 14748 return this.el_.duration || 0; 14749 }; 14750 14751 /** 14752 * Get a TimeRange object that represents the intersection 14753 * of the time ranges for which the user agent has all 14754 * relevant media 14755 * 14756 * @return {TimeRangeObject} 14757 * @method buffered 14758 */ 14759 14760 Html5.prototype.buffered = function buffered() { 14761 return this.el_.buffered; 14762 }; 14763 14764 /** 14765 * Get volume level 14766 * 14767 * @return {Number} 14768 * @method volume 14769 */ 14770 14771 Html5.prototype.volume = function volume() { 14772 return this.el_.volume; 14773 }; 14774 14775 /** 14776 * Set volume level 14777 * 14778 * @param {Number} percentAsDecimal Volume percent as a decimal 14779 * @method setVolume 14780 */ 14781 14782 Html5.prototype.setVolume = function setVolume(percentAsDecimal) { 14783 this.el_.volume = percentAsDecimal; 14784 }; 14785 14786 /** 14787 * Get if muted 14788 * 14789 * @return {Boolean} 14790 * @method muted 14791 */ 14792 14793 Html5.prototype.muted = function muted() { 14794 return this.el_.muted; 14795 }; 14796 14797 /** 14798 * Set muted 14799 * 14800 * @param {Boolean} If player is to be muted or note 14801 * @method setMuted 14802 */ 14803 14804 Html5.prototype.setMuted = function setMuted(muted) { 14805 this.el_.muted = muted; 14806 }; 14807 14808 /** 14809 * Get player width 14810 * 14811 * @return {Number} 14812 * @method width 14813 */ 14814 14815 Html5.prototype.width = function width() { 14816 return this.el_.offsetWidth; 14817 }; 14818 14819 /** 14820 * Get player height 14821 * 14822 * @return {Number} 14823 * @method height 14824 */ 14825 14826 Html5.prototype.height = function height() { 14827 return this.el_.offsetHeight; 14828 }; 14829 14830 /** 14831 * Get if there is fullscreen support 14832 * 14833 * @return {Boolean} 14834 * @method supportsFullScreen 14835 */ 14836 14837 Html5.prototype.supportsFullScreen = function supportsFullScreen() { 14838 if (typeof this.el_.webkitEnterFullScreen === 'function') { 14839 var userAgent = _globalWindow2['default'].navigator.userAgent; 14840 // Seems to be broken in Chromium/Chrome && Safari in Leopard 14841 if (/Android/.test(userAgent) || !/Chrome|Mac OS X 10.5/.test(userAgent)) { 14842 return true; 14843 } 14844 } 14845 return false; 14846 }; 14847 14848 /** 14849 * Request to enter fullscreen 14850 * 14851 * @method enterFullScreen 14852 */ 14853 14854 Html5.prototype.enterFullScreen = function enterFullScreen() { 14855 var video = this.el_; 14856 14857 if ('webkitDisplayingFullscreen' in video) { 14858 this.one('webkitbeginfullscreen', function () { 14859 this.one('webkitendfullscreen', function () { 14860 this.trigger('fullscreenchange', { isFullscreen: false }); 14861 }); 14862 14863 this.trigger('fullscreenchange', { isFullscreen: true }); 14864 }); 14865 } 14866 14867 if (video.paused && video.networkState <= video.HAVE_METADATA) { 14868 // attempt to prime the video element for programmatic access 14869 // this isn't necessary on the desktop but shouldn't hurt 14870 this.el_.play(); 14871 14872 // playing and pausing synchronously during the transition to fullscreen 14873 // can get iOS ~6.1 devices into a play/pause loop 14874 this.setTimeout(function () { 14875 video.pause(); 14876 video.webkitEnterFullScreen(); 14877 }, 0); 14878 } else { 14879 video.webkitEnterFullScreen(); 14880 } 14881 }; 14882 14883 /** 14884 * Request to exit fullscreen 14885 * 14886 * @method exitFullScreen 14887 */ 14888 14889 Html5.prototype.exitFullScreen = function exitFullScreen() { 14890 this.el_.webkitExitFullScreen(); 14891 }; 14892 14893 /** 14894 * Get/set video 14895 * 14896 * @param {Object=} src Source object 14897 * @return {Object} 14898 * @method src 14899 */ 14900 14901 Html5.prototype.src = function src(_src) { 14902 if (_src === undefined) { 14903 return this.el_.src; 14904 } else { 14905 // Setting src through `src` instead of `setSrc` will be deprecated 14906 this.setSrc(_src); 14907 } 14908 }; 14909 14910 /** 14911 * Set video 14912 * 14913 * @param {Object} src Source object 14914 * @deprecated 14915 * @method setSrc 14916 */ 14917 14918 Html5.prototype.setSrc = function setSrc(src) { 14919 this.el_.src = src; 14920 }; 14921 14922 /** 14923 * Load media into player 14924 * 14925 * @method load 14926 */ 14927 14928 Html5.prototype.load = function load() { 14929 this.el_.load(); 14930 }; 14931 14932 /** 14933 * Reset the tech. Removes all sources and calls `load`. 14934 * 14935 * @method reset 14936 */ 14937 14938 Html5.prototype.reset = function reset() { 14939 Html5.resetMediaElement(this.el_); 14940 }; 14941 14942 /** 14943 * Get current source 14944 * 14945 * @return {Object} 14946 * @method currentSrc 14947 */ 14948 14949 Html5.prototype.currentSrc = function currentSrc() { 14950 if (this.currentSource_) { 14951 return this.currentSource_.src; 14952 } else { 14953 return this.el_.currentSrc; 14954 } 14955 }; 14956 14957 /** 14958 * Get poster 14959 * 14960 * @return {String} 14961 * @method poster 14962 */ 14963 14964 Html5.prototype.poster = function poster() { 14965 return this.el_.poster; 14966 }; 14967 14968 /** 14969 * Set poster 14970 * 14971 * @param {String} val URL to poster image 14972 * @method 14973 */ 14974 14975 Html5.prototype.setPoster = function setPoster(val) { 14976 this.el_.poster = val; 14977 }; 14978 14979 /** 14980 * Get preload attribute 14981 * 14982 * @return {String} 14983 * @method preload 14984 */ 14985 14986 Html5.prototype.preload = function preload() { 14987 return this.el_.preload; 14988 }; 14989 14990 /** 14991 * Set preload attribute 14992 * 14993 * @param {String} val Value for preload attribute 14994 * @method setPreload 14995 */ 14996 14997 Html5.prototype.setPreload = function setPreload(val) { 14998 this.el_.preload = val; 14999 }; 15000 15001 /** 15002 * Get autoplay attribute 15003 * 15004 * @return {String} 15005 * @method autoplay 15006 */ 15007 15008 Html5.prototype.autoplay = function autoplay() { 15009 return this.el_.autoplay; 15010 }; 15011 15012 /** 15013 * Set autoplay attribute 15014 * 15015 * @param {String} val Value for preload attribute 15016 * @method setAutoplay 15017 */ 15018 15019 Html5.prototype.setAutoplay = function setAutoplay(val) { 15020 this.el_.autoplay = val; 15021 }; 15022 15023 /** 15024 * Get controls attribute 15025 * 15026 * @return {String} 15027 * @method controls 15028 */ 15029 15030 Html5.prototype.controls = function controls() { 15031 return this.el_.controls; 15032 }; 15033 15034 /** 15035 * Set controls attribute 15036 * 15037 * @param {String} val Value for controls attribute 15038 * @method setControls 15039 */ 15040 15041 Html5.prototype.setControls = function setControls(val) { 15042 this.el_.controls = !!val; 15043 }; 15044 15045 /** 15046 * Get loop attribute 15047 * 15048 * @return {String} 15049 * @method loop 15050 */ 15051 15052 Html5.prototype.loop = function loop() { 15053 return this.el_.loop; 15054 }; 15055 15056 /** 15057 * Set loop attribute 15058 * 15059 * @param {String} val Value for loop attribute 15060 * @method setLoop 15061 */ 15062 15063 Html5.prototype.setLoop = function setLoop(val) { 15064 this.el_.loop = val; 15065 }; 15066 15067 /** 15068 * Get error value 15069 * 15070 * @return {String} 15071 * @method error 15072 */ 15073 15074 Html5.prototype.error = function error() { 15075 return this.el_.error; 15076 }; 15077 15078 /** 15079 * Get whether or not the player is in the "seeking" state 15080 * 15081 * @return {Boolean} 15082 * @method seeking 15083 */ 15084 15085 Html5.prototype.seeking = function seeking() { 15086 return this.el_.seeking; 15087 }; 15088 15089 /** 15090 * Get a TimeRanges object that represents the 15091 * ranges of the media resource to which it is possible 15092 * for the user agent to seek. 15093 * 15094 * @return {TimeRangeObject} 15095 * @method seekable 15096 */ 15097 15098 Html5.prototype.seekable = function seekable() { 15099 return this.el_.seekable; 15100 }; 15101 15102 /** 15103 * Get if video ended 15104 * 15105 * @return {Boolean} 15106 * @method ended 15107 */ 15108 15109 Html5.prototype.ended = function ended() { 15110 return this.el_.ended; 15111 }; 15112 15113 /** 15114 * Get the value of the muted content attribute 15115 * This attribute has no dynamic effect, it only 15116 * controls the default state of the element 15117 * 15118 * @return {Boolean} 15119 * @method defaultMuted 15120 */ 15121 15122 Html5.prototype.defaultMuted = function defaultMuted() { 15123 return this.el_.defaultMuted; 15124 }; 15125 15126 /** 15127 * Get desired speed at which the media resource is to play 15128 * 15129 * @return {Number} 15130 * @method playbackRate 15131 */ 15132 15133 Html5.prototype.playbackRate = function playbackRate() { 15134 return this.el_.playbackRate; 15135 }; 15136 15137 /** 15138 * Returns a TimeRanges object that represents the ranges of the 15139 * media resource that the user agent has played. 15140 * @return {TimeRangeObject} the range of points on the media 15141 * timeline that has been reached through normal playback 15142 * @see https://html.spec.whatwg.org/multipage/embedded-content.html#dom-media-played 15143 */ 15144 15145 Html5.prototype.played = function played() { 15146 return this.el_.played; 15147 }; 15148 15149 /** 15150 * Set desired speed at which the media resource is to play 15151 * 15152 * @param {Number} val Speed at which the media resource is to play 15153 * @method setPlaybackRate 15154 */ 15155 15156 Html5.prototype.setPlaybackRate = function setPlaybackRate(val) { 15157 this.el_.playbackRate = val; 15158 }; 15159 15160 /** 15161 * Get the current state of network activity for the element, from 15162 * the list below 15163 * NETWORK_EMPTY (numeric value 0) 15164 * NETWORK_IDLE (numeric value 1) 15165 * NETWORK_LOADING (numeric value 2) 15166 * NETWORK_NO_SOURCE (numeric value 3) 15167 * 15168 * @return {Number} 15169 * @method networkState 15170 */ 15171 15172 Html5.prototype.networkState = function networkState() { 15173 return this.el_.networkState; 15174 }; 15175 15176 /** 15177 * Get a value that expresses the current state of the element 15178 * with respect to rendering the current playback position, from 15179 * the codes in the list below 15180 * HAVE_NOTHING (numeric value 0) 15181 * HAVE_METADATA (numeric value 1) 15182 * HAVE_CURRENT_DATA (numeric value 2) 15183 * HAVE_FUTURE_DATA (numeric value 3) 15184 * HAVE_ENOUGH_DATA (numeric value 4) 15185 * 15186 * @return {Number} 15187 * @method readyState 15188 */ 15189 15190 Html5.prototype.readyState = function readyState() { 15191 return this.el_.readyState; 15192 }; 15193 15194 /** 15195 * Get width of video 15196 * 15197 * @return {Number} 15198 * @method videoWidth 15199 */ 15200 15201 Html5.prototype.videoWidth = function videoWidth() { 15202 return this.el_.videoWidth; 15203 }; 15204 15205 /** 15206 * Get height of video 15207 * 15208 * @return {Number} 15209 * @method videoHeight 15210 */ 15211 15212 Html5.prototype.videoHeight = function videoHeight() { 15213 return this.el_.videoHeight; 15214 }; 15215 15216 /** 15217 * Get text tracks 15218 * 15219 * @return {TextTrackList} 15220 * @method textTracks 15221 */ 15222 15223 Html5.prototype.textTracks = function textTracks() { 15224 return _Tech.prototype.textTracks.call(this); 15225 }; 15226 15227 /** 15228 * Creates and returns a text track object 15229 * 15230 * @param {String} kind Text track kind (subtitles, captions, descriptions 15231 * chapters and metadata) 15232 * @param {String=} label Label to identify the text track 15233 * @param {String=} language Two letter language abbreviation 15234 * @return {TextTrackObject} 15235 * @method addTextTrack 15236 */ 15237 15238 Html5.prototype.addTextTrack = function addTextTrack(kind, label, language) { 15239 if (!this['featuresNativeTextTracks']) { 15240 return _Tech.prototype.addTextTrack.call(this, kind, label, language); 15241 } 15242 15243 return this.el_.addTextTrack(kind, label, language); 15244 }; 15245 15246 /** 15247 * Creates a remote text track object and returns a html track element 15248 * 15249 * @param {Object} options The object should contain values for 15250 * kind, language, label and src (location of the WebVTT file) 15251 * @return {HTMLTrackElement} 15252 * @method addRemoteTextTrack 15253 */ 15254 15255 Html5.prototype.addRemoteTextTrack = function addRemoteTextTrack() { 15256 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; 15257 15258 if (!this['featuresNativeTextTracks']) { 15259 return _Tech.prototype.addRemoteTextTrack.call(this, options); 15260 } 15261 15262 var htmlTrackElement = _globalDocument2['default'].createElement('track'); 15263 15264 if (options.kind) { 15265 htmlTrackElement.kind = options.kind; 15266 } 15267 if (options.label) { 15268 htmlTrackElement.label = options.label; 15269 } 15270 if (options.language || options.srclang) { 15271 htmlTrackElement.srclang = options.language || options.srclang; 15272 } 15273 if (options['default']) { 15274 htmlTrackElement['default'] = options['default']; 15275 } 15276 if (options.id) { 15277 htmlTrackElement.id = options.id; 15278 } 15279 if (options.src) { 15280 htmlTrackElement.src = options.src; 15281 } 15282 15283 this.el().appendChild(htmlTrackElement); 15284 15285 // store HTMLTrackElement and TextTrack to remote list 15286 this.remoteTextTrackEls().addTrackElement_(htmlTrackElement); 15287 this.remoteTextTracks().addTrack_(htmlTrackElement.track); 15288 15289 return htmlTrackElement; 15290 }; 15291 15292 /** 15293 * Remove remote text track from TextTrackList object 15294 * 15295 * @param {TextTrackObject} track Texttrack object to remove 15296 * @method removeRemoteTextTrack 15297 */ 15298 15299 Html5.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) { 15300 if (!this['featuresNativeTextTracks']) { 15301 return _Tech.prototype.removeRemoteTextTrack.call(this, track); 15302 } 15303 15304 var tracks = undefined, 15305 i = undefined; 15306 15307 var trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track); 15308 15309 // remove HTMLTrackElement and TextTrack from remote list 15310 this.remoteTextTrackEls().removeTrackElement_(trackElement); 15311 this.remoteTextTracks().removeTrack_(track); 15312 15313 tracks = this.$$('track'); 15314 15315 i = tracks.length; 15316 while (i--) { 15317 if (track === tracks[i] || track === tracks[i].track) { 15318 this.el().removeChild(tracks[i]); 15319 } 15320 } 15321 }; 15322 15323 return Html5; 15324 })(_techJs2['default']); 15325 15326 Html5.TEST_VID = _globalDocument2['default'].createElement('video'); 15327 var track = _globalDocument2['default'].createElement('track'); 15328 track.kind = 'captions'; 15329 track.srclang = 'en'; 15330 track.label = 'English'; 15331 Html5.TEST_VID.appendChild(track); 15332 15333 /* 15334 * Check if HTML5 video is supported by this browser/device 15335 * 15336 * @return {Boolean} 15337 */ 15338 Html5.isSupported = function () { 15339 // IE9 with no Media Player is a LIAR! (#984) 15340 try { 15341 Html5.TEST_VID['volume'] = 0.5; 15342 } catch (e) { 15343 return false; 15344 } 15345 15346 return !!Html5.TEST_VID.canPlayType; 15347 }; 15348 15349 // Add Source Handler pattern functions to this tech 15350 _techJs2['default'].withSourceHandlers(Html5); 15351 15352 /* 15353 * The default native source handler. 15354 * This simply passes the source to the video element. Nothing fancy. 15355 * 15356 * @param {Object} source The source object 15357 * @param {Html5} tech The instance of the HTML5 tech 15358 */ 15359 Html5.nativeSourceHandler = {}; 15360 15361 /* 15362 * Check if the video element can play the given videotype 15363 * 15364 * @param {String} type The mimetype to check 15365 * @return {String} 'probably', 'maybe', or '' (empty string) 15366 */ 15367 Html5.nativeSourceHandler.canPlayType = function (type) { 15368 // IE9 on Windows 7 without MediaPlayer throws an error here 15369 // https://github.com/videojs/video.js/issues/519 15370 try { 15371 return Html5.TEST_VID.canPlayType(type); 15372 } catch (e) { 15373 return ''; 15374 } 15375 }; 15376 15377 /* 15378 * Check if the video element can handle the source natively 15379 * 15380 * @param {Object} source The source object 15381 * @return {String} 'probably', 'maybe', or '' (empty string) 15382 */ 15383 Html5.nativeSourceHandler.canHandleSource = function (source) { 15384 var match, ext; 15385 15386 // If a type was provided we should rely on that 15387 if (source.type) { 15388 return Html5.nativeSourceHandler.canPlayType(source.type); 15389 } else if (source.src) { 15390 // If no type, fall back to checking 'video/[EXTENSION]' 15391 ext = Url.getFileExtension(source.src); 15392 15393 return Html5.nativeSourceHandler.canPlayType('video/' + ext); 15394 } 15395 15396 return ''; 15397 }; 15398 15399 /* 15400 * Pass the source to the video element 15401 * Adaptive source handlers will have more complicated workflows before passing 15402 * video data to the video element 15403 * 15404 * @param {Object} source The source object 15405 * @param {Html5} tech The instance of the Html5 tech 15406 */ 15407 Html5.nativeSourceHandler.handleSource = function (source, tech) { 15408 tech.setSrc(source.src); 15409 }; 15410 15411 /* 15412 * Clean up the source handler when disposing the player or switching sources.. 15413 * (no cleanup is needed when supporting the format natively) 15414 */ 15415 Html5.nativeSourceHandler.dispose = function () {}; 15416 15417 // Register the native source handler 15418 Html5.registerSourceHandler(Html5.nativeSourceHandler); 15419 15420 /* 15421 * Check if the volume can be changed in this browser/device. 15422 * Volume cannot be changed in a lot of mobile devices. 15423 * Specifically, it can't be changed from 1 on iOS. 15424 * 15425 * @return {Boolean} 15426 */ 15427 Html5.canControlVolume = function () { 15428 var volume = Html5.TEST_VID.volume; 15429 Html5.TEST_VID.volume = volume / 2 + 0.1; 15430 return volume !== Html5.TEST_VID.volume; 15431 }; 15432 15433 /* 15434 * Check if playbackRate is supported in this browser/device. 15435 * 15436 * @return {Number} [description] 15437 */ 15438 Html5.canControlPlaybackRate = function () { 15439 var playbackRate = Html5.TEST_VID.playbackRate; 15440 Html5.TEST_VID.playbackRate = playbackRate / 2 + 0.1; 15441 return playbackRate !== Html5.TEST_VID.playbackRate; 15442 }; 15443 15444 /* 15445 * Check to see if native text tracks are supported by this browser/device 15446 * 15447 * @return {Boolean} 15448 */ 15449 Html5.supportsNativeTextTracks = function () { 15450 var supportsTextTracks; 15451 15452 // Figure out native text track support 15453 // If mode is a number, we cannot change it because it'll disappear from view. 15454 // Browsers with numeric modes include IE10 and older (<=2013) samsung android models. 15455 // Firefox isn't playing nice either with modifying the mode 15456 // TODO: Investigate firefox: https://github.com/videojs/video.js/issues/1862 15457 supportsTextTracks = !!Html5.TEST_VID.textTracks; 15458 if (supportsTextTracks && Html5.TEST_VID.textTracks.length > 0) { 15459 supportsTextTracks = typeof Html5.TEST_VID.textTracks[0]['mode'] !== 'number'; 15460 } 15461 if (supportsTextTracks && browser.IS_FIREFOX) { 15462 supportsTextTracks = false; 15463 } 15464 if (supportsTextTracks && !('onremovetrack' in Html5.TEST_VID.textTracks)) { 15465 supportsTextTracks = false; 15466 } 15467 15468 return supportsTextTracks; 15469 }; 15470 15471 /** 15472 * An array of events available on the Html5 tech. 15473 * 15474 * @private 15475 * @type {Array} 15476 */ 15477 Html5.Events = ['loadstart', 'suspend', 'abort', 'error', 'emptied', 'stalled', 'loadedmetadata', 'loadeddata', 'canplay', 'canplaythrough', 'playing', 'waiting', 'seeking', 'seeked', 'ended', 'durationchange', 'timeupdate', 'progress', 'play', 'pause', 'ratechange', 'volumechange']; 15478 15479 /* 15480 * Set the tech's volume control support status 15481 * 15482 * @type {Boolean} 15483 */ 15484 Html5.prototype['featuresVolumeControl'] = Html5.canControlVolume(); 15485 15486 /* 15487 * Set the tech's playbackRate support status 15488 * 15489 * @type {Boolean} 15490 */ 15491 Html5.prototype['featuresPlaybackRate'] = Html5.canControlPlaybackRate(); 15492 15493 /* 15494 * Set the tech's status on moving the video element. 15495 * In iOS, if you move a video element in the DOM, it breaks video playback. 15496 * 15497 * @type {Boolean} 15498 */ 15499 Html5.prototype['movingMediaElementInDOM'] = !browser.IS_IOS; 15500 15501 /* 15502 * Set the the tech's fullscreen resize support status. 15503 * HTML video is able to automatically resize when going to fullscreen. 15504 * (No longer appears to be used. Can probably be removed.) 15505 */ 15506 Html5.prototype['featuresFullscreenResize'] = true; 15507 15508 /* 15509 * Set the tech's progress event support status 15510 * (this disables the manual progress events of the Tech) 15511 */ 15512 Html5.prototype['featuresProgressEvents'] = true; 15513 15514 /* 15515 * Sets the tech's status on native text track support 15516 * 15517 * @type {Boolean} 15518 */ 15519 Html5.prototype['featuresNativeTextTracks'] = Html5.supportsNativeTextTracks(); 15520 15521 // HTML5 Feature detection and Device Fixes --------------------------------- // 15522 var canPlayType = undefined; 15523 var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i; 15524 var mp4RE = /^video\/mp4/i; 15525 15526 Html5.patchCanPlayType = function () { 15527 // Android 4.0 and above can play HLS to some extent but it reports being unable to do so 15528 if (browser.ANDROID_VERSION >= 4.0) { 15529 if (!canPlayType) { 15530 canPlayType = Html5.TEST_VID.constructor.prototype.canPlayType; 15531 } 15532 15533 Html5.TEST_VID.constructor.prototype.canPlayType = function (type) { 15534 if (type && mpegurlRE.test(type)) { 15535 return 'maybe'; 15536 } 15537 return canPlayType.call(this, type); 15538 }; 15539 } 15540 15541 // Override Android 2.2 and less canPlayType method which is broken 15542 if (browser.IS_OLD_ANDROID) { 15543 if (!canPlayType) { 15544 canPlayType = Html5.TEST_VID.constructor.prototype.canPlayType; 15545 } 15546 15547 Html5.TEST_VID.constructor.prototype.canPlayType = function (type) { 15548 if (type && mp4RE.test(type)) { 15549 return 'maybe'; 15550 } 15551 return canPlayType.call(this, type); 15552 }; 15553 } 15554 }; 15555 15556 Html5.unpatchCanPlayType = function () { 15557 var r = Html5.TEST_VID.constructor.prototype.canPlayType; 15558 Html5.TEST_VID.constructor.prototype.canPlayType = canPlayType; 15559 canPlayType = null; 15560 return r; 15561 }; 15562 15563 // by default, patch the video element 15564 Html5.patchCanPlayType(); 15565 15566 Html5.disposeMediaElement = function (el) { 15567 if (!el) { 15568 return; 15569 } 15570 15571 if (el.parentNode) { 15572 el.parentNode.removeChild(el); 15573 } 15574 15575 // remove any child track or source nodes to prevent their loading 15576 while (el.hasChildNodes()) { 15577 el.removeChild(el.firstChild); 15578 } 15579 15580 // remove any src reference. not setting `src=''` because that causes a warning 15581 // in firefox 15582 el.removeAttribute('src'); 15583 15584 // force the media element to update its loading state by calling load() 15585 // however IE on Windows 7N has a bug that throws an error so need a try/catch (#793) 15586 if (typeof el.load === 'function') { 15587 // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473) 15588 (function () { 15589 try { 15590 el.load(); 15591 } catch (e) { 15592 // not supported 15593 } 15594 })(); 15595 } 15596 }; 15597 15598 Html5.resetMediaElement = function (el) { 15599 if (!el) { 15600 return; 15601 } 15602 15603 var sources = el.querySelectorAll('source'); 15604 var i = sources.length; 15605 while (i--) { 15606 el.removeChild(sources[i]); 15607 } 15608 15609 // remove any src reference. 15610 // not setting `src=''` because that throws an error 15611 el.removeAttribute('src'); 15612 15613 if (typeof el.load === 'function') { 15614 // wrapping in an iife so it's not deoptimized (#1060#discussion_r10324473) 15615 (function () { 15616 try { 15617 el.load(); 15618 } catch (e) {} 15619 })(); 15620 } 15621 }; 15622 15623 _component2['default'].registerComponent('Html5', Html5); 15624 _techJs2['default'].registerTech('Html5', Html5); 15625 exports['default'] = Html5; 15626 module.exports = exports['default']; 15627 15628 },{"../component":67,"../utils/browser.js":131,"../utils/dom.js":134,"../utils/fn.js":136,"../utils/log.js":139,"../utils/merge-options.js":140,"../utils/url.js":144,"./tech.js":121,"global/document":1,"global/window":2,"object.assign":45}],120:[function(_dereq_,module,exports){ 15629 /** 15630 * @file loader.js 15631 */ 15632 'use strict'; 15633 15634 exports.__esModule = true; 15635 15636 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 15637 15638 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 15639 15640 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; } 15641 15642 var _componentJs = _dereq_('../component.js'); 15643 15644 var _componentJs2 = _interopRequireDefault(_componentJs); 15645 15646 var _techJs = _dereq_('./tech.js'); 15647 15648 var _techJs2 = _interopRequireDefault(_techJs); 15649 15650 var _globalWindow = _dereq_('global/window'); 15651 15652 var _globalWindow2 = _interopRequireDefault(_globalWindow); 15653 15654 var _utilsToTitleCaseJs = _dereq_('../utils/to-title-case.js'); 15655 15656 var _utilsToTitleCaseJs2 = _interopRequireDefault(_utilsToTitleCaseJs); 15657 15658 /** 15659 * The Media Loader is the component that decides which playback technology to load 15660 * when the player is initialized. 15661 * 15662 * @param {Object} player Main Player 15663 * @param {Object=} options Object of option names and values 15664 * @param {Function=} ready Ready callback function 15665 * @extends Component 15666 * @class MediaLoader 15667 */ 15668 15669 var MediaLoader = (function (_Component) { 15670 _inherits(MediaLoader, _Component); 15671 15672 function MediaLoader(player, options, ready) { 15673 _classCallCheck(this, MediaLoader); 15674 15675 _Component.call(this, player, options, ready); 15676 15677 // If there are no sources when the player is initialized, 15678 // load the first supported playback technology. 15679 15680 if (!options.playerOptions['sources'] || options.playerOptions['sources'].length === 0) { 15681 for (var i = 0, j = options.playerOptions['techOrder']; i < j.length; i++) { 15682 var techName = _utilsToTitleCaseJs2['default'](j[i]); 15683 var tech = _techJs2['default'].getTech(techName); 15684 // Support old behavior of techs being registered as components. 15685 // Remove once that deprecated behavior is removed. 15686 if (!techName) { 15687 tech = _componentJs2['default'].getComponent(techName); 15688 } 15689 15690 // Check if the browser supports this technology 15691 if (tech && tech.isSupported()) { 15692 player.loadTech_(techName); 15693 break; 15694 } 15695 } 15696 } else { 15697 // // Loop through playback technologies (HTML5, Flash) and check for support. 15698 // // Then load the best source. 15699 // // A few assumptions here: 15700 // // All playback technologies respect preload false. 15701 player.src(options.playerOptions['sources']); 15702 } 15703 } 15704 15705 return MediaLoader; 15706 })(_componentJs2['default']); 15707 15708 _componentJs2['default'].registerComponent('MediaLoader', MediaLoader); 15709 exports['default'] = MediaLoader; 15710 module.exports = exports['default']; 15711 15712 },{"../component.js":67,"../utils/to-title-case.js":143,"./tech.js":121,"global/window":2}],121:[function(_dereq_,module,exports){ 15713 /** 15714 * @file tech.js 15715 * Media Technology Controller - Base class for media playback 15716 * technology controllers like Flash and HTML5 15717 */ 15718 15719 'use strict'; 15720 15721 exports.__esModule = true; 15722 15723 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; } } 15724 15725 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 15726 15727 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 15728 15729 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; } 15730 15731 var _component = _dereq_('../component'); 15732 15733 var _component2 = _interopRequireDefault(_component); 15734 15735 var _tracksHtmlTrackElement = _dereq_('../tracks/html-track-element'); 15736 15737 var _tracksHtmlTrackElement2 = _interopRequireDefault(_tracksHtmlTrackElement); 15738 15739 var _tracksHtmlTrackElementList = _dereq_('../tracks/html-track-element-list'); 15740 15741 var _tracksHtmlTrackElementList2 = _interopRequireDefault(_tracksHtmlTrackElementList); 15742 15743 var _utilsMergeOptionsJs = _dereq_('../utils/merge-options.js'); 15744 15745 var _utilsMergeOptionsJs2 = _interopRequireDefault(_utilsMergeOptionsJs); 15746 15747 var _tracksTextTrack = _dereq_('../tracks/text-track'); 15748 15749 var _tracksTextTrack2 = _interopRequireDefault(_tracksTextTrack); 15750 15751 var _tracksTextTrackList = _dereq_('../tracks/text-track-list'); 15752 15753 var _tracksTextTrackList2 = _interopRequireDefault(_tracksTextTrackList); 15754 15755 var _utilsFnJs = _dereq_('../utils/fn.js'); 15756 15757 var Fn = _interopRequireWildcard(_utilsFnJs); 15758 15759 var _utilsLogJs = _dereq_('../utils/log.js'); 15760 15761 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 15762 15763 var _utilsTimeRangesJs = _dereq_('../utils/time-ranges.js'); 15764 15765 var _utilsBufferJs = _dereq_('../utils/buffer.js'); 15766 15767 var _mediaErrorJs = _dereq_('../media-error.js'); 15768 15769 var _mediaErrorJs2 = _interopRequireDefault(_mediaErrorJs); 15770 15771 var _globalWindow = _dereq_('global/window'); 15772 15773 var _globalWindow2 = _interopRequireDefault(_globalWindow); 15774 15775 var _globalDocument = _dereq_('global/document'); 15776 15777 var _globalDocument2 = _interopRequireDefault(_globalDocument); 15778 15779 /** 15780 * Base class for media (HTML5 Video, Flash) controllers 15781 * 15782 * @param {Object=} options Options object 15783 * @param {Function=} ready Ready callback function 15784 * @extends Component 15785 * @class Tech 15786 */ 15787 15788 var Tech = (function (_Component) { 15789 _inherits(Tech, _Component); 15790 15791 function Tech() { 15792 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; 15793 var ready = arguments.length <= 1 || arguments[1] === undefined ? function () {} : arguments[1]; 15794 15795 _classCallCheck(this, Tech); 15796 15797 // we don't want the tech to report user activity automatically. 15798 // This is done manually in addControlsListeners 15799 options.reportTouchActivity = false; 15800 _Component.call(this, null, options, ready); 15801 15802 // keep track of whether the current source has played at all to 15803 // implement a very limited played() 15804 this.hasStarted_ = false; 15805 this.on('playing', function () { 15806 this.hasStarted_ = true; 15807 }); 15808 this.on('loadstart', function () { 15809 this.hasStarted_ = false; 15810 }); 15811 15812 this.textTracks_ = options.textTracks; 15813 15814 // Manually track progress in cases where the browser/flash player doesn't report it. 15815 if (!this.featuresProgressEvents) { 15816 this.manualProgressOn(); 15817 } 15818 15819 // Manually track timeupdates in cases where the browser/flash player doesn't report it. 15820 if (!this.featuresTimeupdateEvents) { 15821 this.manualTimeUpdatesOn(); 15822 } 15823 15824 if (options.nativeCaptions === false || options.nativeTextTracks === false) { 15825 this.featuresNativeTextTracks = false; 15826 } 15827 15828 if (!this.featuresNativeTextTracks) { 15829 this.on('ready', this.emulateTextTracks); 15830 } 15831 15832 this.initTextTrackListeners(); 15833 15834 // Turn on component tap events 15835 this.emitTapEvents(); 15836 } 15837 15838 /* 15839 * List of associated text tracks 15840 * 15841 * @type {Array} 15842 * @private 15843 */ 15844 15845 /* Fallbacks for unsupported event types 15846 ================================================================================ */ 15847 // Manually trigger progress events based on changes to the buffered amount 15848 // Many flash players and older HTML5 browsers don't send progress or progress-like events 15849 /** 15850 * Turn on progress events 15851 * 15852 * @method manualProgressOn 15853 */ 15854 15855 Tech.prototype.manualProgressOn = function manualProgressOn() { 15856 this.on('durationchange', this.onDurationChange); 15857 15858 this.manualProgress = true; 15859 15860 // Trigger progress watching when a source begins loading 15861 this.one('ready', this.trackProgress); 15862 }; 15863 15864 /** 15865 * Turn off progress events 15866 * 15867 * @method manualProgressOff 15868 */ 15869 15870 Tech.prototype.manualProgressOff = function manualProgressOff() { 15871 this.manualProgress = false; 15872 this.stopTrackingProgress(); 15873 15874 this.off('durationchange', this.onDurationChange); 15875 }; 15876 15877 /** 15878 * Track progress 15879 * 15880 * @method trackProgress 15881 */ 15882 15883 Tech.prototype.trackProgress = function trackProgress() { 15884 this.stopTrackingProgress(); 15885 this.progressInterval = this.setInterval(Fn.bind(this, function () { 15886 // Don't trigger unless buffered amount is greater than last time 15887 15888 var numBufferedPercent = this.bufferedPercent(); 15889 15890 if (this.bufferedPercent_ !== numBufferedPercent) { 15891 this.trigger('progress'); 15892 } 15893 15894 this.bufferedPercent_ = numBufferedPercent; 15895 15896 if (numBufferedPercent === 1) { 15897 this.stopTrackingProgress(); 15898 } 15899 }), 500); 15900 }; 15901 15902 /** 15903 * Update duration 15904 * 15905 * @method onDurationChange 15906 */ 15907 15908 Tech.prototype.onDurationChange = function onDurationChange() { 15909 this.duration_ = this.duration(); 15910 }; 15911 15912 /** 15913 * Create and get TimeRange object for buffering 15914 * 15915 * @return {TimeRangeObject} 15916 * @method buffered 15917 */ 15918 15919 Tech.prototype.buffered = function buffered() { 15920 return _utilsTimeRangesJs.createTimeRange(0, 0); 15921 }; 15922 15923 /** 15924 * Get buffered percent 15925 * 15926 * @return {Number} 15927 * @method bufferedPercent 15928 */ 15929 15930 Tech.prototype.bufferedPercent = function bufferedPercent() { 15931 return _utilsBufferJs.bufferedPercent(this.buffered(), this.duration_); 15932 }; 15933 15934 /** 15935 * Stops tracking progress by clearing progress interval 15936 * 15937 * @method stopTrackingProgress 15938 */ 15939 15940 Tech.prototype.stopTrackingProgress = function stopTrackingProgress() { 15941 this.clearInterval(this.progressInterval); 15942 }; 15943 15944 /*! Time Tracking -------------------------------------------------------------- */ 15945 /** 15946 * Set event listeners for on play and pause and tracking current time 15947 * 15948 * @method manualTimeUpdatesOn 15949 */ 15950 15951 Tech.prototype.manualTimeUpdatesOn = function manualTimeUpdatesOn() { 15952 this.manualTimeUpdates = true; 15953 15954 this.on('play', this.trackCurrentTime); 15955 this.on('pause', this.stopTrackingCurrentTime); 15956 }; 15957 15958 /** 15959 * Remove event listeners for on play and pause and tracking current time 15960 * 15961 * @method manualTimeUpdatesOff 15962 */ 15963 15964 Tech.prototype.manualTimeUpdatesOff = function manualTimeUpdatesOff() { 15965 this.manualTimeUpdates = false; 15966 this.stopTrackingCurrentTime(); 15967 this.off('play', this.trackCurrentTime); 15968 this.off('pause', this.stopTrackingCurrentTime); 15969 }; 15970 15971 /** 15972 * Tracks current time 15973 * 15974 * @method trackCurrentTime 15975 */ 15976 15977 Tech.prototype.trackCurrentTime = function trackCurrentTime() { 15978 if (this.currentTimeInterval) { 15979 this.stopTrackingCurrentTime(); 15980 } 15981 this.currentTimeInterval = this.setInterval(function () { 15982 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true }); 15983 }, 250); // 42 = 24 fps // 250 is what Webkit uses // FF uses 15 15984 }; 15985 15986 /** 15987 * Turn off play progress tracking (when paused or dragging) 15988 * 15989 * @method stopTrackingCurrentTime 15990 */ 15991 15992 Tech.prototype.stopTrackingCurrentTime = function stopTrackingCurrentTime() { 15993 this.clearInterval(this.currentTimeInterval); 15994 15995 // #1002 - if the video ends right before the next timeupdate would happen, 15996 // the progress bar won't make it all the way to the end 15997 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true }); 15998 }; 15999 16000 /** 16001 * Turn off any manual progress or timeupdate tracking 16002 * 16003 * @method dispose 16004 */ 16005 16006 Tech.prototype.dispose = function dispose() { 16007 // clear out text tracks because we can't reuse them between techs 16008 var textTracks = this.textTracks(); 16009 16010 if (textTracks) { 16011 var i = textTracks.length; 16012 while (i--) { 16013 this.removeRemoteTextTrack(textTracks[i]); 16014 } 16015 } 16016 16017 // Turn off any manual progress or timeupdate tracking 16018 if (this.manualProgress) { 16019 this.manualProgressOff(); 16020 } 16021 16022 if (this.manualTimeUpdates) { 16023 this.manualTimeUpdatesOff(); 16024 } 16025 16026 _Component.prototype.dispose.call(this); 16027 }; 16028 16029 /** 16030 * Reset the tech. Removes all sources and resets readyState. 16031 * 16032 * @method reset 16033 */ 16034 16035 Tech.prototype.reset = function reset() {}; 16036 16037 /** 16038 * When invoked without an argument, returns a MediaError object 16039 * representing the current error state of the player or null if 16040 * there is no error. When invoked with an argument, set the current 16041 * error state of the player. 16042 * @param {MediaError=} err Optional an error object 16043 * @return {MediaError} the current error object or null 16044 * @method error 16045 */ 16046 16047 Tech.prototype.error = function error(err) { 16048 if (err !== undefined) { 16049 if (err instanceof _mediaErrorJs2['default']) { 16050 this.error_ = err; 16051 } else { 16052 this.error_ = new _mediaErrorJs2['default'](err); 16053 } 16054 this.trigger('error'); 16055 } 16056 return this.error_; 16057 }; 16058 16059 /** 16060 * Return the time ranges that have been played through for the 16061 * current source. This implementation is incomplete. It does not 16062 * track the played time ranges, only whether the source has played 16063 * at all or not. 16064 * @return {TimeRangeObject} a single time range if this video has 16065 * played or an empty set of ranges if not. 16066 * @method played 16067 */ 16068 16069 Tech.prototype.played = function played() { 16070 if (this.hasStarted_) { 16071 return _utilsTimeRangesJs.createTimeRange(0, 0); 16072 } 16073 return _utilsTimeRangesJs.createTimeRange(); 16074 }; 16075 16076 /** 16077 * Set current time 16078 * 16079 * @method setCurrentTime 16080 */ 16081 16082 Tech.prototype.setCurrentTime = function setCurrentTime() { 16083 // improve the accuracy of manual timeupdates 16084 if (this.manualTimeUpdates) { 16085 this.trigger({ type: 'timeupdate', target: this, manuallyTriggered: true }); 16086 } 16087 }; 16088 16089 /** 16090 * Initialize texttrack listeners 16091 * 16092 * @method initTextTrackListeners 16093 */ 16094 16095 Tech.prototype.initTextTrackListeners = function initTextTrackListeners() { 16096 var textTrackListChanges = Fn.bind(this, function () { 16097 this.trigger('texttrackchange'); 16098 }); 16099 16100 var tracks = this.textTracks(); 16101 16102 if (!tracks) return; 16103 16104 tracks.addEventListener('removetrack', textTrackListChanges); 16105 tracks.addEventListener('addtrack', textTrackListChanges); 16106 16107 this.on('dispose', Fn.bind(this, function () { 16108 tracks.removeEventListener('removetrack', textTrackListChanges); 16109 tracks.removeEventListener('addtrack', textTrackListChanges); 16110 })); 16111 }; 16112 16113 /** 16114 * Emulate texttracks 16115 * 16116 * @method emulateTextTracks 16117 */ 16118 16119 Tech.prototype.emulateTextTracks = function emulateTextTracks() { 16120 var _this = this; 16121 16122 var tracks = this.textTracks(); 16123 if (!tracks) { 16124 return; 16125 } 16126 16127 if (!_globalWindow2['default']['WebVTT'] && this.el().parentNode != null) { 16128 (function () { 16129 var script = _globalDocument2['default'].createElement('script'); 16130 script.src = _this.options_['vtt.js'] || 'https://cdn.rawgit.com/gkatsev/vtt.js/vjs-v0.12.1/dist/vtt.min.js'; 16131 script.onload = function () { 16132 _this.trigger('vttjsloaded'); 16133 }; 16134 script.onerror = function () { 16135 _this.trigger('vttjserror'); 16136 }; 16137 _this.on('dispose', function () { 16138 script.onload = null; 16139 script.onerror = null; 16140 }); 16141 _this.el().parentNode.appendChild(script); 16142 _globalWindow2['default']['WebVTT'] = true; 16143 })(); 16144 } 16145 16146 var updateDisplay = function updateDisplay() { 16147 return _this.trigger('texttrackchange'); 16148 }; 16149 var textTracksChanges = function textTracksChanges() { 16150 updateDisplay(); 16151 16152 for (var i = 0; i < tracks.length; i++) { 16153 var track = tracks[i]; 16154 track.removeEventListener('cuechange', updateDisplay); 16155 if (track.mode === 'showing') { 16156 track.addEventListener('cuechange', updateDisplay); 16157 } 16158 } 16159 }; 16160 16161 textTracksChanges(); 16162 tracks.addEventListener('change', textTracksChanges); 16163 16164 this.on('dispose', function () { 16165 tracks.removeEventListener('change', textTracksChanges); 16166 }); 16167 }; 16168 16169 /* 16170 * Provide default methods for text tracks. 16171 * 16172 * Html5 tech overrides these. 16173 */ 16174 16175 /** 16176 * Get texttracks 16177 * 16178 * @returns {TextTrackList} 16179 * @method textTracks 16180 */ 16181 16182 Tech.prototype.textTracks = function textTracks() { 16183 this.textTracks_ = this.textTracks_ || new _tracksTextTrackList2['default'](); 16184 return this.textTracks_; 16185 }; 16186 16187 /** 16188 * Get remote texttracks 16189 * 16190 * @returns {TextTrackList} 16191 * @method remoteTextTracks 16192 */ 16193 16194 Tech.prototype.remoteTextTracks = function remoteTextTracks() { 16195 this.remoteTextTracks_ = this.remoteTextTracks_ || new _tracksTextTrackList2['default'](); 16196 return this.remoteTextTracks_; 16197 }; 16198 16199 /** 16200 * Get remote htmltrackelements 16201 * 16202 * @returns {HTMLTrackElementList} 16203 * @method remoteTextTrackEls 16204 */ 16205 16206 Tech.prototype.remoteTextTrackEls = function remoteTextTrackEls() { 16207 this.remoteTextTrackEls_ = this.remoteTextTrackEls_ || new _tracksHtmlTrackElementList2['default'](); 16208 return this.remoteTextTrackEls_; 16209 }; 16210 16211 /** 16212 * Creates and returns a remote text track object 16213 * 16214 * @param {String} kind Text track kind (subtitles, captions, descriptions 16215 * chapters and metadata) 16216 * @param {String=} label Label to identify the text track 16217 * @param {String=} language Two letter language abbreviation 16218 * @return {TextTrackObject} 16219 * @method addTextTrack 16220 */ 16221 16222 Tech.prototype.addTextTrack = function addTextTrack(kind, label, language) { 16223 if (!kind) { 16224 throw new Error('TextTrack kind is required but was not provided'); 16225 } 16226 16227 return createTrackHelper(this, kind, label, language); 16228 }; 16229 16230 /** 16231 * Creates a remote text track object and returns a emulated html track element 16232 * 16233 * @param {Object} options The object should contain values for 16234 * kind, language, label and src (location of the WebVTT file) 16235 * @return {HTMLTrackElement} 16236 * @method addRemoteTextTrack 16237 */ 16238 16239 Tech.prototype.addRemoteTextTrack = function addRemoteTextTrack(options) { 16240 var track = _utilsMergeOptionsJs2['default'](options, { 16241 tech: this 16242 }); 16243 16244 var htmlTrackElement = new _tracksHtmlTrackElement2['default'](track); 16245 16246 // store HTMLTrackElement and TextTrack to remote list 16247 this.remoteTextTrackEls().addTrackElement_(htmlTrackElement); 16248 this.remoteTextTracks().addTrack_(htmlTrackElement.track); 16249 16250 // must come after remoteTextTracks() 16251 this.textTracks().addTrack_(htmlTrackElement.track); 16252 16253 return htmlTrackElement; 16254 }; 16255 16256 /** 16257 * Remove remote texttrack 16258 * 16259 * @param {TextTrackObject} track Texttrack to remove 16260 * @method removeRemoteTextTrack 16261 */ 16262 16263 Tech.prototype.removeRemoteTextTrack = function removeRemoteTextTrack(track) { 16264 this.textTracks().removeTrack_(track); 16265 16266 var trackElement = this.remoteTextTrackEls().getTrackElementByTrack_(track); 16267 16268 // remove HTMLTrackElement and TextTrack from remote list 16269 this.remoteTextTrackEls().removeTrackElement_(trackElement); 16270 this.remoteTextTracks().removeTrack_(track); 16271 }; 16272 16273 /** 16274 * Provide a default setPoster method for techs 16275 * Poster support for techs should be optional, so we don't want techs to 16276 * break if they don't have a way to set a poster. 16277 * 16278 * @method setPoster 16279 */ 16280 16281 Tech.prototype.setPoster = function setPoster() {}; 16282 16283 /* 16284 * Check if the tech can support the given type 16285 * 16286 * The base tech does not support any type, but source handlers might 16287 * overwrite this. 16288 * 16289 * @param {String} type The mimetype to check 16290 * @return {String} 'probably', 'maybe', or '' (empty string) 16291 */ 16292 16293 Tech.prototype.canPlayType = function canPlayType() { 16294 return ''; 16295 }; 16296 16297 /* 16298 * Return whether the argument is a Tech or not. 16299 * Can be passed either a Class like `Html5` or a instance like `player.tech_` 16300 * 16301 * @param {Object} component An item to check 16302 * @return {Boolean} Whether it is a tech or not 16303 */ 16304 16305 Tech.isTech = function isTech(component) { 16306 return component.prototype instanceof Tech || component instanceof Tech || component === Tech; 16307 }; 16308 16309 /** 16310 * Registers a Tech 16311 * 16312 * @param {String} name Name of the Tech to register 16313 * @param {Object} tech The tech to register 16314 * @static 16315 * @method registerComponent 16316 */ 16317 16318 Tech.registerTech = function registerTech(name, tech) { 16319 if (!Tech.techs_) { 16320 Tech.techs_ = {}; 16321 } 16322 16323 if (!Tech.isTech(tech)) { 16324 throw new Error('Tech ' + name + ' must be a Tech'); 16325 } 16326 16327 Tech.techs_[name] = tech; 16328 return tech; 16329 }; 16330 16331 /** 16332 * Gets a component by name 16333 * 16334 * @param {String} name Name of the component to get 16335 * @return {Component} 16336 * @static 16337 * @method getComponent 16338 */ 16339 16340 Tech.getTech = function getTech(name) { 16341 if (Tech.techs_ && Tech.techs_[name]) { 16342 return Tech.techs_[name]; 16343 } 16344 16345 if (_globalWindow2['default'] && _globalWindow2['default'].videojs && _globalWindow2['default'].videojs[name]) { 16346 _utilsLogJs2['default'].warn('The ' + name + ' tech was added to the videojs object when it should be registered using videojs.registerTech(name, tech)'); 16347 return _globalWindow2['default'].videojs[name]; 16348 } 16349 }; 16350 16351 return Tech; 16352 })(_component2['default']); 16353 16354 Tech.prototype.textTracks_; 16355 16356 var createTrackHelper = function createTrackHelper(self, kind, label, language) { 16357 var options = arguments.length <= 4 || arguments[4] === undefined ? {} : arguments[4]; 16358 16359 var tracks = self.textTracks(); 16360 16361 options.kind = kind; 16362 16363 if (label) { 16364 options.label = label; 16365 } 16366 if (language) { 16367 options.language = language; 16368 } 16369 options.tech = self; 16370 16371 var track = new _tracksTextTrack2['default'](options); 16372 tracks.addTrack_(track); 16373 16374 return track; 16375 }; 16376 16377 Tech.prototype.featuresVolumeControl = true; 16378 16379 // Resizing plugins using request fullscreen reloads the plugin 16380 Tech.prototype.featuresFullscreenResize = false; 16381 Tech.prototype.featuresPlaybackRate = false; 16382 16383 // Optional events that we can manually mimic with timers 16384 // currently not triggered by video-js-swf 16385 Tech.prototype.featuresProgressEvents = false; 16386 Tech.prototype.featuresTimeupdateEvents = false; 16387 16388 Tech.prototype.featuresNativeTextTracks = false; 16389 16390 /* 16391 * A functional mixin for techs that want to use the Source Handler pattern. 16392 * 16393 * ##### EXAMPLE: 16394 * 16395 * Tech.withSourceHandlers.call(MyTech); 16396 * 16397 */ 16398 Tech.withSourceHandlers = function (_Tech) { 16399 /* 16400 * Register a source handler 16401 * Source handlers are scripts for handling specific formats. 16402 * The source handler pattern is used for adaptive formats (HLS, DASH) that 16403 * manually load video data and feed it into a Source Buffer (Media Source Extensions) 16404 * @param {Function} handler The source handler 16405 * @param {Boolean} first Register it before any existing handlers 16406 */ 16407 _Tech.registerSourceHandler = function (handler, index) { 16408 var handlers = _Tech.sourceHandlers; 16409 16410 if (!handlers) { 16411 handlers = _Tech.sourceHandlers = []; 16412 } 16413 16414 if (index === undefined) { 16415 // add to the end of the list 16416 index = handlers.length; 16417 } 16418 16419 handlers.splice(index, 0, handler); 16420 }; 16421 16422 /* 16423 * Check if the tech can support the given type 16424 * @param {String} type The mimetype to check 16425 * @return {String} 'probably', 'maybe', or '' (empty string) 16426 */ 16427 _Tech.canPlayType = function (type) { 16428 var handlers = _Tech.sourceHandlers || []; 16429 var can = undefined; 16430 16431 for (var i = 0; i < handlers.length; i++) { 16432 can = handlers[i].canPlayType(type); 16433 16434 if (can) { 16435 return can; 16436 } 16437 } 16438 16439 return ''; 16440 }; 16441 16442 /* 16443 * Return the first source handler that supports the source 16444 * TODO: Answer question: should 'probably' be prioritized over 'maybe' 16445 * @param {Object} source The source object 16446 * @returns {Object} The first source handler that supports the source 16447 * @returns {null} Null if no source handler is found 16448 */ 16449 _Tech.selectSourceHandler = function (source) { 16450 var handlers = _Tech.sourceHandlers || []; 16451 var can = undefined; 16452 16453 for (var i = 0; i < handlers.length; i++) { 16454 can = handlers[i].canHandleSource(source); 16455 16456 if (can) { 16457 return handlers[i]; 16458 } 16459 } 16460 16461 return null; 16462 }; 16463 16464 /* 16465 * Check if the tech can support the given source 16466 * @param {Object} srcObj The source object 16467 * @return {String} 'probably', 'maybe', or '' (empty string) 16468 */ 16469 _Tech.canPlaySource = function (srcObj) { 16470 var sh = _Tech.selectSourceHandler(srcObj); 16471 16472 if (sh) { 16473 return sh.canHandleSource(srcObj); 16474 } 16475 16476 return ''; 16477 }; 16478 16479 /* 16480 * When using a source handler, prefer its implementation of 16481 * any function normally provided by the tech. 16482 */ 16483 var deferrable = ['seekable', 'duration']; 16484 16485 deferrable.forEach(function (fnName) { 16486 var originalFn = this[fnName]; 16487 16488 if (typeof originalFn !== 'function') { 16489 return; 16490 } 16491 16492 this[fnName] = function () { 16493 if (this.sourceHandler_ && this.sourceHandler_[fnName]) { 16494 return this.sourceHandler_[fnName].apply(this.sourceHandler_, arguments); 16495 } 16496 return originalFn.apply(this, arguments); 16497 }; 16498 }, _Tech.prototype); 16499 16500 /* 16501 * Create a function for setting the source using a source object 16502 * and source handlers. 16503 * Should never be called unless a source handler was found. 16504 * @param {Object} source A source object with src and type keys 16505 * @return {Tech} self 16506 */ 16507 _Tech.prototype.setSource = function (source) { 16508 var sh = _Tech.selectSourceHandler(source); 16509 16510 if (!sh) { 16511 // Fall back to a native source hander when unsupported sources are 16512 // deliberately set 16513 if (_Tech.nativeSourceHandler) { 16514 sh = _Tech.nativeSourceHandler; 16515 } else { 16516 _utilsLogJs2['default'].error('No source hander found for the current source.'); 16517 } 16518 } 16519 16520 // Dispose any existing source handler 16521 this.disposeSourceHandler(); 16522 this.off('dispose', this.disposeSourceHandler); 16523 16524 this.currentSource_ = source; 16525 this.sourceHandler_ = sh.handleSource(source, this); 16526 this.on('dispose', this.disposeSourceHandler); 16527 16528 return this; 16529 }; 16530 16531 /* 16532 * Clean up any existing source handler 16533 */ 16534 _Tech.prototype.disposeSourceHandler = function () { 16535 if (this.sourceHandler_ && this.sourceHandler_.dispose) { 16536 this.sourceHandler_.dispose(); 16537 } 16538 }; 16539 }; 16540 16541 _component2['default'].registerComponent('Tech', Tech); 16542 // Old name for Tech 16543 _component2['default'].registerComponent('MediaTechController', Tech); 16544 Tech.registerTech('Tech', Tech); 16545 exports['default'] = Tech; 16546 module.exports = exports['default']; 16547 16548 },{"../component":67,"../media-error.js":105,"../tracks/html-track-element":123,"../tracks/html-track-element-list":122,"../tracks/text-track":130,"../tracks/text-track-list":128,"../utils/buffer.js":132,"../utils/fn.js":136,"../utils/log.js":139,"../utils/merge-options.js":140,"../utils/time-ranges.js":142,"global/document":1,"global/window":2}],122:[function(_dereq_,module,exports){ 16549 /** 16550 * @file html-track-element-list.js 16551 */ 16552 16553 'use strict'; 16554 16555 exports.__esModule = true; 16556 16557 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 16558 16559 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; } } 16560 16561 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 16562 16563 var _utilsBrowserJs = _dereq_('../utils/browser.js'); 16564 16565 var browser = _interopRequireWildcard(_utilsBrowserJs); 16566 16567 var _globalDocument = _dereq_('global/document'); 16568 16569 var _globalDocument2 = _interopRequireDefault(_globalDocument); 16570 16571 var HtmlTrackElementList = (function () { 16572 function HtmlTrackElementList() { 16573 var trackElements = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; 16574 16575 _classCallCheck(this, HtmlTrackElementList); 16576 16577 var list = this; 16578 16579 if (browser.IS_IE8) { 16580 list = _globalDocument2['default'].createElement('custom'); 16581 16582 for (var prop in HtmlTrackElementList.prototype) { 16583 if (prop !== 'constructor') { 16584 list[prop] = HtmlTrackElementList.prototype[prop]; 16585 } 16586 } 16587 } 16588 16589 list.trackElements_ = []; 16590 16591 Object.defineProperty(list, 'length', { 16592 get: function get() { 16593 return this.trackElements_.length; 16594 } 16595 }); 16596 16597 for (var i = 0, _length = trackElements.length; i < _length; i++) { 16598 list.addTrackElement_(trackElements[i]); 16599 } 16600 16601 if (browser.IS_IE8) { 16602 return list; 16603 } 16604 } 16605 16606 HtmlTrackElementList.prototype.addTrackElement_ = function addTrackElement_(trackElement) { 16607 this.trackElements_.push(trackElement); 16608 }; 16609 16610 HtmlTrackElementList.prototype.getTrackElementByTrack_ = function getTrackElementByTrack_(track) { 16611 var trackElement_ = undefined; 16612 16613 for (var i = 0, _length2 = this.trackElements_.length; i < _length2; i++) { 16614 if (track === this.trackElements_[i].track) { 16615 trackElement_ = this.trackElements_[i]; 16616 16617 break; 16618 } 16619 } 16620 16621 return trackElement_; 16622 }; 16623 16624 HtmlTrackElementList.prototype.removeTrackElement_ = function removeTrackElement_(trackElement) { 16625 for (var i = 0, _length3 = this.trackElements_.length; i < _length3; i++) { 16626 if (trackElement === this.trackElements_[i]) { 16627 this.trackElements_.splice(i, 1); 16628 16629 break; 16630 } 16631 } 16632 }; 16633 16634 return HtmlTrackElementList; 16635 })(); 16636 16637 exports['default'] = HtmlTrackElementList; 16638 module.exports = exports['default']; 16639 16640 },{"../utils/browser.js":131,"global/document":1}],123:[function(_dereq_,module,exports){ 16641 /** 16642 * @file html-track-element.js 16643 */ 16644 16645 'use strict'; 16646 16647 exports.__esModule = true; 16648 16649 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 16650 16651 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; } } 16652 16653 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 16654 16655 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; } 16656 16657 var _utilsBrowserJs = _dereq_('../utils/browser.js'); 16658 16659 var browser = _interopRequireWildcard(_utilsBrowserJs); 16660 16661 var _globalDocument = _dereq_('global/document'); 16662 16663 var _globalDocument2 = _interopRequireDefault(_globalDocument); 16664 16665 var _eventTarget = _dereq_('../event-target'); 16666 16667 var _eventTarget2 = _interopRequireDefault(_eventTarget); 16668 16669 var _tracksTextTrack = _dereq_('../tracks/text-track'); 16670 16671 var _tracksTextTrack2 = _interopRequireDefault(_tracksTextTrack); 16672 16673 var NONE = 0; 16674 var LOADING = 1; 16675 var LOADED = 2; 16676 var ERROR = 3; 16677 16678 /** 16679 * https://html.spec.whatwg.org/multipage/embedded-content.html#htmltrackelement 16680 * 16681 * interface HTMLTrackElement : HTMLElement { 16682 * attribute DOMString kind; 16683 * attribute DOMString src; 16684 * attribute DOMString srclang; 16685 * attribute DOMString label; 16686 * attribute boolean default; 16687 * 16688 * const unsigned short NONE = 0; 16689 * const unsigned short LOADING = 1; 16690 * const unsigned short LOADED = 2; 16691 * const unsigned short ERROR = 3; 16692 * readonly attribute unsigned short readyState; 16693 * 16694 * readonly attribute TextTrack track; 16695 * }; 16696 * 16697 * @param {Object} options TextTrack configuration 16698 * @class HTMLTrackElement 16699 */ 16700 16701 var HTMLTrackElement = (function (_EventTarget) { 16702 _inherits(HTMLTrackElement, _EventTarget); 16703 16704 function HTMLTrackElement() { 16705 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; 16706 16707 _classCallCheck(this, HTMLTrackElement); 16708 16709 _EventTarget.call(this); 16710 16711 var readyState = undefined, 16712 trackElement = this; 16713 16714 if (browser.IS_IE8) { 16715 trackElement = _globalDocument2['default'].createElement('custom'); 16716 16717 for (var prop in HTMLTrackElement.prototype) { 16718 if (prop !== 'constructor') { 16719 trackElement[prop] = HTMLTrackElement.prototype[prop]; 16720 } 16721 } 16722 } 16723 16724 var track = new _tracksTextTrack2['default'](options); 16725 16726 trackElement.kind = track.kind; 16727 trackElement.src = track.src; 16728 trackElement.srclang = track.language; 16729 trackElement.label = track.label; 16730 trackElement['default'] = track['default']; 16731 16732 Object.defineProperty(trackElement, 'readyState', { 16733 get: function get() { 16734 return readyState; 16735 } 16736 }); 16737 16738 Object.defineProperty(trackElement, 'track', { 16739 get: function get() { 16740 return track; 16741 } 16742 }); 16743 16744 readyState = NONE; 16745 16746 track.addEventListener('loadeddata', function () { 16747 readyState = LOADED; 16748 16749 trackElement.trigger({ 16750 type: 'load', 16751 target: trackElement 16752 }); 16753 }); 16754 16755 if (browser.IS_IE8) { 16756 return trackElement; 16757 } 16758 } 16759 16760 return HTMLTrackElement; 16761 })(_eventTarget2['default']); 16762 16763 HTMLTrackElement.prototype.allowedEvents_ = { 16764 load: 'load' 16765 }; 16766 16767 HTMLTrackElement.NONE = NONE; 16768 HTMLTrackElement.LOADING = LOADING; 16769 HTMLTrackElement.LOADED = LOADED; 16770 HTMLTrackElement.ERROR = ERROR; 16771 16772 exports['default'] = HTMLTrackElement; 16773 module.exports = exports['default']; 16774 16775 },{"../event-target":101,"../tracks/text-track":130,"../utils/browser.js":131,"global/document":1}],124:[function(_dereq_,module,exports){ 16776 /** 16777 * @file text-track-cue-list.js 16778 */ 16779 'use strict'; 16780 16781 exports.__esModule = true; 16782 16783 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 16784 16785 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; } } 16786 16787 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 16788 16789 var _utilsBrowserJs = _dereq_('../utils/browser.js'); 16790 16791 var browser = _interopRequireWildcard(_utilsBrowserJs); 16792 16793 var _globalDocument = _dereq_('global/document'); 16794 16795 var _globalDocument2 = _interopRequireDefault(_globalDocument); 16796 16797 /** 16798 * A List of text track cues as defined in: 16799 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackcuelist 16800 * 16801 * interface TextTrackCueList { 16802 * readonly attribute unsigned long length; 16803 * getter TextTrackCue (unsigned long index); 16804 * TextTrackCue? getCueById(DOMString id); 16805 * }; 16806 * 16807 * @param {Array} cues A list of cues to be initialized with 16808 * @class TextTrackCueList 16809 */ 16810 16811 var TextTrackCueList = (function () { 16812 function TextTrackCueList(cues) { 16813 _classCallCheck(this, TextTrackCueList); 16814 16815 var list = this; 16816 16817 if (browser.IS_IE8) { 16818 list = _globalDocument2['default'].createElement('custom'); 16819 16820 for (var prop in TextTrackCueList.prototype) { 16821 if (prop !== 'constructor') { 16822 list[prop] = TextTrackCueList.prototype[prop]; 16823 } 16824 } 16825 } 16826 16827 TextTrackCueList.prototype.setCues_.call(list, cues); 16828 16829 Object.defineProperty(list, 'length', { 16830 get: function get() { 16831 return this.length_; 16832 } 16833 }); 16834 16835 if (browser.IS_IE8) { 16836 return list; 16837 } 16838 } 16839 16840 /** 16841 * A setter for cues in this list 16842 * 16843 * @param {Array} cues an array of cues 16844 * @method setCues_ 16845 * @private 16846 */ 16847 16848 TextTrackCueList.prototype.setCues_ = function setCues_(cues) { 16849 var oldLength = this.length || 0; 16850 var i = 0; 16851 var l = cues.length; 16852 16853 this.cues_ = cues; 16854 this.length_ = cues.length; 16855 16856 var defineProp = function defineProp(index) { 16857 if (!('' + index in this)) { 16858 Object.defineProperty(this, '' + index, { 16859 get: function get() { 16860 return this.cues_[index]; 16861 } 16862 }); 16863 } 16864 }; 16865 16866 if (oldLength < l) { 16867 i = oldLength; 16868 16869 for (; i < l; i++) { 16870 defineProp.call(this, i); 16871 } 16872 } 16873 }; 16874 16875 /** 16876 * Get a cue that is currently in the Cue list by id 16877 * 16878 * @param {String} id 16879 * @method getCueById 16880 * @return {Object} a single cue 16881 */ 16882 16883 TextTrackCueList.prototype.getCueById = function getCueById(id) { 16884 var result = null; 16885 16886 for (var i = 0, l = this.length; i < l; i++) { 16887 var cue = this[i]; 16888 16889 if (cue.id === id) { 16890 result = cue; 16891 break; 16892 } 16893 } 16894 16895 return result; 16896 }; 16897 16898 return TextTrackCueList; 16899 })(); 16900 16901 exports['default'] = TextTrackCueList; 16902 module.exports = exports['default']; 16903 16904 },{"../utils/browser.js":131,"global/document":1}],125:[function(_dereq_,module,exports){ 16905 /** 16906 * @file text-track-display.js 16907 */ 16908 'use strict'; 16909 16910 exports.__esModule = true; 16911 16912 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; } } 16913 16914 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 16915 16916 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 16917 16918 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; } 16919 16920 var _component = _dereq_('../component'); 16921 16922 var _component2 = _interopRequireDefault(_component); 16923 16924 var _menuMenuJs = _dereq_('../menu/menu.js'); 16925 16926 var _menuMenuJs2 = _interopRequireDefault(_menuMenuJs); 16927 16928 var _menuMenuItemJs = _dereq_('../menu/menu-item.js'); 16929 16930 var _menuMenuItemJs2 = _interopRequireDefault(_menuMenuItemJs); 16931 16932 var _menuMenuButtonJs = _dereq_('../menu/menu-button.js'); 16933 16934 var _menuMenuButtonJs2 = _interopRequireDefault(_menuMenuButtonJs); 16935 16936 var _utilsFnJs = _dereq_('../utils/fn.js'); 16937 16938 var Fn = _interopRequireWildcard(_utilsFnJs); 16939 16940 var _globalDocument = _dereq_('global/document'); 16941 16942 var _globalDocument2 = _interopRequireDefault(_globalDocument); 16943 16944 var _globalWindow = _dereq_('global/window'); 16945 16946 var _globalWindow2 = _interopRequireDefault(_globalWindow); 16947 16948 var darkGray = '#222'; 16949 var lightGray = '#ccc'; 16950 var fontMap = { 16951 monospace: 'monospace', 16952 sansSerif: 'sans-serif', 16953 serif: 'serif', 16954 monospaceSansSerif: '"Andale Mono", "Lucida Console", monospace', 16955 monospaceSerif: '"Courier New", monospace', 16956 proportionalSansSerif: 'sans-serif', 16957 proportionalSerif: 'serif', 16958 casual: '"Comic Sans MS", Impact, fantasy', 16959 script: '"Monotype Corsiva", cursive', 16960 smallcaps: '"Andale Mono", "Lucida Console", monospace, sans-serif' 16961 }; 16962 16963 /** 16964 * The component for displaying text track cues 16965 * 16966 * @param {Object} player Main Player 16967 * @param {Object=} options Object of option names and values 16968 * @param {Function=} ready Ready callback function 16969 * @extends Component 16970 * @class TextTrackDisplay 16971 */ 16972 16973 var TextTrackDisplay = (function (_Component) { 16974 _inherits(TextTrackDisplay, _Component); 16975 16976 function TextTrackDisplay(player, options, ready) { 16977 _classCallCheck(this, TextTrackDisplay); 16978 16979 _Component.call(this, player, options, ready); 16980 16981 player.on('loadstart', Fn.bind(this, this.toggleDisplay)); 16982 player.on('texttrackchange', Fn.bind(this, this.updateDisplay)); 16983 16984 // This used to be called during player init, but was causing an error 16985 // if a track should show by default and the display hadn't loaded yet. 16986 // Should probably be moved to an external track loader when we support 16987 // tracks that don't need a display. 16988 player.ready(Fn.bind(this, function () { 16989 if (player.tech_ && player.tech_['featuresNativeTextTracks']) { 16990 this.hide(); 16991 return; 16992 } 16993 16994 player.on('fullscreenchange', Fn.bind(this, this.updateDisplay)); 16995 16996 var tracks = this.options_.playerOptions['tracks'] || []; 16997 for (var i = 0; i < tracks.length; i++) { 16998 var track = tracks[i]; 16999 this.player_.addRemoteTextTrack(track); 17000 } 17001 })); 17002 } 17003 17004 /** 17005 * Add cue HTML to display 17006 * 17007 * @param {Number} color Hex number for color, like #f0e 17008 * @param {Number} opacity Value for opacity,0.0 - 1.0 17009 * @return {RGBAColor} In the form 'rgba(255, 0, 0, 0.3)' 17010 * @method constructColor 17011 */ 17012 17013 /** 17014 * Toggle display texttracks 17015 * 17016 * @method toggleDisplay 17017 */ 17018 17019 TextTrackDisplay.prototype.toggleDisplay = function toggleDisplay() { 17020 if (this.player_.tech_ && this.player_.tech_['featuresNativeTextTracks']) { 17021 this.hide(); 17022 } else { 17023 this.show(); 17024 } 17025 }; 17026 17027 /** 17028 * Create the component's DOM element 17029 * 17030 * @return {Element} 17031 * @method createEl 17032 */ 17033 17034 TextTrackDisplay.prototype.createEl = function createEl() { 17035 return _Component.prototype.createEl.call(this, 'div', { 17036 className: 'vjs-text-track-display' 17037 }, { 17038 'aria-live': 'assertive', 17039 'aria-atomic': 'true' 17040 }); 17041 }; 17042 17043 /** 17044 * Clear display texttracks 17045 * 17046 * @method clearDisplay 17047 */ 17048 17049 TextTrackDisplay.prototype.clearDisplay = function clearDisplay() { 17050 if (typeof _globalWindow2['default']['WebVTT'] === 'function') { 17051 _globalWindow2['default']['WebVTT']['processCues'](_globalWindow2['default'], [], this.el_); 17052 } 17053 }; 17054 17055 /** 17056 * Update display texttracks 17057 * 17058 * @method updateDisplay 17059 */ 17060 17061 TextTrackDisplay.prototype.updateDisplay = function updateDisplay() { 17062 var tracks = this.player_.textTracks(); 17063 17064 this.clearDisplay(); 17065 17066 if (!tracks) { 17067 return; 17068 } 17069 17070 // Track display prioritization model: if multiple tracks are 'showing', 17071 // display the first 'subtitles' or 'captions' track which is 'showing', 17072 // otherwise display the first 'descriptions' track which is 'showing' 17073 17074 var descriptionsTrack = null; 17075 var captionsSubtitlesTrack = null; 17076 17077 var i = tracks.length; 17078 while (i--) { 17079 var track = tracks[i]; 17080 if (track['mode'] === 'showing') { 17081 if (track['kind'] === 'descriptions') { 17082 descriptionsTrack = track; 17083 } else { 17084 captionsSubtitlesTrack = track; 17085 } 17086 } 17087 } 17088 17089 if (captionsSubtitlesTrack) { 17090 this.updateForTrack(captionsSubtitlesTrack); 17091 } else if (descriptionsTrack) { 17092 this.updateForTrack(descriptionsTrack); 17093 } 17094 }; 17095 17096 /** 17097 * Add texttrack to texttrack list 17098 * 17099 * @param {TextTrackObject} track Texttrack object to be added to list 17100 * @method updateForTrack 17101 */ 17102 17103 TextTrackDisplay.prototype.updateForTrack = function updateForTrack(track) { 17104 if (typeof _globalWindow2['default']['WebVTT'] !== 'function' || !track['activeCues']) { 17105 return; 17106 } 17107 17108 var overrides = this.player_['textTrackSettings'].getValues(); 17109 17110 var cues = []; 17111 for (var _i = 0; _i < track['activeCues'].length; _i++) { 17112 cues.push(track['activeCues'][_i]); 17113 } 17114 17115 _globalWindow2['default']['WebVTT']['processCues'](_globalWindow2['default'], cues, this.el_); 17116 17117 var i = cues.length; 17118 while (i--) { 17119 var cue = cues[i]; 17120 if (!cue) { 17121 continue; 17122 } 17123 17124 var cueDiv = cue.displayState; 17125 if (overrides.color) { 17126 cueDiv.firstChild.style.color = overrides.color; 17127 } 17128 if (overrides.textOpacity) { 17129 tryUpdateStyle(cueDiv.firstChild, 'color', constructColor(overrides.color || '#fff', overrides.textOpacity)); 17130 } 17131 if (overrides.backgroundColor) { 17132 cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor; 17133 } 17134 if (overrides.backgroundOpacity) { 17135 tryUpdateStyle(cueDiv.firstChild, 'backgroundColor', constructColor(overrides.backgroundColor || '#000', overrides.backgroundOpacity)); 17136 } 17137 if (overrides.windowColor) { 17138 if (overrides.windowOpacity) { 17139 tryUpdateStyle(cueDiv, 'backgroundColor', constructColor(overrides.windowColor, overrides.windowOpacity)); 17140 } else { 17141 cueDiv.style.backgroundColor = overrides.windowColor; 17142 } 17143 } 17144 if (overrides.edgeStyle) { 17145 if (overrides.edgeStyle === 'dropshadow') { 17146 cueDiv.firstChild.style.textShadow = '2px 2px 3px ' + darkGray + ', 2px 2px 4px ' + darkGray + ', 2px 2px 5px ' + darkGray; 17147 } else if (overrides.edgeStyle === 'raised') { 17148 cueDiv.firstChild.style.textShadow = '1px 1px ' + darkGray + ', 2px 2px ' + darkGray + ', 3px 3px ' + darkGray; 17149 } else if (overrides.edgeStyle === 'depressed') { 17150 cueDiv.firstChild.style.textShadow = '1px 1px ' + lightGray + ', 0 1px ' + lightGray + ', -1px -1px ' + darkGray + ', 0 -1px ' + darkGray; 17151 } else if (overrides.edgeStyle === 'uniform') { 17152 cueDiv.firstChild.style.textShadow = '0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray + ', 0 0 4px ' + darkGray; 17153 } 17154 } 17155 if (overrides.fontPercent && overrides.fontPercent !== 1) { 17156 var fontSize = _globalWindow2['default'].parseFloat(cueDiv.style.fontSize); 17157 cueDiv.style.fontSize = fontSize * overrides.fontPercent + 'px'; 17158 cueDiv.style.height = 'auto'; 17159 cueDiv.style.top = 'auto'; 17160 cueDiv.style.bottom = '2px'; 17161 } 17162 if (overrides.fontFamily && overrides.fontFamily !== 'default') { 17163 if (overrides.fontFamily === 'small-caps') { 17164 cueDiv.firstChild.style.fontVariant = 'small-caps'; 17165 } else { 17166 cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily]; 17167 } 17168 } 17169 } 17170 }; 17171 17172 return TextTrackDisplay; 17173 })(_component2['default']); 17174 17175 function constructColor(color, opacity) { 17176 return 'rgba(' + 17177 // color looks like "#f0e" 17178 parseInt(color[1] + color[1], 16) + ',' + parseInt(color[2] + color[2], 16) + ',' + parseInt(color[3] + color[3], 16) + ',' + opacity + ')'; 17179 } 17180 17181 /** 17182 * Try to update style 17183 * Some style changes will throw an error, particularly in IE8. Those should be noops. 17184 * 17185 * @param {Element} el The element to be styles 17186 * @param {CSSProperty} style The CSS property to be styled 17187 * @param {CSSStyle} rule The actual style to be applied to the property 17188 * @method tryUpdateStyle 17189 */ 17190 function tryUpdateStyle(el, style, rule) { 17191 // 17192 try { 17193 el.style[style] = rule; 17194 } catch (e) {} 17195 } 17196 17197 _component2['default'].registerComponent('TextTrackDisplay', TextTrackDisplay); 17198 exports['default'] = TextTrackDisplay; 17199 module.exports = exports['default']; 17200 17201 },{"../component":67,"../menu/menu-button.js":106,"../menu/menu-item.js":107,"../menu/menu.js":108,"../utils/fn.js":136,"global/document":1,"global/window":2}],126:[function(_dereq_,module,exports){ 17202 /** 17203 * @file text-track-enums.js 17204 */ 17205 17206 /** 17207 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackmode 17208 * 17209 * enum TextTrackMode { "disabled", "hidden", "showing" }; 17210 */ 17211 'use strict'; 17212 17213 exports.__esModule = true; 17214 var TextTrackMode = { 17215 disabled: 'disabled', 17216 hidden: 'hidden', 17217 showing: 'showing' 17218 }; 17219 17220 /** 17221 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrackkind 17222 * 17223 * enum TextTrackKind { 17224 * "subtitles", 17225 * "captions", 17226 * "descriptions", 17227 * "chapters", 17228 * "metadata" 17229 * }; 17230 */ 17231 var TextTrackKind = { 17232 subtitles: 'subtitles', 17233 captions: 'captions', 17234 descriptions: 'descriptions', 17235 chapters: 'chapters', 17236 metadata: 'metadata' 17237 }; 17238 17239 /* jshint ignore:start */ 17240 // we ignore jshint here because it does not see 17241 // TextTrackMode or TextTrackKind as defined here somehow... 17242 exports.TextTrackMode = TextTrackMode; 17243 exports.TextTrackKind = TextTrackKind; 17244 17245 /* jshint ignore:end */ 17246 17247 },{}],127:[function(_dereq_,module,exports){ 17248 /** 17249 * Utilities for capturing text track state and re-creating tracks 17250 * based on a capture. 17251 * 17252 * @file text-track-list-converter.js 17253 */ 17254 17255 /** 17256 * Examine a single text track and return a JSON-compatible javascript 17257 * object that represents the text track's state. 17258 * @param track {TextTrackObject} the text track to query 17259 * @return {Object} a serializable javascript representation of the 17260 * @private 17261 */ 17262 'use strict'; 17263 17264 exports.__esModule = true; 17265 var trackToJson_ = function trackToJson_(track) { 17266 var ret = ['kind', 'label', 'language', 'id', 'inBandMetadataTrackDispatchType', 'mode', 'src'].reduce(function (acc, prop, i) { 17267 if (track[prop]) { 17268 acc[prop] = track[prop]; 17269 } 17270 17271 return acc; 17272 }, { 17273 cues: track.cues && Array.prototype.map.call(track.cues, function (cue) { 17274 return { 17275 startTime: cue.startTime, 17276 endTime: cue.endTime, 17277 text: cue.text, 17278 id: cue.id 17279 }; 17280 }) 17281 }); 17282 17283 return ret; 17284 }; 17285 17286 /** 17287 * Examine a tech and return a JSON-compatible javascript array that 17288 * represents the state of all text tracks currently configured. The 17289 * return array is compatible with `jsonToTextTracks`. 17290 * @param tech {tech} the tech object to query 17291 * @return {Array} a serializable javascript representation of the 17292 * @function textTracksToJson 17293 */ 17294 var textTracksToJson = function textTracksToJson(tech) { 17295 17296 var trackEls = tech.$$('track'); 17297 17298 var trackObjs = Array.prototype.map.call(trackEls, function (t) { 17299 return t.track; 17300 }); 17301 var tracks = Array.prototype.map.call(trackEls, function (trackEl) { 17302 var json = trackToJson_(trackEl.track); 17303 if (trackEl.src) { 17304 json.src = trackEl.src; 17305 } 17306 return json; 17307 }); 17308 17309 return tracks.concat(Array.prototype.filter.call(tech.textTracks(), function (track) { 17310 return trackObjs.indexOf(track) === -1; 17311 }).map(trackToJson_)); 17312 }; 17313 17314 /** 17315 * Creates a set of remote text tracks on a tech based on an array of 17316 * javascript text track representations. 17317 * @param json {Array} an array of text track representation objects, 17318 * like those that would be produced by `textTracksToJson` 17319 * @param tech {tech} the tech to create text tracks on 17320 * @function jsonToTextTracks 17321 */ 17322 var jsonToTextTracks = function jsonToTextTracks(json, tech) { 17323 json.forEach(function (track) { 17324 var addedTrack = tech.addRemoteTextTrack(track).track; 17325 if (!track.src && track.cues) { 17326 track.cues.forEach(function (cue) { 17327 return addedTrack.addCue(cue); 17328 }); 17329 } 17330 }); 17331 17332 return tech.textTracks(); 17333 }; 17334 17335 exports['default'] = { textTracksToJson: textTracksToJson, jsonToTextTracks: jsonToTextTracks, trackToJson_: trackToJson_ }; 17336 module.exports = exports['default']; 17337 17338 },{}],128:[function(_dereq_,module,exports){ 17339 /** 17340 * @file text-track-list.js 17341 */ 17342 'use strict'; 17343 17344 exports.__esModule = true; 17345 17346 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; } } 17347 17348 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 17349 17350 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 17351 17352 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; } 17353 17354 var _eventTarget = _dereq_('../event-target'); 17355 17356 var _eventTarget2 = _interopRequireDefault(_eventTarget); 17357 17358 var _utilsFnJs = _dereq_('../utils/fn.js'); 17359 17360 var Fn = _interopRequireWildcard(_utilsFnJs); 17361 17362 var _utilsBrowserJs = _dereq_('../utils/browser.js'); 17363 17364 var browser = _interopRequireWildcard(_utilsBrowserJs); 17365 17366 var _globalDocument = _dereq_('global/document'); 17367 17368 var _globalDocument2 = _interopRequireDefault(_globalDocument); 17369 17370 /** 17371 * A text track list as defined in: 17372 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttracklist 17373 * 17374 * interface TextTrackList : EventTarget { 17375 * readonly attribute unsigned long length; 17376 * getter TextTrack (unsigned long index); 17377 * TextTrack? getTrackById(DOMString id); 17378 * 17379 * attribute EventHandler onchange; 17380 * attribute EventHandler onaddtrack; 17381 * attribute EventHandler onremovetrack; 17382 * }; 17383 * 17384 * @param {Track[]} tracks A list of tracks to initialize the list with 17385 * @extends EventTarget 17386 * @class TextTrackList 17387 */ 17388 17389 var TextTrackList = (function (_EventTarget) { 17390 _inherits(TextTrackList, _EventTarget); 17391 17392 function TextTrackList() { 17393 var tracks = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0]; 17394 17395 _classCallCheck(this, TextTrackList); 17396 17397 _EventTarget.call(this); 17398 var list = this; 17399 17400 if (browser.IS_IE8) { 17401 list = _globalDocument2['default'].createElement('custom'); 17402 17403 for (var prop in TextTrackList.prototype) { 17404 if (prop !== 'constructor') { 17405 list[prop] = TextTrackList.prototype[prop]; 17406 } 17407 } 17408 } 17409 17410 list.tracks_ = []; 17411 17412 Object.defineProperty(list, 'length', { 17413 get: function get() { 17414 return this.tracks_.length; 17415 } 17416 }); 17417 17418 for (var i = 0; i < tracks.length; i++) { 17419 list.addTrack_(tracks[i]); 17420 } 17421 17422 if (browser.IS_IE8) { 17423 return list; 17424 } 17425 } 17426 17427 /** 17428 * change - One or more tracks in the track list have been enabled or disabled. 17429 * addtrack - A track has been added to the track list. 17430 * removetrack - A track has been removed from the track list. 17431 */ 17432 17433 /** 17434 * Add TextTrack from TextTrackList 17435 * 17436 * @param {TextTrack} track 17437 * @method addTrack_ 17438 * @private 17439 */ 17440 17441 TextTrackList.prototype.addTrack_ = function addTrack_(track) { 17442 var index = this.tracks_.length; 17443 17444 if (!('' + index in this)) { 17445 Object.defineProperty(this, index, { 17446 get: function get() { 17447 return this.tracks_[index]; 17448 } 17449 }); 17450 } 17451 17452 track.addEventListener('modechange', Fn.bind(this, function () { 17453 this.trigger('change'); 17454 })); 17455 17456 // Do not add duplicate tracks 17457 if (this.tracks_.indexOf(track) === -1) { 17458 this.tracks_.push(track); 17459 this.trigger({ 17460 track: track, 17461 type: 'addtrack' 17462 }); 17463 } 17464 }; 17465 17466 /** 17467 * Remove TextTrack from TextTrackList 17468 * NOTE: Be mindful of what is passed in as it may be a HTMLTrackElement 17469 * 17470 * @param {TextTrack} rtrack 17471 * @method removeTrack_ 17472 * @private 17473 */ 17474 17475 TextTrackList.prototype.removeTrack_ = function removeTrack_(rtrack) { 17476 var track = undefined; 17477 17478 for (var i = 0, l = this.length; i < l; i++) { 17479 if (this[i] === rtrack) { 17480 track = this[i]; 17481 if (track.off) { 17482 track.off(); 17483 } 17484 17485 this.tracks_.splice(i, 1); 17486 17487 break; 17488 } 17489 } 17490 17491 if (!track) { 17492 return; 17493 } 17494 17495 this.trigger({ 17496 track: track, 17497 type: 'removetrack' 17498 }); 17499 }; 17500 17501 /** 17502 * Get a TextTrack from TextTrackList by a tracks id 17503 * 17504 * @param {String} id - the id of the track to get 17505 * @method getTrackById 17506 * @return {TextTrack} 17507 * @private 17508 */ 17509 17510 TextTrackList.prototype.getTrackById = function getTrackById(id) { 17511 var result = null; 17512 17513 for (var i = 0, l = this.length; i < l; i++) { 17514 var track = this[i]; 17515 17516 if (track.id === id) { 17517 result = track; 17518 break; 17519 } 17520 } 17521 17522 return result; 17523 }; 17524 17525 return TextTrackList; 17526 })(_eventTarget2['default']); 17527 17528 TextTrackList.prototype.allowedEvents_ = { 17529 change: 'change', 17530 addtrack: 'addtrack', 17531 removetrack: 'removetrack' 17532 }; 17533 17534 // emulate attribute EventHandler support to allow for feature detection 17535 for (var _event in TextTrackList.prototype.allowedEvents_) { 17536 TextTrackList.prototype['on' + _event] = null; 17537 } 17538 17539 exports['default'] = TextTrackList; 17540 module.exports = exports['default']; 17541 17542 },{"../event-target":101,"../utils/browser.js":131,"../utils/fn.js":136,"global/document":1}],129:[function(_dereq_,module,exports){ 17543 /** 17544 * @file text-track-settings.js 17545 */ 17546 'use strict'; 17547 17548 exports.__esModule = true; 17549 17550 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; } } 17551 17552 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 17553 17554 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 17555 17556 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; } 17557 17558 var _component = _dereq_('../component'); 17559 17560 var _component2 = _interopRequireDefault(_component); 17561 17562 var _utilsEventsJs = _dereq_('../utils/events.js'); 17563 17564 var Events = _interopRequireWildcard(_utilsEventsJs); 17565 17566 var _utilsFnJs = _dereq_('../utils/fn.js'); 17567 17568 var Fn = _interopRequireWildcard(_utilsFnJs); 17569 17570 var _utilsLogJs = _dereq_('../utils/log.js'); 17571 17572 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 17573 17574 var _safeJsonParseTuple = _dereq_('safe-json-parse/tuple'); 17575 17576 var _safeJsonParseTuple2 = _interopRequireDefault(_safeJsonParseTuple); 17577 17578 var _globalWindow = _dereq_('global/window'); 17579 17580 var _globalWindow2 = _interopRequireDefault(_globalWindow); 17581 17582 /** 17583 * Manipulate settings of texttracks 17584 * 17585 * @param {Object} player Main Player 17586 * @param {Object=} options Object of option names and values 17587 * @extends Component 17588 * @class TextTrackSettings 17589 */ 17590 17591 var TextTrackSettings = (function (_Component) { 17592 _inherits(TextTrackSettings, _Component); 17593 17594 function TextTrackSettings(player, options) { 17595 _classCallCheck(this, TextTrackSettings); 17596 17597 _Component.call(this, player, options); 17598 this.hide(); 17599 17600 // Grab `persistTextTrackSettings` from the player options if not passed in child options 17601 if (options.persistTextTrackSettings === undefined) { 17602 this.options_.persistTextTrackSettings = this.options_.playerOptions.persistTextTrackSettings; 17603 } 17604 17605 Events.on(this.$('.vjs-done-button'), 'click', Fn.bind(this, function () { 17606 this.saveSettings(); 17607 this.hide(); 17608 })); 17609 17610 Events.on(this.$('.vjs-default-button'), 'click', Fn.bind(this, function () { 17611 this.$('.vjs-fg-color > select').selectedIndex = 0; 17612 this.$('.vjs-bg-color > select').selectedIndex = 0; 17613 this.$('.window-color > select').selectedIndex = 0; 17614 this.$('.vjs-text-opacity > select').selectedIndex = 0; 17615 this.$('.vjs-bg-opacity > select').selectedIndex = 0; 17616 this.$('.vjs-window-opacity > select').selectedIndex = 0; 17617 this.$('.vjs-edge-style select').selectedIndex = 0; 17618 this.$('.vjs-font-family select').selectedIndex = 0; 17619 this.$('.vjs-font-percent select').selectedIndex = 2; 17620 this.updateDisplay(); 17621 })); 17622 17623 Events.on(this.$('.vjs-fg-color > select'), 'change', Fn.bind(this, this.updateDisplay)); 17624 Events.on(this.$('.vjs-bg-color > select'), 'change', Fn.bind(this, this.updateDisplay)); 17625 Events.on(this.$('.window-color > select'), 'change', Fn.bind(this, this.updateDisplay)); 17626 Events.on(this.$('.vjs-text-opacity > select'), 'change', Fn.bind(this, this.updateDisplay)); 17627 Events.on(this.$('.vjs-bg-opacity > select'), 'change', Fn.bind(this, this.updateDisplay)); 17628 Events.on(this.$('.vjs-window-opacity > select'), 'change', Fn.bind(this, this.updateDisplay)); 17629 Events.on(this.$('.vjs-font-percent select'), 'change', Fn.bind(this, this.updateDisplay)); 17630 Events.on(this.$('.vjs-edge-style select'), 'change', Fn.bind(this, this.updateDisplay)); 17631 Events.on(this.$('.vjs-font-family select'), 'change', Fn.bind(this, this.updateDisplay)); 17632 17633 if (this.options_.persistTextTrackSettings) { 17634 this.restoreSettings(); 17635 } 17636 } 17637 17638 /** 17639 * Create the component's DOM element 17640 * 17641 * @return {Element} 17642 * @method createEl 17643 */ 17644 17645 TextTrackSettings.prototype.createEl = function createEl() { 17646 return _Component.prototype.createEl.call(this, 'div', { 17647 className: 'vjs-caption-settings vjs-modal-overlay', 17648 innerHTML: captionOptionsMenuTemplate() 17649 }); 17650 }; 17651 17652 /** 17653 * Get texttrack settings 17654 * Settings are 17655 * .vjs-edge-style 17656 * .vjs-font-family 17657 * .vjs-fg-color 17658 * .vjs-text-opacity 17659 * .vjs-bg-color 17660 * .vjs-bg-opacity 17661 * .window-color 17662 * .vjs-window-opacity 17663 * 17664 * @return {Object} 17665 * @method getValues 17666 */ 17667 17668 TextTrackSettings.prototype.getValues = function getValues() { 17669 var textEdge = getSelectedOptionValue(this.$('.vjs-edge-style select')); 17670 var fontFamily = getSelectedOptionValue(this.$('.vjs-font-family select')); 17671 var fgColor = getSelectedOptionValue(this.$('.vjs-fg-color > select')); 17672 var textOpacity = getSelectedOptionValue(this.$('.vjs-text-opacity > select')); 17673 var bgColor = getSelectedOptionValue(this.$('.vjs-bg-color > select')); 17674 var bgOpacity = getSelectedOptionValue(this.$('.vjs-bg-opacity > select')); 17675 var windowColor = getSelectedOptionValue(this.$('.window-color > select')); 17676 var windowOpacity = getSelectedOptionValue(this.$('.vjs-window-opacity > select')); 17677 var fontPercent = _globalWindow2['default']['parseFloat'](getSelectedOptionValue(this.$('.vjs-font-percent > select'))); 17678 17679 var result = { 17680 'backgroundOpacity': bgOpacity, 17681 'textOpacity': textOpacity, 17682 'windowOpacity': windowOpacity, 17683 'edgeStyle': textEdge, 17684 'fontFamily': fontFamily, 17685 'color': fgColor, 17686 'backgroundColor': bgColor, 17687 'windowColor': windowColor, 17688 'fontPercent': fontPercent 17689 }; 17690 for (var _name in result) { 17691 if (result[_name] === '' || result[_name] === 'none' || _name === 'fontPercent' && result[_name] === 1.00) { 17692 delete result[_name]; 17693 } 17694 } 17695 return result; 17696 }; 17697 17698 /** 17699 * Set texttrack settings 17700 * Settings are 17701 * .vjs-edge-style 17702 * .vjs-font-family 17703 * .vjs-fg-color 17704 * .vjs-text-opacity 17705 * .vjs-bg-color 17706 * .vjs-bg-opacity 17707 * .window-color 17708 * .vjs-window-opacity 17709 * 17710 * @param {Object} values Object with texttrack setting values 17711 * @method setValues 17712 */ 17713 17714 TextTrackSettings.prototype.setValues = function setValues(values) { 17715 setSelectedOption(this.$('.vjs-edge-style select'), values.edgeStyle); 17716 setSelectedOption(this.$('.vjs-font-family select'), values.fontFamily); 17717 setSelectedOption(this.$('.vjs-fg-color > select'), values.color); 17718 setSelectedOption(this.$('.vjs-text-opacity > select'), values.textOpacity); 17719 setSelectedOption(this.$('.vjs-bg-color > select'), values.backgroundColor); 17720 setSelectedOption(this.$('.vjs-bg-opacity > select'), values.backgroundOpacity); 17721 setSelectedOption(this.$('.window-color > select'), values.windowColor); 17722 setSelectedOption(this.$('.vjs-window-opacity > select'), values.windowOpacity); 17723 17724 var fontPercent = values.fontPercent; 17725 17726 if (fontPercent) { 17727 fontPercent = fontPercent.toFixed(2); 17728 } 17729 17730 setSelectedOption(this.$('.vjs-font-percent > select'), fontPercent); 17731 }; 17732 17733 /** 17734 * Restore texttrack settings 17735 * 17736 * @method restoreSettings 17737 */ 17738 17739 TextTrackSettings.prototype.restoreSettings = function restoreSettings() { 17740 var err = undefined, 17741 values = undefined; 17742 17743 try { 17744 var _safeParseTuple = _safeJsonParseTuple2['default'](_globalWindow2['default'].localStorage.getItem('vjs-text-track-settings')); 17745 17746 err = _safeParseTuple[0]; 17747 values = _safeParseTuple[1]; 17748 17749 if (err) { 17750 _utilsLogJs2['default'].error(err); 17751 } 17752 } catch (e) { 17753 _utilsLogJs2['default'].warn(e); 17754 } 17755 17756 if (values) { 17757 this.setValues(values); 17758 } 17759 }; 17760 17761 /** 17762 * Save texttrack settings to local storage 17763 * 17764 * @method saveSettings 17765 */ 17766 17767 TextTrackSettings.prototype.saveSettings = function saveSettings() { 17768 if (!this.options_.persistTextTrackSettings) { 17769 return; 17770 } 17771 17772 var values = this.getValues(); 17773 try { 17774 if (Object.getOwnPropertyNames(values).length > 0) { 17775 _globalWindow2['default'].localStorage.setItem('vjs-text-track-settings', JSON.stringify(values)); 17776 } else { 17777 _globalWindow2['default'].localStorage.removeItem('vjs-text-track-settings'); 17778 } 17779 } catch (e) { 17780 _utilsLogJs2['default'].warn(e); 17781 } 17782 }; 17783 17784 /** 17785 * Update display of texttrack settings 17786 * 17787 * @method updateDisplay 17788 */ 17789 17790 TextTrackSettings.prototype.updateDisplay = function updateDisplay() { 17791 var ttDisplay = this.player_.getChild('textTrackDisplay'); 17792 if (ttDisplay) { 17793 ttDisplay.updateDisplay(); 17794 } 17795 }; 17796 17797 return TextTrackSettings; 17798 })(_component2['default']); 17799 17800 _component2['default'].registerComponent('TextTrackSettings', TextTrackSettings); 17801 17802 function getSelectedOptionValue(target) { 17803 var selectedOption = undefined; 17804 // not all browsers support selectedOptions, so, fallback to options 17805 if (target.selectedOptions) { 17806 selectedOption = target.selectedOptions[0]; 17807 } else if (target.options) { 17808 selectedOption = target.options[target.options.selectedIndex]; 17809 } 17810 17811 return selectedOption.value; 17812 } 17813 17814 function setSelectedOption(target, value) { 17815 if (!value) { 17816 return; 17817 } 17818 17819 var i = undefined; 17820 for (i = 0; i < target.options.length; i++) { 17821 var option = target.options[i]; 17822 if (option.value === value) { 17823 break; 17824 } 17825 } 17826 17827 target.selectedIndex = i; 17828 } 17829 17830 function captionOptionsMenuTemplate() { 17831 var template = '<div class="vjs-tracksettings">\n <div class="vjs-tracksettings-colors">\n <div class="vjs-fg-color vjs-tracksetting">\n <label class="vjs-label">Foreground</label>\n <select>\n <option value="">---</option>\n <option value="#FFF">White</option>\n <option value="#000">Black</option>\n <option value="#F00">Red</option>\n <option value="#0F0">Green</option>\n <option value="#00F">Blue</option>\n <option value="#FF0">Yellow</option>\n <option value="#F0F">Magenta</option>\n <option value="#0FF">Cyan</option>\n </select>\n <span class="vjs-text-opacity vjs-opacity">\n <select>\n <option value="">---</option>\n <option value="1">Opaque</option>\n <option value="0.5">Semi-Opaque</option>\n </select>\n </span>\n </div> <!-- vjs-fg-color -->\n <div class="vjs-bg-color vjs-tracksetting">\n <label class="vjs-label">Background</label>\n <select>\n <option value="">---</option>\n <option value="#FFF">White</option>\n <option value="#000">Black</option>\n <option value="#F00">Red</option>\n <option value="#0F0">Green</option>\n <option value="#00F">Blue</option>\n <option value="#FF0">Yellow</option>\n <option value="#F0F">Magenta</option>\n <option value="#0FF">Cyan</option>\n </select>\n <span class="vjs-bg-opacity vjs-opacity">\n <select>\n <option value="">---</option>\n <option value="1">Opaque</option>\n <option value="0.5">Semi-Transparent</option>\n <option value="0">Transparent</option>\n </select>\n </span>\n </div> <!-- vjs-bg-color -->\n <div class="window-color vjs-tracksetting">\n <label class="vjs-label">Window</label>\n <select>\n <option value="">---</option>\n <option value="#FFF">White</option>\n <option value="#000">Black</option>\n <option value="#F00">Red</option>\n <option value="#0F0">Green</option>\n <option value="#00F">Blue</option>\n <option value="#FF0">Yellow</option>\n <option value="#F0F">Magenta</option>\n <option value="#0FF">Cyan</option>\n </select>\n <span class="vjs-window-opacity vjs-opacity">\n <select>\n <option value="">---</option>\n <option value="1">Opaque</option>\n <option value="0.5">Semi-Transparent</option>\n <option value="0">Transparent</option>\n </select>\n </span>\n </div> <!-- vjs-window-color -->\n </div> <!-- vjs-tracksettings -->\n <div class="vjs-tracksettings-font">\n <div class="vjs-font-percent vjs-tracksetting">\n <label class="vjs-label">Font Size</label>\n <select>\n <option value="0.50">50%</option>\n <option value="0.75">75%</option>\n <option value="1.00" selected>100%</option>\n <option value="1.25">125%</option>\n <option value="1.50">150%</option>\n <option value="1.75">175%</option>\n <option value="2.00">200%</option>\n <option value="3.00">300%</option>\n <option value="4.00">400%</option>\n </select>\n </div> <!-- vjs-font-percent -->\n <div class="vjs-edge-style vjs-tracksetting">\n <label class="vjs-label">Text Edge Style</label>\n <select>\n <option value="none">None</option>\n <option value="raised">Raised</option>\n <option value="depressed">Depressed</option>\n <option value="uniform">Uniform</option>\n <option value="dropshadow">Dropshadow</option>\n </select>\n </div> <!-- vjs-edge-style -->\n <div class="vjs-font-family vjs-tracksetting">\n <label class="vjs-label">Font Family</label>\n <select>\n <option value="">Default</option>\n <option value="monospaceSerif">Monospace Serif</option>\n <option value="proportionalSerif">Proportional Serif</option>\n <option value="monospaceSansSerif">Monospace Sans-Serif</option>\n <option value="proportionalSansSerif">Proportional Sans-Serif</option>\n <option value="casual">Casual</option>\n <option value="script">Script</option>\n <option value="small-caps">Small Caps</option>\n </select>\n </div> <!-- vjs-font-family -->\n </div>\n </div>\n <div class="vjs-tracksettings-controls">\n <button class="vjs-default-button">Defaults</button>\n <button class="vjs-done-button">Done</button>\n </div>'; 17832 17833 return template; 17834 } 17835 17836 exports['default'] = TextTrackSettings; 17837 module.exports = exports['default']; 17838 17839 },{"../component":67,"../utils/events.js":135,"../utils/fn.js":136,"../utils/log.js":139,"global/window":2,"safe-json-parse/tuple":54}],130:[function(_dereq_,module,exports){ 17840 /** 17841 * @file text-track.js 17842 */ 17843 'use strict'; 17844 17845 exports.__esModule = true; 17846 17847 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; } } 17848 17849 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 17850 17851 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 17852 17853 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; } 17854 17855 var _textTrackCueList = _dereq_('./text-track-cue-list'); 17856 17857 var _textTrackCueList2 = _interopRequireDefault(_textTrackCueList); 17858 17859 var _utilsFnJs = _dereq_('../utils/fn.js'); 17860 17861 var Fn = _interopRequireWildcard(_utilsFnJs); 17862 17863 var _utilsGuidJs = _dereq_('../utils/guid.js'); 17864 17865 var Guid = _interopRequireWildcard(_utilsGuidJs); 17866 17867 var _utilsBrowserJs = _dereq_('../utils/browser.js'); 17868 17869 var browser = _interopRequireWildcard(_utilsBrowserJs); 17870 17871 var _textTrackEnums = _dereq_('./text-track-enums'); 17872 17873 var TextTrackEnum = _interopRequireWildcard(_textTrackEnums); 17874 17875 var _utilsLogJs = _dereq_('../utils/log.js'); 17876 17877 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 17878 17879 var _eventTarget = _dereq_('../event-target'); 17880 17881 var _eventTarget2 = _interopRequireDefault(_eventTarget); 17882 17883 var _globalDocument = _dereq_('global/document'); 17884 17885 var _globalDocument2 = _interopRequireDefault(_globalDocument); 17886 17887 var _globalWindow = _dereq_('global/window'); 17888 17889 var _globalWindow2 = _interopRequireDefault(_globalWindow); 17890 17891 var _utilsUrlJs = _dereq_('../utils/url.js'); 17892 17893 var _xhr = _dereq_('xhr'); 17894 17895 var _xhr2 = _interopRequireDefault(_xhr); 17896 17897 /** 17898 * takes a webvtt file contents and parses it into cues 17899 * 17900 * @param {String} srcContent webVTT file contents 17901 * @param {Track} track track to addcues to 17902 */ 17903 var parseCues = function parseCues(srcContent, track) { 17904 var parser = new _globalWindow2['default'].WebVTT.Parser(_globalWindow2['default'], _globalWindow2['default'].vttjs, _globalWindow2['default'].WebVTT.StringDecoder()); 17905 17906 parser.oncue = function (cue) { 17907 track.addCue(cue); 17908 }; 17909 17910 parser.onparsingerror = function (error) { 17911 _utilsLogJs2['default'].error(error); 17912 }; 17913 17914 parser.onflush = function () { 17915 track.trigger({ 17916 type: 'loadeddata', 17917 target: track 17918 }); 17919 }; 17920 17921 parser.parse(srcContent); 17922 parser.flush(); 17923 }; 17924 17925 /** 17926 * load a track from a specifed url 17927 * 17928 * @param {String} src url to load track from 17929 * @param {Track} track track to addcues to 17930 */ 17931 var loadTrack = function loadTrack(src, track) { 17932 var opts = { 17933 uri: src 17934 }; 17935 var crossOrigin = _utilsUrlJs.isCrossOrigin(src); 17936 17937 if (crossOrigin) { 17938 opts.cors = crossOrigin; 17939 } 17940 17941 _xhr2['default'](opts, Fn.bind(this, function (err, response, responseBody) { 17942 if (err) { 17943 return _utilsLogJs2['default'].error(err, response); 17944 } 17945 17946 track.loaded_ = true; 17947 17948 // Make sure that vttjs has loaded, otherwise, wait till it finished loading 17949 // NOTE: this is only used for the alt/video.novtt.js build 17950 if (typeof _globalWindow2['default'].WebVTT !== 'function') { 17951 if (track.tech_) { 17952 (function () { 17953 var loadHandler = function loadHandler() { 17954 return parseCues(responseBody, track); 17955 }; 17956 track.tech_.on('vttjsloaded', loadHandler); 17957 track.tech_.on('vttjserror', function () { 17958 _utilsLogJs2['default'].error('vttjs failed to load, stopping trying to process ' + track.src); 17959 track.tech_.off('vttjsloaded', loadHandler); 17960 }); 17961 })(); 17962 } 17963 } else { 17964 parseCues(responseBody, track); 17965 } 17966 })); 17967 }; 17968 17969 /** 17970 * A single text track as defined in: 17971 * https://html.spec.whatwg.org/multipage/embedded-content.html#texttrack 17972 * 17973 * interface TextTrack : EventTarget { 17974 * readonly attribute TextTrackKind kind; 17975 * readonly attribute DOMString label; 17976 * readonly attribute DOMString language; 17977 * 17978 * readonly attribute DOMString id; 17979 * readonly attribute DOMString inBandMetadataTrackDispatchType; 17980 * 17981 * attribute TextTrackMode mode; 17982 * 17983 * readonly attribute TextTrackCueList? cues; 17984 * readonly attribute TextTrackCueList? activeCues; 17985 * 17986 * void addCue(TextTrackCue cue); 17987 * void removeCue(TextTrackCue cue); 17988 * 17989 * attribute EventHandler oncuechange; 17990 * }; 17991 * 17992 * @param {Object=} options Object of option names and values 17993 * @extends EventTarget 17994 * @class TextTrack 17995 */ 17996 17997 var TextTrack = (function (_EventTarget) { 17998 _inherits(TextTrack, _EventTarget); 17999 18000 function TextTrack() { 18001 var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; 18002 18003 _classCallCheck(this, TextTrack); 18004 18005 _EventTarget.call(this); 18006 if (!options.tech) { 18007 throw new Error('A tech was not provided.'); 18008 } 18009 18010 var tt = this; 18011 18012 if (browser.IS_IE8) { 18013 tt = _globalDocument2['default'].createElement('custom'); 18014 18015 for (var prop in TextTrack.prototype) { 18016 if (prop !== 'constructor') { 18017 tt[prop] = TextTrack.prototype[prop]; 18018 } 18019 } 18020 } 18021 18022 tt.tech_ = options.tech; 18023 18024 var mode = TextTrackEnum.TextTrackMode[options.mode] || 'disabled'; 18025 var kind = TextTrackEnum.TextTrackKind[options.kind] || 'subtitles'; 18026 var label = options.label || ''; 18027 var language = options.language || options.srclang || ''; 18028 var id = options.id || 'vjs_text_track_' + Guid.newGUID(); 18029 18030 if (kind === 'metadata' || kind === 'chapters') { 18031 mode = 'hidden'; 18032 } 18033 18034 tt.cues_ = []; 18035 tt.activeCues_ = []; 18036 18037 var cues = new _textTrackCueList2['default'](tt.cues_); 18038 var activeCues = new _textTrackCueList2['default'](tt.activeCues_); 18039 var changed = false; 18040 var timeupdateHandler = Fn.bind(tt, function () { 18041 this.activeCues; 18042 if (changed) { 18043 this.trigger('cuechange'); 18044 changed = false; 18045 } 18046 }); 18047 18048 if (mode !== 'disabled') { 18049 tt.tech_.on('timeupdate', timeupdateHandler); 18050 } 18051 18052 Object.defineProperty(tt, 'kind', { 18053 get: function get() { 18054 return kind; 18055 }, 18056 set: function set() {} 18057 }); 18058 18059 Object.defineProperty(tt, 'label', { 18060 get: function get() { 18061 return label; 18062 }, 18063 set: function set() {} 18064 }); 18065 18066 Object.defineProperty(tt, 'language', { 18067 get: function get() { 18068 return language; 18069 }, 18070 set: function set() {} 18071 }); 18072 18073 Object.defineProperty(tt, 'id', { 18074 get: function get() { 18075 return id; 18076 }, 18077 set: function set() {} 18078 }); 18079 18080 Object.defineProperty(tt, 'mode', { 18081 get: function get() { 18082 return mode; 18083 }, 18084 set: function set(newMode) { 18085 if (!TextTrackEnum.TextTrackMode[newMode]) { 18086 return; 18087 } 18088 mode = newMode; 18089 if (mode === 'showing') { 18090 this.tech_.on('timeupdate', timeupdateHandler); 18091 } 18092 this.trigger('modechange'); 18093 } 18094 }); 18095 18096 Object.defineProperty(tt, 'cues', { 18097 get: function get() { 18098 if (!this.loaded_) { 18099 return null; 18100 } 18101 18102 return cues; 18103 }, 18104 set: function set() {} 18105 }); 18106 18107 Object.defineProperty(tt, 'activeCues', { 18108 get: function get() { 18109 if (!this.loaded_) { 18110 return null; 18111 } 18112 18113 // nothing to do 18114 if (this.cues.length === 0) { 18115 return activeCues; 18116 } 18117 18118 var ct = this.tech_.currentTime(); 18119 var active = []; 18120 18121 for (var i = 0, l = this.cues.length; i < l; i++) { 18122 var cue = this.cues[i]; 18123 18124 if (cue.startTime <= ct && cue.endTime >= ct) { 18125 active.push(cue); 18126 } else if (cue.startTime === cue.endTime && cue.startTime <= ct && cue.startTime + 0.5 >= ct) { 18127 active.push(cue); 18128 } 18129 } 18130 18131 changed = false; 18132 18133 if (active.length !== this.activeCues_.length) { 18134 changed = true; 18135 } else { 18136 for (var i = 0; i < active.length; i++) { 18137 if (this.activeCues_.indexOf(active[i]) === -1) { 18138 changed = true; 18139 } 18140 } 18141 } 18142 18143 this.activeCues_ = active; 18144 activeCues.setCues_(this.activeCues_); 18145 18146 return activeCues; 18147 }, 18148 set: function set() {} 18149 }); 18150 18151 if (options.src) { 18152 tt.src = options.src; 18153 loadTrack(options.src, tt); 18154 } else { 18155 tt.loaded_ = true; 18156 } 18157 18158 if (browser.IS_IE8) { 18159 return tt; 18160 } 18161 } 18162 18163 /** 18164 * cuechange - One or more cues in the track have become active or stopped being active. 18165 */ 18166 18167 /** 18168 * add a cue to the internal list of cues 18169 * 18170 * @param {Object} cue the cue to add to our internal list 18171 * @method addCue 18172 */ 18173 18174 TextTrack.prototype.addCue = function addCue(cue) { 18175 var tracks = this.tech_.textTracks(); 18176 18177 if (tracks) { 18178 for (var i = 0; i < tracks.length; i++) { 18179 if (tracks[i] !== this) { 18180 tracks[i].removeCue(cue); 18181 } 18182 } 18183 } 18184 18185 this.cues_.push(cue); 18186 this.cues.setCues_(this.cues_); 18187 }; 18188 18189 /** 18190 * remvoe a cue from our internal list 18191 * 18192 * @param {Object} removeCue the cue to remove from our internal list 18193 * @method removeCue 18194 */ 18195 18196 TextTrack.prototype.removeCue = function removeCue(_removeCue) { 18197 var removed = false; 18198 18199 for (var i = 0, l = this.cues_.length; i < l; i++) { 18200 var cue = this.cues_[i]; 18201 18202 if (cue === _removeCue) { 18203 this.cues_.splice(i, 1); 18204 removed = true; 18205 } 18206 } 18207 18208 if (removed) { 18209 this.cues.setCues_(this.cues_); 18210 } 18211 }; 18212 18213 return TextTrack; 18214 })(_eventTarget2['default']); 18215 18216 TextTrack.prototype.allowedEvents_ = { 18217 cuechange: 'cuechange' 18218 }; 18219 18220 exports['default'] = TextTrack; 18221 module.exports = exports['default']; 18222 18223 },{"../event-target":101,"../utils/browser.js":131,"../utils/fn.js":136,"../utils/guid.js":138,"../utils/log.js":139,"../utils/url.js":144,"./text-track-cue-list":124,"./text-track-enums":126,"global/document":1,"global/window":2,"xhr":56}],131:[function(_dereq_,module,exports){ 18224 /** 18225 * @file browser.js 18226 */ 18227 'use strict'; 18228 18229 exports.__esModule = true; 18230 18231 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 18232 18233 var _globalDocument = _dereq_('global/document'); 18234 18235 var _globalDocument2 = _interopRequireDefault(_globalDocument); 18236 18237 var _globalWindow = _dereq_('global/window'); 18238 18239 var _globalWindow2 = _interopRequireDefault(_globalWindow); 18240 18241 var USER_AGENT = _globalWindow2['default'].navigator.userAgent; 18242 var webkitVersionMap = /AppleWebKit\/([\d.]+)/i.exec(USER_AGENT); 18243 var appleWebkitVersion = webkitVersionMap ? parseFloat(webkitVersionMap.pop()) : null; 18244 18245 /* 18246 * Device is an iPhone 18247 * 18248 * @type {Boolean} 18249 * @constant 18250 * @private 18251 */ 18252 var IS_IPAD = /iPad/i.test(USER_AGENT); 18253 18254 exports.IS_IPAD = IS_IPAD; 18255 // The Facebook app's UIWebView identifies as both an iPhone and iPad, so 18256 // to identify iPhones, we need to exclude iPads. 18257 // http://artsy.github.io/blog/2012/10/18/the-perils-of-ios-user-agent-sniffing/ 18258 var IS_IPHONE = /iPhone/i.test(USER_AGENT) && !IS_IPAD; 18259 exports.IS_IPHONE = IS_IPHONE; 18260 var IS_IPOD = /iPod/i.test(USER_AGENT); 18261 exports.IS_IPOD = IS_IPOD; 18262 var IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD; 18263 18264 exports.IS_IOS = IS_IOS; 18265 var IOS_VERSION = (function () { 18266 var match = USER_AGENT.match(/OS (\d+)_/i); 18267 if (match && match[1]) { 18268 return match[1]; 18269 } 18270 })(); 18271 18272 exports.IOS_VERSION = IOS_VERSION; 18273 var IS_ANDROID = /Android/i.test(USER_AGENT); 18274 exports.IS_ANDROID = IS_ANDROID; 18275 var ANDROID_VERSION = (function () { 18276 // This matches Android Major.Minor.Patch versions 18277 // ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned 18278 var match = USER_AGENT.match(/Android (\d+)(?:\.(\d+))?(?:\.(\d+))*/i), 18279 major, 18280 minor; 18281 18282 if (!match) { 18283 return null; 18284 } 18285 18286 major = match[1] && parseFloat(match[1]); 18287 minor = match[2] && parseFloat(match[2]); 18288 18289 if (major && minor) { 18290 return parseFloat(match[1] + '.' + match[2]); 18291 } else if (major) { 18292 return major; 18293 } else { 18294 return null; 18295 } 18296 })(); 18297 exports.ANDROID_VERSION = ANDROID_VERSION; 18298 // Old Android is defined as Version older than 2.3, and requiring a webkit version of the android browser 18299 var IS_OLD_ANDROID = IS_ANDROID && /webkit/i.test(USER_AGENT) && ANDROID_VERSION < 2.3; 18300 exports.IS_OLD_ANDROID = IS_OLD_ANDROID; 18301 var IS_NATIVE_ANDROID = IS_ANDROID && ANDROID_VERSION < 5 && appleWebkitVersion < 537; 18302 18303 exports.IS_NATIVE_ANDROID = IS_NATIVE_ANDROID; 18304 var IS_FIREFOX = /Firefox/i.test(USER_AGENT); 18305 exports.IS_FIREFOX = IS_FIREFOX; 18306 var IS_CHROME = /Chrome/i.test(USER_AGENT); 18307 exports.IS_CHROME = IS_CHROME; 18308 var IS_IE8 = /MSIE\s8\.0/.test(USER_AGENT); 18309 18310 exports.IS_IE8 = IS_IE8; 18311 var TOUCH_ENABLED = !!('ontouchstart' in _globalWindow2['default'] || _globalWindow2['default'].DocumentTouch && _globalDocument2['default'] instanceof _globalWindow2['default'].DocumentTouch); 18312 exports.TOUCH_ENABLED = TOUCH_ENABLED; 18313 var BACKGROUND_SIZE_SUPPORTED = ('backgroundSize' in _globalDocument2['default'].createElement('video').style); 18314 exports.BACKGROUND_SIZE_SUPPORTED = BACKGROUND_SIZE_SUPPORTED; 18315 18316 },{"global/document":1,"global/window":2}],132:[function(_dereq_,module,exports){ 18317 /** 18318 * @file buffer.js 18319 */ 18320 'use strict'; 18321 18322 exports.__esModule = true; 18323 exports.bufferedPercent = bufferedPercent; 18324 18325 var _timeRangesJs = _dereq_('./time-ranges.js'); 18326 18327 /** 18328 * Compute how much your video has been buffered 18329 * 18330 * @param {Object} Buffered object 18331 * @param {Number} Total duration 18332 * @return {Number} Percent buffered of the total duration 18333 * @private 18334 * @function bufferedPercent 18335 */ 18336 18337 function bufferedPercent(buffered, duration) { 18338 var bufferedDuration = 0, 18339 start, 18340 end; 18341 18342 if (!duration) { 18343 return 0; 18344 } 18345 18346 if (!buffered || !buffered.length) { 18347 buffered = _timeRangesJs.createTimeRange(0, 0); 18348 } 18349 18350 for (var i = 0; i < buffered.length; i++) { 18351 start = buffered.start(i); 18352 end = buffered.end(i); 18353 18354 // buffered end can be bigger than duration by a very small fraction 18355 if (end > duration) { 18356 end = duration; 18357 } 18358 18359 bufferedDuration += end - start; 18360 } 18361 18362 return bufferedDuration / duration; 18363 } 18364 18365 },{"./time-ranges.js":142}],133:[function(_dereq_,module,exports){ 18366 'use strict'; 18367 18368 exports.__esModule = true; 18369 18370 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 18371 18372 var _logJs = _dereq_('./log.js'); 18373 18374 var _logJs2 = _interopRequireDefault(_logJs); 18375 18376 /** 18377 * Object containing the default behaviors for available handler methods. 18378 * 18379 * @private 18380 * @type {Object} 18381 */ 18382 var defaultBehaviors = { 18383 get: function get(obj, key) { 18384 return obj[key]; 18385 }, 18386 set: function set(obj, key, value) { 18387 obj[key] = value; 18388 return true; 18389 } 18390 }; 18391 18392 /** 18393 * Expose private objects publicly using a Proxy to log deprecation warnings. 18394 * 18395 * Browsers that do not support Proxy objects will simply return the `target` 18396 * object, so it can be directly exposed. 18397 * 18398 * @param {Object} target The target object. 18399 * @param {Object} messages Messages to display from a Proxy. Only operations 18400 * with an associated message will be proxied. 18401 * @param {String} [messages.get] 18402 * @param {String} [messages.set] 18403 * @return {Object} A Proxy if supported or the `target` argument. 18404 */ 18405 18406 exports['default'] = function (target) { 18407 var messages = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 18408 18409 if (typeof Proxy === 'function') { 18410 var _ret = (function () { 18411 var handler = {}; 18412 18413 // Build a handler object based on those keys that have both messages 18414 // and default behaviors. 18415 Object.keys(messages).forEach(function (key) { 18416 if (defaultBehaviors.hasOwnProperty(key)) { 18417 handler[key] = function () { 18418 _logJs2['default'].warn(messages[key]); 18419 return defaultBehaviors[key].apply(this, arguments); 18420 }; 18421 } 18422 }); 18423 18424 return { 18425 v: new Proxy(target, handler) 18426 }; 18427 })(); 18428 18429 if (typeof _ret === 'object') return _ret.v; 18430 } 18431 return target; 18432 }; 18433 18434 module.exports = exports['default']; 18435 18436 },{"./log.js":139}],134:[function(_dereq_,module,exports){ 18437 /** 18438 * @file dom.js 18439 */ 18440 'use strict'; 18441 18442 exports.__esModule = true; 18443 exports.getEl = getEl; 18444 exports.createEl = createEl; 18445 exports.textContent = textContent; 18446 exports.insertElFirst = insertElFirst; 18447 exports.getElData = getElData; 18448 exports.hasElData = hasElData; 18449 exports.removeElData = removeElData; 18450 exports.hasElClass = hasElClass; 18451 exports.addElClass = addElClass; 18452 exports.removeElClass = removeElClass; 18453 exports.toggleElClass = toggleElClass; 18454 exports.setElAttributes = setElAttributes; 18455 exports.getElAttributes = getElAttributes; 18456 exports.blockTextSelection = blockTextSelection; 18457 exports.unblockTextSelection = unblockTextSelection; 18458 exports.findElPosition = findElPosition; 18459 exports.getPointerPosition = getPointerPosition; 18460 exports.isEl = isEl; 18461 exports.isTextNode = isTextNode; 18462 exports.emptyEl = emptyEl; 18463 exports.normalizeContent = normalizeContent; 18464 exports.appendContent = appendContent; 18465 exports.insertContent = insertContent; 18466 18467 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 ', '.']); 18468 18469 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; } } 18470 18471 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 18472 18473 function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; } 18474 18475 var _globalDocument = _dereq_('global/document'); 18476 18477 var _globalDocument2 = _interopRequireDefault(_globalDocument); 18478 18479 var _globalWindow = _dereq_('global/window'); 18480 18481 var _globalWindow2 = _interopRequireDefault(_globalWindow); 18482 18483 var _guidJs = _dereq_('./guid.js'); 18484 18485 var Guid = _interopRequireWildcard(_guidJs); 18486 18487 var _logJs = _dereq_('./log.js'); 18488 18489 var _logJs2 = _interopRequireDefault(_logJs); 18490 18491 var _tsml = _dereq_('tsml'); 18492 18493 var _tsml2 = _interopRequireDefault(_tsml); 18494 18495 /** 18496 * Detect if a value is a string with any non-whitespace characters. 18497 * 18498 * @param {String} str 18499 * @return {Boolean} 18500 */ 18501 function isNonBlankString(str) { 18502 return typeof str === 'string' && /\S/.test(str); 18503 } 18504 18505 /** 18506 * Throws an error if the passed string has whitespace. This is used by 18507 * class methods to be relatively consistent with the classList API. 18508 * 18509 * @param {String} str 18510 * @return {Boolean} 18511 */ 18512 function throwIfWhitespace(str) { 18513 if (/\s/.test(str)) { 18514 throw new Error('class has illegal whitespace characters'); 18515 } 18516 } 18517 18518 /** 18519 * Produce a regular expression for matching a class name. 18520 * 18521 * @param {String} className 18522 * @return {RegExp} 18523 */ 18524 function classRegExp(className) { 18525 return new RegExp('(^|\\s)' + className + '($|\\s)'); 18526 } 18527 18528 /** 18529 * Creates functions to query the DOM using a given method. 18530 * 18531 * @function createQuerier 18532 * @private 18533 * @param {String} method 18534 * @return {Function} 18535 */ 18536 function createQuerier(method) { 18537 return function (selector, context) { 18538 if (!isNonBlankString(selector)) { 18539 return _globalDocument2['default'][method](null); 18540 } 18541 if (isNonBlankString(context)) { 18542 context = _globalDocument2['default'].querySelector(context); 18543 } 18544 return (isEl(context) ? context : _globalDocument2['default'])[method](selector); 18545 }; 18546 } 18547 18548 /** 18549 * Shorthand for document.getElementById() 18550 * Also allows for CSS (jQuery) ID syntax. But nothing other than IDs. 18551 * 18552 * @param {String} id Element ID 18553 * @return {Element} Element with supplied ID 18554 * @function getEl 18555 */ 18556 18557 function getEl(id) { 18558 if (id.indexOf('#') === 0) { 18559 id = id.slice(1); 18560 } 18561 18562 return _globalDocument2['default'].getElementById(id); 18563 } 18564 18565 /** 18566 * Creates an element and applies properties. 18567 * 18568 * @param {String} [tagName='div'] Name of tag to be created. 18569 * @param {Object} [properties={}] Element properties to be applied. 18570 * @param {Object} [attributes={}] Element attributes to be applied. 18571 * @return {Element} 18572 * @function createEl 18573 */ 18574 18575 function createEl() { 18576 var tagName = arguments.length <= 0 || arguments[0] === undefined ? 'div' : arguments[0]; 18577 var properties = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; 18578 var attributes = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; 18579 18580 var el = _globalDocument2['default'].createElement(tagName); 18581 18582 Object.getOwnPropertyNames(properties).forEach(function (propName) { 18583 var val = properties[propName]; 18584 18585 // See #2176 18586 // We originally were accepting both properties and attributes in the 18587 // same object, but that doesn't work so well. 18588 if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') { 18589 _logJs2['default'].warn(_tsml2['default'](_templateObject, propName, val)); 18590 el.setAttribute(propName, val); 18591 } else { 18592 el[propName] = val; 18593 } 18594 }); 18595 18596 Object.getOwnPropertyNames(attributes).forEach(function (attrName) { 18597 var val = attributes[attrName]; 18598 el.setAttribute(attrName, attributes[attrName]); 18599 }); 18600 18601 return el; 18602 } 18603 18604 /** 18605 * Injects text into an element, replacing any existing contents entirely. 18606 * 18607 * @param {Element} el 18608 * @param {String} text 18609 * @return {Element} 18610 * @function textContent 18611 */ 18612 18613 function textContent(el, text) { 18614 if (typeof el.textContent === 'undefined') { 18615 el.innerText = text; 18616 } else { 18617 el.textContent = text; 18618 } 18619 } 18620 18621 /** 18622 * Insert an element as the first child node of another 18623 * 18624 * @param {Element} child Element to insert 18625 * @param {Element} parent Element to insert child into 18626 * @private 18627 * @function insertElFirst 18628 */ 18629 18630 function insertElFirst(child, parent) { 18631 if (parent.firstChild) { 18632 parent.insertBefore(child, parent.firstChild); 18633 } else { 18634 parent.appendChild(child); 18635 } 18636 } 18637 18638 /** 18639 * Element Data Store. Allows for binding data to an element without putting it directly on the element. 18640 * Ex. Event listeners are stored here. 18641 * (also from jsninja.com, slightly modified and updated for closure compiler) 18642 * 18643 * @type {Object} 18644 * @private 18645 */ 18646 var elData = {}; 18647 18648 /* 18649 * Unique attribute name to store an element's guid in 18650 * 18651 * @type {String} 18652 * @constant 18653 * @private 18654 */ 18655 var elIdAttr = 'vdata' + new Date().getTime(); 18656 18657 /** 18658 * Returns the cache object where data for an element is stored 18659 * 18660 * @param {Element} el Element to store data for. 18661 * @return {Object} 18662 * @function getElData 18663 */ 18664 18665 function getElData(el) { 18666 var id = el[elIdAttr]; 18667 18668 if (!id) { 18669 id = el[elIdAttr] = Guid.newGUID(); 18670 } 18671 18672 if (!elData[id]) { 18673 elData[id] = {}; 18674 } 18675 18676 return elData[id]; 18677 } 18678 18679 /** 18680 * Returns whether or not an element has cached data 18681 * 18682 * @param {Element} el A dom element 18683 * @return {Boolean} 18684 * @private 18685 * @function hasElData 18686 */ 18687 18688 function hasElData(el) { 18689 var id = el[elIdAttr]; 18690 18691 if (!id) { 18692 return false; 18693 } 18694 18695 return !!Object.getOwnPropertyNames(elData[id]).length; 18696 } 18697 18698 /** 18699 * Delete data for the element from the cache and the guid attr from getElementById 18700 * 18701 * @param {Element} el Remove data for an element 18702 * @private 18703 * @function removeElData 18704 */ 18705 18706 function removeElData(el) { 18707 var id = el[elIdAttr]; 18708 18709 if (!id) { 18710 return; 18711 } 18712 18713 // Remove all stored data 18714 delete elData[id]; 18715 18716 // Remove the elIdAttr property from the DOM node 18717 try { 18718 delete el[elIdAttr]; 18719 } catch (e) { 18720 if (el.removeAttribute) { 18721 el.removeAttribute(elIdAttr); 18722 } else { 18723 // IE doesn't appear to support removeAttribute on the document element 18724 el[elIdAttr] = null; 18725 } 18726 } 18727 } 18728 18729 /** 18730 * Check if an element has a CSS class 18731 * 18732 * @function hasElClass 18733 * @param {Element} element Element to check 18734 * @param {String} classToCheck Classname to check 18735 */ 18736 18737 function hasElClass(element, classToCheck) { 18738 if (element.classList) { 18739 return element.classList.contains(classToCheck); 18740 } else { 18741 throwIfWhitespace(classToCheck); 18742 return classRegExp(classToCheck).test(element.className); 18743 } 18744 } 18745 18746 /** 18747 * Add a CSS class name to an element 18748 * 18749 * @function addElClass 18750 * @param {Element} element Element to add class name to 18751 * @param {String} classToAdd Classname to add 18752 */ 18753 18754 function addElClass(element, classToAdd) { 18755 if (element.classList) { 18756 element.classList.add(classToAdd); 18757 18758 // Don't need to `throwIfWhitespace` here because `hasElClass` will do it 18759 // in the case of classList not being supported. 18760 } else if (!hasElClass(element, classToAdd)) { 18761 element.className = (element.className + ' ' + classToAdd).trim(); 18762 } 18763 18764 return element; 18765 } 18766 18767 /** 18768 * Remove a CSS class name from an element 18769 * 18770 * @function removeElClass 18771 * @param {Element} element Element to remove from class name 18772 * @param {String} classToRemove Classname to remove 18773 */ 18774 18775 function removeElClass(element, classToRemove) { 18776 if (element.classList) { 18777 element.classList.remove(classToRemove); 18778 } else { 18779 throwIfWhitespace(classToRemove); 18780 element.className = element.className.split(/\s+/).filter(function (c) { 18781 return c !== classToRemove; 18782 }).join(' '); 18783 } 18784 18785 return element; 18786 } 18787 18788 /** 18789 * Adds or removes a CSS class name on an element depending on an optional 18790 * condition or the presence/absence of the class name. 18791 * 18792 * @function toggleElClass 18793 * @param {Element} element 18794 * @param {String} classToToggle 18795 * @param {Boolean|Function} [predicate] 18796 * Can be a function that returns a Boolean. If `true`, the class 18797 * will be added; if `false`, the class will be removed. If not 18798 * given, the class will be added if not present and vice versa. 18799 */ 18800 18801 function toggleElClass(element, classToToggle, predicate) { 18802 18803 // This CANNOT use `classList` internally because IE does not support the 18804 // second parameter to the `classList.toggle()` method! Which is fine because 18805 // `classList` will be used by the add/remove functions. 18806 var has = hasElClass(element, classToToggle); 18807 18808 if (typeof predicate === 'function') { 18809 predicate = predicate(element, classToToggle); 18810 } 18811 18812 if (typeof predicate !== 'boolean') { 18813 predicate = !has; 18814 } 18815 18816 // If the necessary class operation matches the current state of the 18817 // element, no action is required. 18818 if (predicate === has) { 18819 return; 18820 } 18821 18822 if (predicate) { 18823 addElClass(element, classToToggle); 18824 } else { 18825 removeElClass(element, classToToggle); 18826 } 18827 18828 return element; 18829 } 18830 18831 /** 18832 * Apply attributes to an HTML element. 18833 * 18834 * @param {Element} el Target element. 18835 * @param {Object=} attributes Element attributes to be applied. 18836 * @private 18837 * @function setElAttributes 18838 */ 18839 18840 function setElAttributes(el, attributes) { 18841 Object.getOwnPropertyNames(attributes).forEach(function (attrName) { 18842 var attrValue = attributes[attrName]; 18843 18844 if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) { 18845 el.removeAttribute(attrName); 18846 } else { 18847 el.setAttribute(attrName, attrValue === true ? '' : attrValue); 18848 } 18849 }); 18850 } 18851 18852 /** 18853 * Get an element's attribute values, as defined on the HTML tag 18854 * Attributes are not the same as properties. They're defined on the tag 18855 * or with setAttribute (which shouldn't be used with HTML) 18856 * This will return true or false for boolean attributes. 18857 * 18858 * @param {Element} tag Element from which to get tag attributes 18859 * @return {Object} 18860 * @private 18861 * @function getElAttributes 18862 */ 18863 18864 function getElAttributes(tag) { 18865 var obj, knownBooleans, attrs, attrName, attrVal; 18866 18867 obj = {}; 18868 18869 // known boolean attributes 18870 // we can check for matching boolean properties, but older browsers 18871 // won't know about HTML5 boolean attributes that we still read from 18872 knownBooleans = ',' + 'autoplay,controls,loop,muted,default' + ','; 18873 18874 if (tag && tag.attributes && tag.attributes.length > 0) { 18875 attrs = tag.attributes; 18876 18877 for (var i = attrs.length - 1; i >= 0; i--) { 18878 attrName = attrs[i].name; 18879 attrVal = attrs[i].value; 18880 18881 // check for known booleans 18882 // the matching element property will return a value for typeof 18883 if (typeof tag[attrName] === 'boolean' || knownBooleans.indexOf(',' + attrName + ',') !== -1) { 18884 // the value of an included boolean attribute is typically an empty 18885 // string ('') which would equal false if we just check for a false value. 18886 // we also don't want support bad code like autoplay='false' 18887 attrVal = attrVal !== null ? true : false; 18888 } 18889 18890 obj[attrName] = attrVal; 18891 } 18892 } 18893 18894 return obj; 18895 } 18896 18897 /** 18898 * Attempt to block the ability to select text while dragging controls 18899 * 18900 * @return {Boolean} 18901 * @function blockTextSelection 18902 */ 18903 18904 function blockTextSelection() { 18905 _globalDocument2['default'].body.focus(); 18906 _globalDocument2['default'].onselectstart = function () { 18907 return false; 18908 }; 18909 } 18910 18911 /** 18912 * Turn off text selection blocking 18913 * 18914 * @return {Boolean} 18915 * @function unblockTextSelection 18916 */ 18917 18918 function unblockTextSelection() { 18919 _globalDocument2['default'].onselectstart = function () { 18920 return true; 18921 }; 18922 } 18923 18924 /** 18925 * Offset Left 18926 * getBoundingClientRect technique from 18927 * John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/ 18928 * 18929 * @function findElPosition 18930 * @param {Element} el Element from which to get offset 18931 * @return {Object} 18932 */ 18933 18934 function findElPosition(el) { 18935 var box = undefined; 18936 18937 if (el.getBoundingClientRect && el.parentNode) { 18938 box = el.getBoundingClientRect(); 18939 } 18940 18941 if (!box) { 18942 return { 18943 left: 0, 18944 top: 0 18945 }; 18946 } 18947 18948 var docEl = _globalDocument2['default'].documentElement; 18949 var body = _globalDocument2['default'].body; 18950 18951 var clientLeft = docEl.clientLeft || body.clientLeft || 0; 18952 var scrollLeft = _globalWindow2['default'].pageXOffset || body.scrollLeft; 18953 var left = box.left + scrollLeft - clientLeft; 18954 18955 var clientTop = docEl.clientTop || body.clientTop || 0; 18956 var scrollTop = _globalWindow2['default'].pageYOffset || body.scrollTop; 18957 var top = box.top + scrollTop - clientTop; 18958 18959 // Android sometimes returns slightly off decimal values, so need to round 18960 return { 18961 left: Math.round(left), 18962 top: Math.round(top) 18963 }; 18964 } 18965 18966 /** 18967 * Get pointer position in element 18968 * Returns an object with x and y coordinates. 18969 * The base on the coordinates are the bottom left of the element. 18970 * 18971 * @function getPointerPosition 18972 * @param {Element} el Element on which to get the pointer position on 18973 * @param {Event} event Event object 18974 * @return {Object} This object will have x and y coordinates corresponding to the mouse position 18975 */ 18976 18977 function getPointerPosition(el, event) { 18978 var position = {}; 18979 var box = findElPosition(el); 18980 var boxW = el.offsetWidth; 18981 var boxH = el.offsetHeight; 18982 18983 var boxY = box.top; 18984 var boxX = box.left; 18985 var pageY = event.pageY; 18986 var pageX = event.pageX; 18987 18988 if (event.changedTouches) { 18989 pageX = event.changedTouches[0].pageX; 18990 pageY = event.changedTouches[0].pageY; 18991 } 18992 18993 position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH)); 18994 position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW)); 18995 18996 return position; 18997 } 18998 18999 /** 19000 * Determines, via duck typing, whether or not a value is a DOM element. 19001 * 19002 * @function isEl 19003 * @param {Mixed} value 19004 * @return {Boolean} 19005 */ 19006 19007 function isEl(value) { 19008 return !!value && typeof value === 'object' && value.nodeType === 1; 19009 } 19010 19011 /** 19012 * Determines, via duck typing, whether or not a value is a text node. 19013 * 19014 * @param {Mixed} value 19015 * @return {Boolean} 19016 */ 19017 19018 function isTextNode(value) { 19019 return !!value && typeof value === 'object' && value.nodeType === 3; 19020 } 19021 19022 /** 19023 * Empties the contents of an element. 19024 * 19025 * @function emptyEl 19026 * @param {Element} el 19027 * @return {Element} 19028 */ 19029 19030 function emptyEl(el) { 19031 while (el.firstChild) { 19032 el.removeChild(el.firstChild); 19033 } 19034 return el; 19035 } 19036 19037 /** 19038 * Normalizes content for eventual insertion into the DOM. 19039 * 19040 * This allows a wide range of content definition methods, but protects 19041 * from falling into the trap of simply writing to `innerHTML`, which is 19042 * an XSS concern. 19043 * 19044 * The content for an element can be passed in multiple types and 19045 * combinations, whose behavior is as follows: 19046 * 19047 * - String 19048 * Normalized into a text node. 19049 * 19050 * - Element, TextNode 19051 * Passed through. 19052 * 19053 * - Array 19054 * A one-dimensional array of strings, elements, nodes, or functions (which 19055 * return single strings, elements, or nodes). 19056 * 19057 * - Function 19058 * If the sole argument, is expected to produce a string, element, 19059 * node, or array. 19060 * 19061 * @function normalizeContent 19062 * @param {String|Element|TextNode|Array|Function} content 19063 * @return {Array} 19064 */ 19065 19066 function normalizeContent(content) { 19067 19068 // First, invoke content if it is a function. If it produces an array, 19069 // that needs to happen before normalization. 19070 if (typeof content === 'function') { 19071 content = content(); 19072 } 19073 19074 // Next up, normalize to an array, so one or many items can be normalized, 19075 // filtered, and returned. 19076 return (Array.isArray(content) ? content : [content]).map(function (value) { 19077 19078 // First, invoke value if it is a function to produce a new value, 19079 // which will be subsequently normalized to a Node of some kind. 19080 if (typeof value === 'function') { 19081 value = value(); 19082 } 19083 19084 if (isEl(value) || isTextNode(value)) { 19085 return value; 19086 } 19087 19088 if (typeof value === 'string' && /\S/.test(value)) { 19089 return _globalDocument2['default'].createTextNode(value); 19090 } 19091 }).filter(function (value) { 19092 return value; 19093 }); 19094 } 19095 19096 /** 19097 * Normalizes and appends content to an element. 19098 * 19099 * @function appendContent 19100 * @param {Element} el 19101 * @param {String|Element|TextNode|Array|Function} content 19102 * See: `normalizeContent` 19103 * @return {Element} 19104 */ 19105 19106 function appendContent(el, content) { 19107 normalizeContent(content).forEach(function (node) { 19108 return el.appendChild(node); 19109 }); 19110 return el; 19111 } 19112 19113 /** 19114 * Normalizes and inserts content into an element; this is identical to 19115 * `appendContent()`, except it empties the element first. 19116 * 19117 * @function insertContent 19118 * @param {Element} el 19119 * @param {String|Element|TextNode|Array|Function} content 19120 * See: `normalizeContent` 19121 * @return {Element} 19122 */ 19123 19124 function insertContent(el, content) { 19125 return appendContent(emptyEl(el), content); 19126 } 19127 19128 /** 19129 * Finds a single DOM element matching `selector` within the optional 19130 * `context` of another DOM element (defaulting to `document`). 19131 * 19132 * @function $ 19133 * @param {String} selector 19134 * A valid CSS selector, which will be passed to `querySelector`. 19135 * 19136 * @param {Element|String} [context=document] 19137 * A DOM element within which to query. Can also be a selector 19138 * string in which case the first matching element will be used 19139 * as context. If missing (or no element matches selector), falls 19140 * back to `document`. 19141 * 19142 * @return {Element|null} 19143 */ 19144 var $ = createQuerier('querySelector'); 19145 19146 exports.$ = $; 19147 /** 19148 * Finds a all DOM elements matching `selector` within the optional 19149 * `context` of another DOM element (defaulting to `document`). 19150 * 19151 * @function $$ 19152 * @param {String} selector 19153 * A valid CSS selector, which will be passed to `querySelectorAll`. 19154 * 19155 * @param {Element|String} [context=document] 19156 * A DOM element within which to query. Can also be a selector 19157 * string in which case the first matching element will be used 19158 * as context. If missing (or no element matches selector), falls 19159 * back to `document`. 19160 * 19161 * @return {NodeList} 19162 */ 19163 var $$ = createQuerier('querySelectorAll'); 19164 exports.$$ = $$; 19165 19166 },{"./guid.js":138,"./log.js":139,"global/document":1,"global/window":2,"tsml":55}],135:[function(_dereq_,module,exports){ 19167 /** 19168 * @file events.js 19169 * 19170 * Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/) 19171 * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible) 19172 * This should work very similarly to jQuery's events, however it's based off the book version which isn't as 19173 * robust as jquery's, so there's probably some differences. 19174 */ 19175 19176 'use strict'; 19177 19178 exports.__esModule = true; 19179 exports.on = on; 19180 exports.off = off; 19181 exports.trigger = trigger; 19182 exports.one = one; 19183 exports.fixEvent = fixEvent; 19184 19185 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 19186 19187 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; } } 19188 19189 var _domJs = _dereq_('./dom.js'); 19190 19191 var Dom = _interopRequireWildcard(_domJs); 19192 19193 var _guidJs = _dereq_('./guid.js'); 19194 19195 var Guid = _interopRequireWildcard(_guidJs); 19196 19197 var _globalWindow = _dereq_('global/window'); 19198 19199 var _globalWindow2 = _interopRequireDefault(_globalWindow); 19200 19201 var _globalDocument = _dereq_('global/document'); 19202 19203 var _globalDocument2 = _interopRequireDefault(_globalDocument); 19204 19205 /** 19206 * Add an event listener to element 19207 * It stores the handler function in a separate cache object 19208 * and adds a generic handler to the element's event, 19209 * along with a unique id (guid) to the element. 19210 * 19211 * @param {Element|Object} elem Element or object to bind listeners to 19212 * @param {String|Array} type Type of event to bind to. 19213 * @param {Function} fn Event listener. 19214 * @method on 19215 */ 19216 19217 function on(elem, type, fn) { 19218 if (Array.isArray(type)) { 19219 return _handleMultipleEvents(on, elem, type, fn); 19220 } 19221 19222 var data = Dom.getElData(elem); 19223 19224 // We need a place to store all our handler data 19225 if (!data.handlers) data.handlers = {}; 19226 19227 if (!data.handlers[type]) data.handlers[type] = []; 19228 19229 if (!fn.guid) fn.guid = Guid.newGUID(); 19230 19231 data.handlers[type].push(fn); 19232 19233 if (!data.dispatcher) { 19234 data.disabled = false; 19235 19236 data.dispatcher = function (event, hash) { 19237 19238 if (data.disabled) return; 19239 event = fixEvent(event); 19240 19241 var handlers = data.handlers[event.type]; 19242 19243 if (handlers) { 19244 // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off. 19245 var handlersCopy = handlers.slice(0); 19246 19247 for (var m = 0, n = handlersCopy.length; m < n; m++) { 19248 if (event.isImmediatePropagationStopped()) { 19249 break; 19250 } else { 19251 handlersCopy[m].call(elem, event, hash); 19252 } 19253 } 19254 } 19255 }; 19256 } 19257 19258 if (data.handlers[type].length === 1) { 19259 if (elem.addEventListener) { 19260 elem.addEventListener(type, data.dispatcher, false); 19261 } else if (elem.attachEvent) { 19262 elem.attachEvent('on' + type, data.dispatcher); 19263 } 19264 } 19265 } 19266 19267 /** 19268 * Removes event listeners from an element 19269 * 19270 * @param {Element|Object} elem Object to remove listeners from 19271 * @param {String|Array=} type Type of listener to remove. Don't include to remove all events from element. 19272 * @param {Function} fn Specific listener to remove. Don't include to remove listeners for an event type. 19273 * @method off 19274 */ 19275 19276 function off(elem, type, fn) { 19277 // Don't want to add a cache object through getElData if not needed 19278 if (!Dom.hasElData(elem)) return; 19279 19280 var data = Dom.getElData(elem); 19281 19282 // If no events exist, nothing to unbind 19283 if (!data.handlers) { 19284 return; 19285 } 19286 19287 if (Array.isArray(type)) { 19288 return _handleMultipleEvents(off, elem, type, fn); 19289 } 19290 19291 // Utility function 19292 var removeType = function removeType(t) { 19293 data.handlers[t] = []; 19294 _cleanUpEvents(elem, t); 19295 }; 19296 19297 // Are we removing all bound events? 19298 if (!type) { 19299 for (var t in data.handlers) { 19300 removeType(t); 19301 }return; 19302 } 19303 19304 var handlers = data.handlers[type]; 19305 19306 // If no handlers exist, nothing to unbind 19307 if (!handlers) return; 19308 19309 // If no listener was provided, remove all listeners for type 19310 if (!fn) { 19311 removeType(type); 19312 return; 19313 } 19314 19315 // We're only removing a single handler 19316 if (fn.guid) { 19317 for (var n = 0; n < handlers.length; n++) { 19318 if (handlers[n].guid === fn.guid) { 19319 handlers.splice(n--, 1); 19320 } 19321 } 19322 } 19323 19324 _cleanUpEvents(elem, type); 19325 } 19326 19327 /** 19328 * Trigger an event for an element 19329 * 19330 * @param {Element|Object} elem Element to trigger an event on 19331 * @param {Event|Object|String} event A string (the type) or an event object with a type attribute 19332 * @param {Object} [hash] data hash to pass along with the event 19333 * @return {Boolean=} Returned only if default was prevented 19334 * @method trigger 19335 */ 19336 19337 function trigger(elem, event, hash) { 19338 // Fetches element data and a reference to the parent (for bubbling). 19339 // Don't want to add a data object to cache for every parent, 19340 // so checking hasElData first. 19341 var elemData = Dom.hasElData(elem) ? Dom.getElData(elem) : {}; 19342 var parent = elem.parentNode || elem.ownerDocument; 19343 // type = event.type || event, 19344 // handler; 19345 19346 // If an event name was passed as a string, creates an event out of it 19347 if (typeof event === 'string') { 19348 event = { type: event, target: elem }; 19349 } 19350 // Normalizes the event properties. 19351 event = fixEvent(event); 19352 19353 // If the passed element has a dispatcher, executes the established handlers. 19354 if (elemData.dispatcher) { 19355 elemData.dispatcher.call(elem, event, hash); 19356 } 19357 19358 // Unless explicitly stopped or the event does not bubble (e.g. media events) 19359 // recursively calls this function to bubble the event up the DOM. 19360 if (parent && !event.isPropagationStopped() && event.bubbles === true) { 19361 trigger.call(null, parent, event, hash); 19362 19363 // If at the top of the DOM, triggers the default action unless disabled. 19364 } else if (!parent && !event.defaultPrevented) { 19365 var targetData = Dom.getElData(event.target); 19366 19367 // Checks if the target has a default action for this event. 19368 if (event.target[event.type]) { 19369 // Temporarily disables event dispatching on the target as we have already executed the handler. 19370 targetData.disabled = true; 19371 // Executes the default action. 19372 if (typeof event.target[event.type] === 'function') { 19373 event.target[event.type](); 19374 } 19375 // Re-enables event dispatching. 19376 targetData.disabled = false; 19377 } 19378 } 19379 19380 // Inform the triggerer if the default was prevented by returning false 19381 return !event.defaultPrevented; 19382 } 19383 19384 /** 19385 * Trigger a listener only once for an event 19386 * 19387 * @param {Element|Object} elem Element or object to 19388 * @param {String|Array} type Name/type of event 19389 * @param {Function} fn Event handler function 19390 * @method one 19391 */ 19392 19393 function one(elem, type, fn) { 19394 if (Array.isArray(type)) { 19395 return _handleMultipleEvents(one, elem, type, fn); 19396 } 19397 var func = function func() { 19398 off(elem, type, func); 19399 fn.apply(this, arguments); 19400 }; 19401 // copy the guid to the new function so it can removed using the original function's ID 19402 func.guid = fn.guid = fn.guid || Guid.newGUID(); 19403 on(elem, type, func); 19404 } 19405 19406 /** 19407 * Fix a native event to have standard property values 19408 * 19409 * @param {Object} event Event object to fix 19410 * @return {Object} 19411 * @private 19412 * @method fixEvent 19413 */ 19414 19415 function fixEvent(event) { 19416 19417 function returnTrue() { 19418 return true; 19419 } 19420 function returnFalse() { 19421 return false; 19422 } 19423 19424 // Test if fixing up is needed 19425 // Used to check if !event.stopPropagation instead of isPropagationStopped 19426 // But native events return true for stopPropagation, but don't have 19427 // other expected methods like isPropagationStopped. Seems to be a problem 19428 // with the Javascript Ninja code. So we're just overriding all events now. 19429 if (!event || !event.isPropagationStopped) { 19430 var old = event || _globalWindow2['default'].event; 19431 19432 event = {}; 19433 // Clone the old object so that we can modify the values event = {}; 19434 // IE8 Doesn't like when you mess with native event properties 19435 // Firefox returns false for event.hasOwnProperty('type') and other props 19436 // which makes copying more difficult. 19437 // TODO: Probably best to create a whitelist of event props 19438 for (var key in old) { 19439 // Safari 6.0.3 warns you if you try to copy deprecated layerX/Y 19440 // Chrome warns you if you try to copy deprecated keyboardEvent.keyLocation 19441 // and webkitMovementX/Y 19442 if (key !== 'layerX' && key !== 'layerY' && key !== 'keyLocation' && key !== 'webkitMovementX' && key !== 'webkitMovementY') { 19443 // Chrome 32+ warns if you try to copy deprecated returnValue, but 19444 // we still want to if preventDefault isn't supported (IE8). 19445 if (!(key === 'returnValue' && old.preventDefault)) { 19446 event[key] = old[key]; 19447 } 19448 } 19449 } 19450 19451 // The event occurred on this element 19452 if (!event.target) { 19453 event.target = event.srcElement || _globalDocument2['default']; 19454 } 19455 19456 // Handle which other element the event is related to 19457 if (!event.relatedTarget) { 19458 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; 19459 } 19460 19461 // Stop the default browser action 19462 event.preventDefault = function () { 19463 if (old.preventDefault) { 19464 old.preventDefault(); 19465 } 19466 event.returnValue = false; 19467 old.returnValue = false; 19468 event.defaultPrevented = true; 19469 }; 19470 19471 event.defaultPrevented = false; 19472 19473 // Stop the event from bubbling 19474 event.stopPropagation = function () { 19475 if (old.stopPropagation) { 19476 old.stopPropagation(); 19477 } 19478 event.cancelBubble = true; 19479 old.cancelBubble = true; 19480 event.isPropagationStopped = returnTrue; 19481 }; 19482 19483 event.isPropagationStopped = returnFalse; 19484 19485 // Stop the event from bubbling and executing other handlers 19486 event.stopImmediatePropagation = function () { 19487 if (old.stopImmediatePropagation) { 19488 old.stopImmediatePropagation(); 19489 } 19490 event.isImmediatePropagationStopped = returnTrue; 19491 event.stopPropagation(); 19492 }; 19493 19494 event.isImmediatePropagationStopped = returnFalse; 19495 19496 // Handle mouse position 19497 if (event.clientX != null) { 19498 var doc = _globalDocument2['default'].documentElement, 19499 body = _globalDocument2['default'].body; 19500 19501 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); 19502 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); 19503 } 19504 19505 // Handle key presses 19506 event.which = event.charCode || event.keyCode; 19507 19508 // Fix button for mouse clicks: 19509 // 0 == left; 1 == middle; 2 == right 19510 if (event.button != null) { 19511 event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0; 19512 } 19513 } 19514 19515 // Returns fixed-up instance 19516 return event; 19517 } 19518 19519 /** 19520 * Clean up the listener cache and dispatchers 19521 * 19522 * @param {Element|Object} elem Element to clean up 19523 * @param {String} type Type of event to clean up 19524 * @private 19525 * @method _cleanUpEvents 19526 */ 19527 function _cleanUpEvents(elem, type) { 19528 var data = Dom.getElData(elem); 19529 19530 // Remove the events of a particular type if there are none left 19531 if (data.handlers[type].length === 0) { 19532 delete data.handlers[type]; 19533 // data.handlers[type] = null; 19534 // Setting to null was causing an error with data.handlers 19535 19536 // Remove the meta-handler from the element 19537 if (elem.removeEventListener) { 19538 elem.removeEventListener(type, data.dispatcher, false); 19539 } else if (elem.detachEvent) { 19540 elem.detachEvent('on' + type, data.dispatcher); 19541 } 19542 } 19543 19544 // Remove the events object if there are no types left 19545 if (Object.getOwnPropertyNames(data.handlers).length <= 0) { 19546 delete data.handlers; 19547 delete data.dispatcher; 19548 delete data.disabled; 19549 } 19550 19551 // Finally remove the element data if there is no data left 19552 if (Object.getOwnPropertyNames(data).length === 0) { 19553 Dom.removeElData(elem); 19554 } 19555 } 19556 19557 /** 19558 * Loops through an array of event types and calls the requested method for each type. 19559 * 19560 * @param {Function} fn The event method we want to use. 19561 * @param {Element|Object} elem Element or object to bind listeners to 19562 * @param {String} type Type of event to bind to. 19563 * @param {Function} callback Event listener. 19564 * @private 19565 * @function _handleMultipleEvents 19566 */ 19567 function _handleMultipleEvents(fn, elem, types, callback) { 19568 types.forEach(function (type) { 19569 //Call the event method for each one of the types 19570 fn(elem, type, callback); 19571 }); 19572 } 19573 19574 },{"./dom.js":134,"./guid.js":138,"global/document":1,"global/window":2}],136:[function(_dereq_,module,exports){ 19575 /** 19576 * @file fn.js 19577 */ 19578 'use strict'; 19579 19580 exports.__esModule = true; 19581 19582 var _guidJs = _dereq_('./guid.js'); 19583 19584 /** 19585 * Bind (a.k.a proxy or Context). A simple method for changing the context of a function 19586 * It also stores a unique id on the function so it can be easily removed from events 19587 * 19588 * @param {*} context The object to bind as scope 19589 * @param {Function} fn The function to be bound to a scope 19590 * @param {Number=} uid An optional unique ID for the function to be set 19591 * @return {Function} 19592 * @private 19593 * @method bind 19594 */ 19595 var bind = function bind(context, fn, uid) { 19596 // Make sure the function has a unique ID 19597 if (!fn.guid) { 19598 fn.guid = _guidJs.newGUID(); 19599 } 19600 19601 // Create the new function that changes the context 19602 var ret = function ret() { 19603 return fn.apply(context, arguments); 19604 }; 19605 19606 // Allow for the ability to individualize this function 19607 // Needed in the case where multiple objects might share the same prototype 19608 // IF both items add an event listener with the same function, then you try to remove just one 19609 // it will remove both because they both have the same guid. 19610 // when using this, you need to use the bind method when you remove the listener as well. 19611 // currently used in text tracks 19612 ret.guid = uid ? uid + '_' + fn.guid : fn.guid; 19613 19614 return ret; 19615 }; 19616 exports.bind = bind; 19617 19618 },{"./guid.js":138}],137:[function(_dereq_,module,exports){ 19619 /** 19620 * @file format-time.js 19621 * 19622 * Format seconds as a time string, H:MM:SS or M:SS 19623 * Supplying a guide (in seconds) will force a number of leading zeros 19624 * to cover the length of the guide 19625 * 19626 * @param {Number} seconds Number of seconds to be turned into a string 19627 * @param {Number} guide Number (in seconds) to model the string after 19628 * @return {String} Time formatted as H:MM:SS or M:SS 19629 * @private 19630 * @function formatTime 19631 */ 19632 'use strict'; 19633 19634 exports.__esModule = true; 19635 function formatTime(seconds) { 19636 var guide = arguments.length <= 1 || arguments[1] === undefined ? seconds : arguments[1]; 19637 return (function () { 19638 seconds = seconds < 0 ? 0 : seconds; 19639 var s = Math.floor(seconds % 60); 19640 var m = Math.floor(seconds / 60 % 60); 19641 var h = Math.floor(seconds / 3600); 19642 var gm = Math.floor(guide / 60 % 60); 19643 var gh = Math.floor(guide / 3600); 19644 19645 // handle invalid times 19646 if (isNaN(seconds) || seconds === Infinity) { 19647 // '-' is false for all relational operators (e.g. <, >=) so this setting 19648 // will add the minimum number of fields specified by the guide 19649 h = m = s = '-'; 19650 } 19651 19652 // Check if we need to show hours 19653 h = h > 0 || gh > 0 ? h + ':' : ''; 19654 19655 // If hours are showing, we may need to add a leading zero. 19656 // Always show at least one digit of minutes. 19657 m = ((h || gm >= 10) && m < 10 ? '0' + m : m) + ':'; 19658 19659 // Check if leading zero is need for seconds 19660 s = s < 10 ? '0' + s : s; 19661 19662 return h + m + s; 19663 })(); 19664 } 19665 19666 exports['default'] = formatTime; 19667 module.exports = exports['default']; 19668 19669 },{}],138:[function(_dereq_,module,exports){ 19670 /** 19671 * @file guid.js 19672 * 19673 * Unique ID for an element or function 19674 * @type {Number} 19675 * @private 19676 */ 19677 "use strict"; 19678 19679 exports.__esModule = true; 19680 exports.newGUID = newGUID; 19681 var _guid = 1; 19682 19683 /** 19684 * Get the next unique ID 19685 * 19686 * @return {String} 19687 * @function newGUID 19688 */ 19689 19690 function newGUID() { 19691 return _guid++; 19692 } 19693 19694 },{}],139:[function(_dereq_,module,exports){ 19695 /** 19696 * @file log.js 19697 */ 19698 'use strict'; 19699 19700 exports.__esModule = true; 19701 19702 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 19703 19704 var _globalWindow = _dereq_('global/window'); 19705 19706 var _globalWindow2 = _interopRequireDefault(_globalWindow); 19707 19708 /** 19709 * Log plain debug messages 19710 */ 19711 var log = function log() { 19712 _logType(null, arguments); 19713 }; 19714 19715 /** 19716 * Keep a history of log messages 19717 * @type {Array} 19718 */ 19719 log.history = []; 19720 19721 /** 19722 * Log error messages 19723 */ 19724 log.error = function () { 19725 _logType('error', arguments); 19726 }; 19727 19728 /** 19729 * Log warning messages 19730 */ 19731 log.warn = function () { 19732 _logType('warn', arguments); 19733 }; 19734 19735 /** 19736 * Log messages to the console and history based on the type of message 19737 * 19738 * @param {String} type The type of message, or `null` for `log` 19739 * @param {Object} args The args to be passed to the log 19740 * @private 19741 * @method _logType 19742 */ 19743 function _logType(type, args) { 19744 // convert args to an array to get array functions 19745 var argsArray = Array.prototype.slice.call(args); 19746 // if there's no console then don't try to output messages 19747 // they will still be stored in log.history 19748 // Was setting these once outside of this function, but containing them 19749 // in the function makes it easier to test cases where console doesn't exist 19750 var noop = function noop() {}; 19751 19752 var console = _globalWindow2['default']['console'] || { 19753 'log': noop, 19754 'warn': noop, 19755 'error': noop 19756 }; 19757 19758 if (type) { 19759 // add the type to the front of the message 19760 argsArray.unshift(type.toUpperCase() + ':'); 19761 } else { 19762 // default to log with no prefix 19763 type = 'log'; 19764 } 19765 19766 // add to history 19767 log.history.push(argsArray); 19768 19769 // add console prefix after adding to history 19770 argsArray.unshift('VIDEOJS:'); 19771 19772 // call appropriate log function 19773 if (console[type].apply) { 19774 console[type].apply(console, argsArray); 19775 } else { 19776 // ie8 doesn't allow error.apply, but it will just join() the array anyway 19777 console[type](argsArray.join(' ')); 19778 } 19779 } 19780 19781 exports['default'] = log; 19782 module.exports = exports['default']; 19783 19784 },{"global/window":2}],140:[function(_dereq_,module,exports){ 19785 /** 19786 * @file merge-options.js 19787 */ 19788 'use strict'; 19789 19790 exports.__esModule = true; 19791 exports['default'] = mergeOptions; 19792 19793 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 19794 19795 var _lodashCompatObjectMerge = _dereq_('lodash-compat/object/merge'); 19796 19797 var _lodashCompatObjectMerge2 = _interopRequireDefault(_lodashCompatObjectMerge); 19798 19799 function isPlain(obj) { 19800 return !!obj && typeof obj === 'object' && obj.toString() === '[object Object]' && obj.constructor === Object; 19801 } 19802 19803 /** 19804 * Merge customizer. video.js simply overwrites non-simple objects 19805 * (like arrays) instead of attempting to overlay them. 19806 * @see https://lodash.com/docs#merge 19807 */ 19808 var customizer = function customizer(destination, source) { 19809 // If we're not working with a plain object, copy the value as is 19810 // If source is an array, for instance, it will replace destination 19811 if (!isPlain(source)) { 19812 return source; 19813 } 19814 19815 // If the new value is a plain object but the first object value is not 19816 // we need to create a new object for the first object to merge with. 19817 // This makes it consistent with how merge() works by default 19818 // and also protects from later changes the to first object affecting 19819 // the second object's values. 19820 if (!isPlain(destination)) { 19821 return mergeOptions(source); 19822 } 19823 }; 19824 19825 /** 19826 * Merge one or more options objects, recursively merging **only** 19827 * plain object properties. Previously `deepMerge`. 19828 * 19829 * @param {...Object} source One or more objects to merge 19830 * @returns {Object} a new object that is the union of all 19831 * provided objects 19832 * @function mergeOptions 19833 */ 19834 19835 function mergeOptions() { 19836 // contruct the call dynamically to handle the variable number of 19837 // objects to merge 19838 var args = Array.prototype.slice.call(arguments); 19839 19840 // unshift an empty object into the front of the call as the target 19841 // of the merge 19842 args.unshift({}); 19843 19844 // customize conflict resolution to match our historical merge behavior 19845 args.push(customizer); 19846 19847 _lodashCompatObjectMerge2['default'].apply(null, args); 19848 19849 // return the mutated result object 19850 return args[0]; 19851 } 19852 19853 module.exports = exports['default']; 19854 19855 },{"lodash-compat/object/merge":40}],141:[function(_dereq_,module,exports){ 19856 'use strict'; 19857 19858 exports.__esModule = true; 19859 19860 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 19861 19862 var _globalDocument = _dereq_('global/document'); 19863 19864 var _globalDocument2 = _interopRequireDefault(_globalDocument); 19865 19866 var createStyleElement = function createStyleElement(className) { 19867 var style = _globalDocument2['default'].createElement('style'); 19868 style.className = className; 19869 19870 return style; 19871 }; 19872 19873 exports.createStyleElement = createStyleElement; 19874 var setTextContent = function setTextContent(el, content) { 19875 if (el.styleSheet) { 19876 el.styleSheet.cssText = content; 19877 } else { 19878 el.textContent = content; 19879 } 19880 }; 19881 exports.setTextContent = setTextContent; 19882 19883 },{"global/document":1}],142:[function(_dereq_,module,exports){ 19884 'use strict'; 19885 19886 exports.__esModule = true; 19887 exports.createTimeRanges = createTimeRanges; 19888 19889 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 19890 19891 var _logJs = _dereq_('./log.js'); 19892 19893 var _logJs2 = _interopRequireDefault(_logJs); 19894 19895 /** 19896 * @file time-ranges.js 19897 * 19898 * Should create a fake TimeRange object 19899 * Mimics an HTML5 time range instance, which has functions that 19900 * return the start and end times for a range 19901 * TimeRanges are returned by the buffered() method 19902 * 19903 * @param {(Number|Array)} Start of a single range or an array of ranges 19904 * @param {Number} End of a single range 19905 * @private 19906 * @method createTimeRanges 19907 */ 19908 19909 function createTimeRanges(start, end) { 19910 if (Array.isArray(start)) { 19911 return createTimeRangesObj(start); 19912 } else if (start === undefined || end === undefined) { 19913 return createTimeRangesObj(); 19914 } 19915 return createTimeRangesObj([[start, end]]); 19916 } 19917 19918 exports.createTimeRange = createTimeRanges; 19919 19920 function createTimeRangesObj(ranges) { 19921 if (ranges === undefined || ranges.length === 0) { 19922 return { 19923 length: 0, 19924 start: function start() { 19925 throw new Error('This TimeRanges object is empty'); 19926 }, 19927 end: function end() { 19928 throw new Error('This TimeRanges object is empty'); 19929 } 19930 }; 19931 } 19932 return { 19933 length: ranges.length, 19934 start: getRange.bind(null, 'start', 0, ranges), 19935 end: getRange.bind(null, 'end', 1, ranges) 19936 }; 19937 } 19938 19939 function getRange(fnName, valueIndex, ranges, rangeIndex) { 19940 if (rangeIndex === undefined) { 19941 _logJs2['default'].warn('DEPRECATED: Function \'' + fnName + '\' on \'TimeRanges\' called without an index argument.'); 19942 rangeIndex = 0; 19943 } 19944 rangeCheck(fnName, rangeIndex, ranges.length - 1); 19945 return ranges[rangeIndex][valueIndex]; 19946 } 19947 19948 function rangeCheck(fnName, index, maxIndex) { 19949 if (index < 0 || index > maxIndex) { 19950 throw new Error('Failed to execute \'' + fnName + '\' on \'TimeRanges\': The index provided (' + index + ') is greater than or equal to the maximum bound (' + maxIndex + ').'); 19951 } 19952 } 19953 19954 },{"./log.js":139}],143:[function(_dereq_,module,exports){ 19955 /** 19956 * @file to-title-case.js 19957 * 19958 * Uppercase the first letter of a string 19959 * 19960 * @param {String} string String to be uppercased 19961 * @return {String} 19962 * @private 19963 * @method toTitleCase 19964 */ 19965 "use strict"; 19966 19967 exports.__esModule = true; 19968 function toTitleCase(string) { 19969 return string.charAt(0).toUpperCase() + string.slice(1); 19970 } 19971 19972 exports["default"] = toTitleCase; 19973 module.exports = exports["default"]; 19974 19975 },{}],144:[function(_dereq_,module,exports){ 19976 /** 19977 * @file url.js 19978 */ 19979 'use strict'; 19980 19981 exports.__esModule = true; 19982 19983 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 19984 19985 var _globalDocument = _dereq_('global/document'); 19986 19987 var _globalDocument2 = _interopRequireDefault(_globalDocument); 19988 19989 var _globalWindow = _dereq_('global/window'); 19990 19991 var _globalWindow2 = _interopRequireDefault(_globalWindow); 19992 19993 /** 19994 * Resolve and parse the elements of a URL 19995 * 19996 * @param {String} url The url to parse 19997 * @return {Object} An object of url details 19998 * @method parseUrl 19999 */ 20000 var parseUrl = function parseUrl(url) { 20001 var props = ['protocol', 'hostname', 'port', 'pathname', 'search', 'hash', 'host']; 20002 20003 // add the url to an anchor and let the browser parse the URL 20004 var a = _globalDocument2['default'].createElement('a'); 20005 a.href = url; 20006 20007 // IE8 (and 9?) Fix 20008 // ie8 doesn't parse the URL correctly until the anchor is actually 20009 // added to the body, and an innerHTML is needed to trigger the parsing 20010 var addToBody = a.host === '' && a.protocol !== 'file:'; 20011 var div = undefined; 20012 if (addToBody) { 20013 div = _globalDocument2['default'].createElement('div'); 20014 div.innerHTML = '<a href="' + url + '"></a>'; 20015 a = div.firstChild; 20016 // prevent the div from affecting layout 20017 div.setAttribute('style', 'display:none; position:absolute;'); 20018 _globalDocument2['default'].body.appendChild(div); 20019 } 20020 20021 // Copy the specific URL properties to a new object 20022 // This is also needed for IE8 because the anchor loses its 20023 // properties when it's removed from the dom 20024 var details = {}; 20025 for (var i = 0; i < props.length; i++) { 20026 details[props[i]] = a[props[i]]; 20027 } 20028 20029 // IE9 adds the port to the host property unlike everyone else. If 20030 // a port identifier is added for standard ports, strip it. 20031 if (details.protocol === 'http:') { 20032 details.host = details.host.replace(/:80$/, ''); 20033 } 20034 if (details.protocol === 'https:') { 20035 details.host = details.host.replace(/:443$/, ''); 20036 } 20037 20038 if (addToBody) { 20039 _globalDocument2['default'].body.removeChild(div); 20040 } 20041 20042 return details; 20043 }; 20044 20045 exports.parseUrl = parseUrl; 20046 /** 20047 * Get absolute version of relative URL. Used to tell flash correct URL. 20048 * http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue 20049 * 20050 * @param {String} url URL to make absolute 20051 * @return {String} Absolute URL 20052 * @private 20053 * @method getAbsoluteURL 20054 */ 20055 var getAbsoluteURL = function getAbsoluteURL(url) { 20056 // Check if absolute URL 20057 if (!url.match(/^https?:\/\//)) { 20058 // Convert to absolute URL. Flash hosted off-site needs an absolute URL. 20059 var div = _globalDocument2['default'].createElement('div'); 20060 div.innerHTML = '<a href="' + url + '">x</a>'; 20061 url = div.firstChild.href; 20062 } 20063 20064 return url; 20065 }; 20066 20067 exports.getAbsoluteURL = getAbsoluteURL; 20068 /** 20069 * Returns the extension of the passed file name. It will return an empty string if you pass an invalid path 20070 * 20071 * @param {String} path The fileName path like '/path/to/file.mp4' 20072 * @returns {String} The extension in lower case or an empty string if no extension could be found. 20073 * @method getFileExtension 20074 */ 20075 var getFileExtension = function getFileExtension(path) { 20076 if (typeof path === 'string') { 20077 var splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i; 20078 var pathParts = splitPathRe.exec(path); 20079 20080 if (pathParts) { 20081 return pathParts.pop().toLowerCase(); 20082 } 20083 } 20084 20085 return ''; 20086 }; 20087 20088 exports.getFileExtension = getFileExtension; 20089 /** 20090 * Returns whether the url passed is a cross domain request or not. 20091 * 20092 * @param {String} url The url to check 20093 * @return {Boolean} Whether it is a cross domain request or not 20094 * @method isCrossOrigin 20095 */ 20096 var isCrossOrigin = function isCrossOrigin(url) { 20097 var winLoc = _globalWindow2['default'].location; 20098 var urlInfo = parseUrl(url); 20099 20100 // IE8 protocol relative urls will return ':' for protocol 20101 var srcProtocol = urlInfo.protocol === ':' ? winLoc.protocol : urlInfo.protocol; 20102 20103 // Check if url is for another domain/origin 20104 // IE8 doesn't know location.origin, so we won't rely on it here 20105 var crossOrigin = srcProtocol + urlInfo.host !== winLoc.protocol + winLoc.host; 20106 20107 return crossOrigin; 20108 }; 20109 exports.isCrossOrigin = isCrossOrigin; 20110 20111 },{"global/document":1,"global/window":2}],145:[function(_dereq_,module,exports){ 20112 /** 20113 * @file video.js 20114 */ 20115 'use strict'; 20116 20117 exports.__esModule = true; 20118 20119 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; } } 20120 20121 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 20122 20123 var _globalWindow = _dereq_('global/window'); 20124 20125 var _globalWindow2 = _interopRequireDefault(_globalWindow); 20126 20127 var _globalDocument = _dereq_('global/document'); 20128 20129 var _globalDocument2 = _interopRequireDefault(_globalDocument); 20130 20131 var _setup = _dereq_('./setup'); 20132 20133 var setup = _interopRequireWildcard(_setup); 20134 20135 var _utilsStylesheetJs = _dereq_('./utils/stylesheet.js'); 20136 20137 var stylesheet = _interopRequireWildcard(_utilsStylesheetJs); 20138 20139 var _component = _dereq_('./component'); 20140 20141 var _component2 = _interopRequireDefault(_component); 20142 20143 var _eventTarget = _dereq_('./event-target'); 20144 20145 var _eventTarget2 = _interopRequireDefault(_eventTarget); 20146 20147 var _utilsEventsJs = _dereq_('./utils/events.js'); 20148 20149 var Events = _interopRequireWildcard(_utilsEventsJs); 20150 20151 var _player = _dereq_('./player'); 20152 20153 var _player2 = _interopRequireDefault(_player); 20154 20155 var _pluginsJs = _dereq_('./plugins.js'); 20156 20157 var _pluginsJs2 = _interopRequireDefault(_pluginsJs); 20158 20159 var _srcJsUtilsMergeOptionsJs = _dereq_('../../src/js/utils/merge-options.js'); 20160 20161 var _srcJsUtilsMergeOptionsJs2 = _interopRequireDefault(_srcJsUtilsMergeOptionsJs); 20162 20163 var _utilsFnJs = _dereq_('./utils/fn.js'); 20164 20165 var Fn = _interopRequireWildcard(_utilsFnJs); 20166 20167 var _tracksTextTrackJs = _dereq_('./tracks/text-track.js'); 20168 20169 var _tracksTextTrackJs2 = _interopRequireDefault(_tracksTextTrackJs); 20170 20171 var _objectAssign = _dereq_('object.assign'); 20172 20173 var _objectAssign2 = _interopRequireDefault(_objectAssign); 20174 20175 var _utilsTimeRangesJs = _dereq_('./utils/time-ranges.js'); 20176 20177 var _utilsFormatTimeJs = _dereq_('./utils/format-time.js'); 20178 20179 var _utilsFormatTimeJs2 = _interopRequireDefault(_utilsFormatTimeJs); 20180 20181 var _utilsLogJs = _dereq_('./utils/log.js'); 20182 20183 var _utilsLogJs2 = _interopRequireDefault(_utilsLogJs); 20184 20185 var _utilsDomJs = _dereq_('./utils/dom.js'); 20186 20187 var Dom = _interopRequireWildcard(_utilsDomJs); 20188 20189 var _utilsBrowserJs = _dereq_('./utils/browser.js'); 20190 20191 var browser = _interopRequireWildcard(_utilsBrowserJs); 20192 20193 var _utilsUrlJs = _dereq_('./utils/url.js'); 20194 20195 var Url = _interopRequireWildcard(_utilsUrlJs); 20196 20197 var _extendJs = _dereq_('./extend.js'); 20198 20199 var _extendJs2 = _interopRequireDefault(_extendJs); 20200 20201 var _lodashCompatObjectMerge = _dereq_('lodash-compat/object/merge'); 20202 20203 var _lodashCompatObjectMerge2 = _interopRequireDefault(_lodashCompatObjectMerge); 20204 20205 var _utilsCreateDeprecationProxyJs = _dereq_('./utils/create-deprecation-proxy.js'); 20206 20207 var _utilsCreateDeprecationProxyJs2 = _interopRequireDefault(_utilsCreateDeprecationProxyJs); 20208 20209 var _xhr = _dereq_('xhr'); 20210 20211 var _xhr2 = _interopRequireDefault(_xhr); 20212 20213 // Include the built-in techs 20214 20215 var _techTechJs = _dereq_('./tech/tech.js'); 20216 20217 var _techTechJs2 = _interopRequireDefault(_techTechJs); 20218 20219 var _techHtml5Js = _dereq_('./tech/html5.js'); 20220 20221 var _techHtml5Js2 = _interopRequireDefault(_techHtml5Js); 20222 20223 var _techFlashJs = _dereq_('./tech/flash.js'); 20224 20225 var _techFlashJs2 = _interopRequireDefault(_techFlashJs); 20226 20227 // HTML5 Element Shim for IE8 20228 if (typeof HTMLVideoElement === 'undefined') { 20229 _globalDocument2['default'].createElement('video'); 20230 _globalDocument2['default'].createElement('audio'); 20231 _globalDocument2['default'].createElement('track'); 20232 } 20233 20234 /** 20235 * Doubles as the main function for users to create a player instance and also 20236 * the main library object. 20237 * The `videojs` function can be used to initialize or retrieve a player. 20238 * ```js 20239 * var myPlayer = videojs('my_video_id'); 20240 * ``` 20241 * 20242 * @param {String|Element} id Video element or video element ID 20243 * @param {Object=} options Optional options object for config/settings 20244 * @param {Function=} ready Optional ready callback 20245 * @return {Player} A player instance 20246 * @mixes videojs 20247 * @method videojs 20248 */ 20249 var videojs = function videojs(id, options, ready) { 20250 var tag = undefined; // Element of ID 20251 20252 // Allow for element or ID to be passed in 20253 // String ID 20254 if (typeof id === 'string') { 20255 20256 // Adjust for jQuery ID syntax 20257 if (id.indexOf('#') === 0) { 20258 id = id.slice(1); 20259 } 20260 20261 // If a player instance has already been created for this ID return it. 20262 if (videojs.getPlayers()[id]) { 20263 20264 // If options or ready funtion are passed, warn 20265 if (options) { 20266 _utilsLogJs2['default'].warn('Player "' + id + '" is already initialised. Options will not be applied.'); 20267 } 20268 20269 if (ready) { 20270 videojs.getPlayers()[id].ready(ready); 20271 } 20272 20273 return videojs.getPlayers()[id]; 20274 20275 // Otherwise get element for ID 20276 } else { 20277 tag = Dom.getEl(id); 20278 } 20279 20280 // ID is a media element 20281 } else { 20282 tag = id; 20283 } 20284 20285 // Check for a useable element 20286 if (!tag || !tag.nodeName) { 20287 // re: nodeName, could be a box div also 20288 throw new TypeError('The element or ID supplied is not valid. (videojs)'); // Returns 20289 } 20290 20291 // Element may have a player attr referring to an already created player instance. 20292 // If not, set up a new player and return the instance. 20293 return tag['player'] || _player2['default'].players[tag.playerId] || new _player2['default'](tag, options, ready); 20294 }; 20295 20296 // Add default styles 20297 if (_globalWindow2['default'].VIDEOJS_NO_DYNAMIC_STYLE !== true) { 20298 var style = Dom.$('.vjs-styles-defaults'); 20299 20300 if (!style) { 20301 style = stylesheet.createStyleElement('vjs-styles-defaults'); 20302 var head = Dom.$('head'); 20303 head.insertBefore(style, head.firstChild); 20304 stylesheet.setTextContent(style, '\n .video-js {\n width: 300px;\n height: 150px;\n }\n\n .vjs-fluid {\n padding-top: 56.25%\n }\n '); 20305 } 20306 } 20307 20308 // Run Auto-load players 20309 // 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) 20310 setup.autoSetupTimeout(1, videojs); 20311 20312 /* 20313 * Current software version (semver) 20314 * 20315 * @type {String} 20316 */ 20317 videojs.VERSION = '5.9.0'; 20318 20319 /** 20320 * The global options object. These are the settings that take effect 20321 * if no overrides are specified when the player is created. 20322 * 20323 * ```js 20324 * videojs.options.autoplay = true 20325 * // -> all players will autoplay by default 20326 * ``` 20327 * 20328 * @type {Object} 20329 */ 20330 videojs.options = _player2['default'].prototype.options_; 20331 20332 /** 20333 * Get an object with the currently created players, keyed by player ID 20334 * 20335 * @return {Object} The created players 20336 * @mixes videojs 20337 * @method getPlayers 20338 */ 20339 videojs.getPlayers = function () { 20340 return _player2['default'].players; 20341 }; 20342 20343 /** 20344 * For backward compatibility, expose players object. 20345 * 20346 * @deprecated 20347 * @memberOf videojs 20348 * @property {Object|Proxy} players 20349 */ 20350 videojs.players = _utilsCreateDeprecationProxyJs2['default'](_player2['default'].players, { 20351 get: 'Access to videojs.players is deprecated; use videojs.getPlayers instead', 20352 set: 'Modification of videojs.players is deprecated' 20353 }); 20354 20355 /** 20356 * Get a component class object by name 20357 * ```js 20358 * var VjsButton = videojs.getComponent('Button'); 20359 * // Create a new instance of the component 20360 * var myButton = new VjsButton(myPlayer); 20361 * ``` 20362 * 20363 * @return {Component} Component identified by name 20364 * @mixes videojs 20365 * @method getComponent 20366 */ 20367 videojs.getComponent = _component2['default'].getComponent; 20368 20369 /** 20370 * Register a component so it can referred to by name 20371 * Used when adding to other 20372 * components, either through addChild 20373 * `component.addChild('myComponent')` 20374 * or through default children options 20375 * `{ children: ['myComponent'] }`. 20376 * ```js 20377 * // Get a component to subclass 20378 * var VjsButton = videojs.getComponent('Button'); 20379 * // Subclass the component (see 'extend' doc for more info) 20380 * var MySpecialButton = videojs.extend(VjsButton, {}); 20381 * // Register the new component 20382 * VjsButton.registerComponent('MySepcialButton', MySepcialButton); 20383 * // (optionally) add the new component as a default player child 20384 * myPlayer.addChild('MySepcialButton'); 20385 * ``` 20386 * NOTE: You could also just initialize the component before adding. 20387 * `component.addChild(new MyComponent());` 20388 * 20389 * @param {String} The class name of the component 20390 * @param {Component} The component class 20391 * @return {Component} The newly registered component 20392 * @mixes videojs 20393 * @method registerComponent 20394 */ 20395 videojs.registerComponent = function (name, comp) { 20396 if (_techTechJs2['default'].isTech(comp)) { 20397 _utilsLogJs2['default'].warn('The ' + name + ' tech was registered as a component. It should instead be registered using videojs.registerTech(name, tech)'); 20398 } 20399 20400 _component2['default'].registerComponent.call(_component2['default'], name, comp); 20401 }; 20402 20403 /** 20404 * Get a Tech class object by name 20405 * ```js 20406 * var Html5 = videojs.getTech('Html5'); 20407 * // Create a new instance of the component 20408 * var html5 = new Html5(options); 20409 * ``` 20410 * 20411 * @return {Tech} Tech identified by name 20412 * @mixes videojs 20413 * @method getComponent 20414 */ 20415 videojs.getTech = _techTechJs2['default'].getTech; 20416 20417 /** 20418 * Register a Tech so it can referred to by name. 20419 * This is used in the tech order for the player. 20420 * 20421 * ```js 20422 * // get the Html5 Tech 20423 * var Html5 = videojs.getTech('Html5'); 20424 * var MyTech = videojs.extend(Html5, {}); 20425 * // Register the new Tech 20426 * VjsButton.registerTech('Tech', MyTech); 20427 * var player = videojs('myplayer', { 20428 * techOrder: ['myTech', 'html5'] 20429 * }); 20430 * ``` 20431 * 20432 * @param {String} The class name of the tech 20433 * @param {Tech} The tech class 20434 * @return {Tech} The newly registered Tech 20435 * @mixes videojs 20436 * @method registerTech 20437 */ 20438 videojs.registerTech = _techTechJs2['default'].registerTech; 20439 20440 /** 20441 * A suite of browser and device tests 20442 * 20443 * @type {Object} 20444 * @private 20445 */ 20446 videojs.browser = browser; 20447 20448 /** 20449 * Whether or not the browser supports touch events. Included for backward 20450 * compatibility with 4.x, but deprecated. Use `videojs.browser.TOUCH_ENABLED` 20451 * instead going forward. 20452 * 20453 * @deprecated 20454 * @type {Boolean} 20455 */ 20456 videojs.TOUCH_ENABLED = browser.TOUCH_ENABLED; 20457 20458 /** 20459 * Subclass an existing class 20460 * Mimics ES6 subclassing with the `extend` keyword 20461 * ```js 20462 * // Create a basic javascript 'class' 20463 * function MyClass(name){ 20464 * // Set a property at initialization 20465 * this.myName = name; 20466 * } 20467 * // Create an instance method 20468 * MyClass.prototype.sayMyName = function(){ 20469 * alert(this.myName); 20470 * }; 20471 * // Subclass the exisitng class and change the name 20472 * // when initializing 20473 * var MySubClass = videojs.extend(MyClass, { 20474 * constructor: function(name) { 20475 * // Call the super class constructor for the subclass 20476 * MyClass.call(this, name) 20477 * } 20478 * }); 20479 * // Create an instance of the new sub class 20480 * var myInstance = new MySubClass('John'); 20481 * myInstance.sayMyName(); // -> should alert "John" 20482 * ``` 20483 * 20484 * @param {Function} The Class to subclass 20485 * @param {Object} An object including instace methods for the new class 20486 * Optionally including a `constructor` function 20487 * @return {Function} The newly created subclass 20488 * @mixes videojs 20489 * @method extend 20490 */ 20491 videojs.extend = _extendJs2['default']; 20492 20493 /** 20494 * Merge two options objects recursively 20495 * Performs a deep merge like lodash.merge but **only merges plain objects** 20496 * (not arrays, elements, anything else) 20497 * Other values will be copied directly from the second object. 20498 * ```js 20499 * var defaultOptions = { 20500 * foo: true, 20501 * bar: { 20502 * a: true, 20503 * b: [1,2,3] 20504 * } 20505 * }; 20506 * var newOptions = { 20507 * foo: false, 20508 * bar: { 20509 * b: [4,5,6] 20510 * } 20511 * }; 20512 * var result = videojs.mergeOptions(defaultOptions, newOptions); 20513 * // result.foo = false; 20514 * // result.bar.a = true; 20515 * // result.bar.b = [4,5,6]; 20516 * ``` 20517 * 20518 * @param {Object} defaults The options object whose values will be overriden 20519 * @param {Object} overrides The options object with values to override the first 20520 * @param {Object} etc Any number of additional options objects 20521 * 20522 * @return {Object} a new object with the merged values 20523 * @mixes videojs 20524 * @method mergeOptions 20525 */ 20526 videojs.mergeOptions = _srcJsUtilsMergeOptionsJs2['default']; 20527 20528 /** 20529 * Change the context (this) of a function 20530 * 20531 * videojs.bind(newContext, function(){ 20532 * this === newContext 20533 * }); 20534 * 20535 * NOTE: as of v5.0 we require an ES5 shim, so you should use the native 20536 * `function(){}.bind(newContext);` instead of this. 20537 * 20538 * @param {*} context The object to bind as scope 20539 * @param {Function} fn The function to be bound to a scope 20540 * @param {Number=} uid An optional unique ID for the function to be set 20541 * @return {Function} 20542 */ 20543 videojs.bind = Fn.bind; 20544 20545 /** 20546 * Create a Video.js player plugin 20547 * Plugins are only initialized when options for the plugin are included 20548 * in the player options, or the plugin function on the player instance is 20549 * called. 20550 * **See the plugin guide in the docs for a more detailed example** 20551 * ```js 20552 * // Make a plugin that alerts when the player plays 20553 * videojs.plugin('myPlugin', function(myPluginOptions) { 20554 * myPluginOptions = myPluginOptions || {}; 20555 * 20556 * var player = this; 20557 * var alertText = myPluginOptions.text || 'Player is playing!' 20558 * 20559 * player.on('play', function(){ 20560 * alert(alertText); 20561 * }); 20562 * }); 20563 * // USAGE EXAMPLES 20564 * // EXAMPLE 1: New player with plugin options, call plugin immediately 20565 * var player1 = videojs('idOne', { 20566 * myPlugin: { 20567 * text: 'Custom text!' 20568 * } 20569 * }); 20570 * // Click play 20571 * // --> Should alert 'Custom text!' 20572 * // EXAMPLE 3: New player, initialize plugin later 20573 * var player3 = videojs('idThree'); 20574 * // Click play 20575 * // --> NO ALERT 20576 * // Click pause 20577 * // Initialize plugin using the plugin function on the player instance 20578 * player3.myPlugin({ 20579 * text: 'Plugin added later!' 20580 * }); 20581 * // Click play 20582 * // --> Should alert 'Plugin added later!' 20583 * ``` 20584 * 20585 * @param {String} name The plugin name 20586 * @param {Function} fn The plugin function that will be called with options 20587 * @mixes videojs 20588 * @method plugin 20589 */ 20590 videojs.plugin = _pluginsJs2['default']; 20591 20592 /** 20593 * Adding languages so that they're available to all players. 20594 * ```js 20595 * videojs.addLanguage('es', { 'Hello': 'Hola' }); 20596 * ``` 20597 * 20598 * @param {String} code The language code or dictionary property 20599 * @param {Object} data The data values to be translated 20600 * @return {Object} The resulting language dictionary object 20601 * @mixes videojs 20602 * @method addLanguage 20603 */ 20604 videojs.addLanguage = function (code, data) { 20605 var _merge; 20606 20607 code = ('' + code).toLowerCase(); 20608 return _lodashCompatObjectMerge2['default'](videojs.options.languages, (_merge = {}, _merge[code] = data, _merge))[code]; 20609 }; 20610 20611 /** 20612 * Log debug messages. 20613 * 20614 * @param {...Object} messages One or more messages to log 20615 */ 20616 videojs.log = _utilsLogJs2['default']; 20617 20618 /** 20619 * Creates an emulated TimeRange object. 20620 * 20621 * @param {Number|Array} start Start time in seconds or an array of ranges 20622 * @param {Number} end End time in seconds 20623 * @return {Object} Fake TimeRange object 20624 * @method createTimeRange 20625 */ 20626 videojs.createTimeRange = videojs.createTimeRanges = _utilsTimeRangesJs.createTimeRanges; 20627 20628 /** 20629 * Format seconds as a time string, H:MM:SS or M:SS 20630 * Supplying a guide (in seconds) will force a number of leading zeros 20631 * to cover the length of the guide 20632 * 20633 * @param {Number} seconds Number of seconds to be turned into a string 20634 * @param {Number} guide Number (in seconds) to model the string after 20635 * @return {String} Time formatted as H:MM:SS or M:SS 20636 * @method formatTime 20637 */ 20638 videojs.formatTime = _utilsFormatTimeJs2['default']; 20639 20640 /** 20641 * Resolve and parse the elements of a URL 20642 * 20643 * @param {String} url The url to parse 20644 * @return {Object} An object of url details 20645 * @method parseUrl 20646 */ 20647 videojs.parseUrl = Url.parseUrl; 20648 20649 /** 20650 * Returns whether the url passed is a cross domain request or not. 20651 * 20652 * @param {String} url The url to check 20653 * @return {Boolean} Whether it is a cross domain request or not 20654 * @method isCrossOrigin 20655 */ 20656 videojs.isCrossOrigin = Url.isCrossOrigin; 20657 20658 /** 20659 * Event target class. 20660 * 20661 * @type {Function} 20662 */ 20663 videojs.EventTarget = _eventTarget2['default']; 20664 20665 /** 20666 * Add an event listener to element 20667 * It stores the handler function in a separate cache object 20668 * and adds a generic handler to the element's event, 20669 * along with a unique id (guid) to the element. 20670 * 20671 * @param {Element|Object} elem Element or object to bind listeners to 20672 * @param {String|Array} type Type of event to bind to. 20673 * @param {Function} fn Event listener. 20674 * @method on 20675 */ 20676 videojs.on = Events.on; 20677 20678 /** 20679 * Trigger a listener only once for an event 20680 * 20681 * @param {Element|Object} elem Element or object to 20682 * @param {String|Array} type Name/type of event 20683 * @param {Function} fn Event handler function 20684 * @method one 20685 */ 20686 videojs.one = Events.one; 20687 20688 /** 20689 * Removes event listeners from an element 20690 * 20691 * @param {Element|Object} elem Object to remove listeners from 20692 * @param {String|Array=} type Type of listener to remove. Don't include to remove all events from element. 20693 * @param {Function} fn Specific listener to remove. Don't include to remove listeners for an event type. 20694 * @method off 20695 */ 20696 videojs.off = Events.off; 20697 20698 /** 20699 * Trigger an event for an element 20700 * 20701 * @param {Element|Object} elem Element to trigger an event on 20702 * @param {Event|Object|String} event A string (the type) or an event object with a type attribute 20703 * @param {Object} [hash] data hash to pass along with the event 20704 * @return {Boolean=} Returned only if default was prevented 20705 * @method trigger 20706 */ 20707 videojs.trigger = Events.trigger; 20708 20709 /** 20710 * A cross-browser XMLHttpRequest wrapper. Here's a simple example: 20711 * 20712 * videojs.xhr({ 20713 * body: someJSONString, 20714 * uri: "/foo", 20715 * headers: { 20716 * "Content-Type": "application/json" 20717 * } 20718 * }, function (err, resp, body) { 20719 * // check resp.statusCode 20720 * }); 20721 * 20722 * Check out the [full 20723 * documentation](https://github.com/Raynos/xhr/blob/v2.1.0/README.md) 20724 * for more options. 20725 * 20726 * @param {Object} options settings for the request. 20727 * @return {XMLHttpRequest|XDomainRequest} the request object. 20728 * @see https://github.com/Raynos/xhr 20729 */ 20730 videojs.xhr = _xhr2['default']; 20731 20732 /** 20733 * TextTrack class 20734 * 20735 * @type {Function} 20736 */ 20737 videojs.TextTrack = _tracksTextTrackJs2['default']; 20738 20739 /** 20740 * Determines, via duck typing, whether or not a value is a DOM element. 20741 * 20742 * @method isEl 20743 * @param {Mixed} value 20744 * @return {Boolean} 20745 */ 20746 videojs.isEl = Dom.isEl; 20747 20748 /** 20749 * Determines, via duck typing, whether or not a value is a text node. 20750 * 20751 * @method isTextNode 20752 * @param {Mixed} value 20753 * @return {Boolean} 20754 */ 20755 videojs.isTextNode = Dom.isTextNode; 20756 20757 /** 20758 * Creates an element and applies properties. 20759 * 20760 * @method createEl 20761 * @param {String} [tagName='div'] Name of tag to be created. 20762 * @param {Object} [properties={}] Element properties to be applied. 20763 * @param {Object} [attributes={}] Element attributes to be applied. 20764 * @return {Element} 20765 */ 20766 videojs.createEl = Dom.createEl; 20767 20768 /** 20769 * Check if an element has a CSS class 20770 * 20771 * @method hasClass 20772 * @param {Element} element Element to check 20773 * @param {String} classToCheck Classname to check 20774 */ 20775 videojs.hasClass = Dom.hasElClass; 20776 20777 /** 20778 * Add a CSS class name to an element 20779 * 20780 * @method addClass 20781 * @param {Element} element Element to add class name to 20782 * @param {String} classToAdd Classname to add 20783 */ 20784 videojs.addClass = Dom.addElClass; 20785 20786 /** 20787 * Remove a CSS class name from an element 20788 * 20789 * @method removeClass 20790 * @param {Element} element Element to remove from class name 20791 * @param {String} classToRemove Classname to remove 20792 */ 20793 videojs.removeClass = Dom.removeElClass; 20794 20795 /** 20796 * Adds or removes a CSS class name on an element depending on an optional 20797 * condition or the presence/absence of the class name. 20798 * 20799 * @method toggleElClass 20800 * @param {Element} element 20801 * @param {String} classToToggle 20802 * @param {Boolean|Function} [predicate] 20803 * Can be a function that returns a Boolean. If `true`, the class 20804 * will be added; if `false`, the class will be removed. If not 20805 * given, the class will be added if not present and vice versa. 20806 */ 20807 videojs.toggleClass = Dom.toggleElClass; 20808 20809 /** 20810 * Apply attributes to an HTML element. 20811 * 20812 * @method setAttributes 20813 * @param {Element} el Target element. 20814 * @param {Object=} attributes Element attributes to be applied. 20815 */ 20816 videojs.setAttributes = Dom.setElAttributes; 20817 20818 /** 20819 * Get an element's attribute values, as defined on the HTML tag 20820 * Attributes are not the same as properties. They're defined on the tag 20821 * or with setAttribute (which shouldn't be used with HTML) 20822 * This will return true or false for boolean attributes. 20823 * 20824 * @method getAttributes 20825 * @param {Element} tag Element from which to get tag attributes 20826 * @return {Object} 20827 */ 20828 videojs.getAttributes = Dom.getElAttributes; 20829 20830 /** 20831 * Empties the contents of an element. 20832 * 20833 * @method emptyEl 20834 * @param {Element} el 20835 * @return {Element} 20836 */ 20837 videojs.emptyEl = Dom.emptyEl; 20838 20839 /** 20840 * Normalizes and appends content to an element. 20841 * 20842 * The content for an element can be passed in multiple types and 20843 * combinations, whose behavior is as follows: 20844 * 20845 * - String 20846 * Normalized into a text node. 20847 * 20848 * - Element, TextNode 20849 * Passed through. 20850 * 20851 * - Array 20852 * A one-dimensional array of strings, elements, nodes, or functions (which 20853 * return single strings, elements, or nodes). 20854 * 20855 * - Function 20856 * If the sole argument, is expected to produce a string, element, 20857 * node, or array. 20858 * 20859 * @method appendContent 20860 * @param {Element} el 20861 * @param {String|Element|TextNode|Array|Function} content 20862 * @return {Element} 20863 */ 20864 videojs.appendContent = Dom.appendContent; 20865 20866 /** 20867 * Normalizes and inserts content into an element; this is identical to 20868 * `appendContent()`, except it empties the element first. 20869 * 20870 * The content for an element can be passed in multiple types and 20871 * combinations, whose behavior is as follows: 20872 * 20873 * - String 20874 * Normalized into a text node. 20875 * 20876 * - Element, TextNode 20877 * Passed through. 20878 * 20879 * - Array 20880 * A one-dimensional array of strings, elements, nodes, or functions (which 20881 * return single strings, elements, or nodes). 20882 * 20883 * - Function 20884 * If the sole argument, is expected to produce a string, element, 20885 * node, or array. 20886 * 20887 * @method insertContent 20888 * @param {Element} el 20889 * @param {String|Element|TextNode|Array|Function} content 20890 * @return {Element} 20891 */ 20892 videojs.insertContent = Dom.insertContent; 20893 20894 /* 20895 * Custom Universal Module Definition (UMD) 20896 * 20897 * Video.js will never be a non-browser lib so we can simplify UMD a bunch and 20898 * still support requirejs and browserify. This also needs to be closure 20899 * compiler compatible, so string keys are used. 20900 */ 20901 if (typeof define === 'function' && define['amd']) { 20902 define('videojs', [], function () { 20903 return videojs; 20904 }); 20905 20906 // checking that module is an object too because of umdjs/umd#35 20907 } else if (typeof exports === 'object' && typeof module === 'object') { 20908 module['exports'] = videojs; 20909 } 20910 20911 exports['default'] = videojs; 20912 module.exports = exports['default']; 20913 20914 },{"../../src/js/utils/merge-options.js":140,"./component":67,"./event-target":101,"./extend.js":102,"./player":110,"./plugins.js":111,"./setup":115,"./tech/flash.js":118,"./tech/html5.js":119,"./tech/tech.js":121,"./tracks/text-track.js":130,"./utils/browser.js":131,"./utils/create-deprecation-proxy.js":133,"./utils/dom.js":134,"./utils/events.js":135,"./utils/fn.js":136,"./utils/format-time.js":137,"./utils/log.js":139,"./utils/stylesheet.js":141,"./utils/time-ranges.js":142,"./utils/url.js":144,"global/document":1,"global/window":2,"lodash-compat/object/merge":40,"object.assign":45,"xhr":56}]},{},[145])(145) 20915 }); 20916 20917 20918 //# sourceMappingURL=video.js.map