diff options
author | Sam Potts <sam@potts.es> | 2018-06-09 17:03:16 +1000 |
---|---|---|
committer | Sam Potts <sam@potts.es> | 2018-06-09 17:03:16 +1000 |
commit | 7c6d4666e99f1604c28c57bec12f16bd0fb7e79c (patch) | |
tree | 2b5e3288defe5760694fe1096cc1d9c3490f3118 /dist/plyr.polyfilled.js | |
parent | 90c5735904354f5fde0dcdae9f8894fe9088739c (diff) | |
parent | 76bb299c68a6b5cc72729771aca2f0d51078ebc5 (diff) | |
download | plyr-7c6d4666e99f1604c28c57bec12f16bd0fb7e79c.tar.lz plyr-7c6d4666e99f1604c28c57bec12f16bd0fb7e79c.tar.xz plyr-7c6d4666e99f1604c28c57bec12f16bd0fb7e79c.zip |
Merge branch 'develop' into a11y-improvements
# Conflicts:
# demo/dist/demo.css
# dist/plyr.css
# dist/plyr.js.map
# dist/plyr.min.js
# dist/plyr.min.js.map
# dist/plyr.polyfilled.js
# dist/plyr.polyfilled.js.map
# dist/plyr.polyfilled.min.js
# dist/plyr.polyfilled.min.js.map
# src/js/captions.js
# src/js/plyr.js
Diffstat (limited to 'dist/plyr.polyfilled.js')
-rw-r--r-- | dist/plyr.polyfilled.js | 391 |
1 files changed, 164 insertions, 227 deletions
diff --git a/dist/plyr.polyfilled.js b/dist/plyr.polyfilled.js index da24e216..e5a32e77 100644 --- a/dist/plyr.polyfilled.js +++ b/dist/plyr.polyfilled.js @@ -20,7 +20,7 @@ if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef }); var _core = createCommonjsModule(function (module) { -var core = module.exports = { version: '2.5.6' }; +var core = module.exports = { version: '2.5.3' }; if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef }); var _core_1 = _core.version; @@ -333,18 +333,11 @@ var _arrayIncludes = function (IS_INCLUDES) { }; }; -var _shared = createCommonjsModule(function (module) { var SHARED = '__core-js_shared__'; var store = _global[SHARED] || (_global[SHARED] = {}); - -(module.exports = function (key, value) { - return store[key] || (store[key] = value !== undefined ? value : {}); -})('versions', []).push({ - version: _core.version, - mode: _library ? 'pure' : 'global', - copyright: '© 2018 Denis Pushkarev (zloirock.ru)' -}); -}); +var _shared = function (key) { + return store[key] || (store[key] = {}); +}; var shared = _shared('keys'); @@ -998,7 +991,7 @@ var _iterDefine = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORC var VALUES_BUG = false; var proto = Base.prototype; var $native = proto[ITERATOR$2] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; - var $default = $native || getMethod(DEFAULT); + var $default = (!BUGGY && $native) || getMethod(DEFAULT); var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; var methods, key, IteratorPrototype; @@ -1009,7 +1002,7 @@ var _iterDefine = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORC // Set @@toStringTag to native iterators _setToStringTag(IteratorPrototype, TAG, true); // fix for some old engines - if (!_library && typeof IteratorPrototype[ITERATOR$2] != 'function') _hide(IteratorPrototype, ITERATOR$2, returnThis); + if (!_library && !_has(IteratorPrototype, ITERATOR$2)) _hide(IteratorPrototype, ITERATOR$2, returnThis); } } // fix Array#{values, @@iterator}.name in V8 / FF @@ -2503,11 +2496,9 @@ function set(target, propertyKey, V /* , receiver */) { } if (_has(ownDesc, 'value')) { if (ownDesc.writable === false || !_isObject(receiver)) return false; - if (existingDescriptor = _objectGopd.f(receiver, propertyKey)) { - if (existingDescriptor.get || existingDescriptor.set || existingDescriptor.writable === false) return false; - existingDescriptor.value = V; - _objectDp.f(receiver, propertyKey, existingDescriptor); - } else _objectDp.f(receiver, propertyKey, _propertyDesc(0, V)); + existingDescriptor = _objectGopd.f(receiver, propertyKey) || _propertyDesc(0); + existingDescriptor.value = V; + _objectDp.f(receiver, propertyKey, existingDescriptor); return true; } return ownDesc.set === undefined ? false : (ownDesc.set.call(receiver, V), true); @@ -2652,8 +2643,7 @@ var _microtask = function () { }; // environments with maybe non-completely correct, but existent Promise } else if (Promise$1 && Promise$1.resolve) { - // Promise.resolve without an argument throws an error in LG WebOS 2 - var promise = Promise$1.resolve(undefined); + var promise = Promise$1.resolve(); notify = function () { promise.then(flush); }; @@ -2710,10 +2700,6 @@ var _perform = function (exec) { } }; -var navigator$1 = _global.navigator; - -var _userAgent = navigator$1 && navigator$1.userAgent || ''; - var _promiseResolve = function (C, x) { _anObject(C); if (_isObject(x) && x.constructor === C) return x; @@ -2728,12 +2714,9 @@ var microtask = _microtask(); - var PROMISE = 'Promise'; var TypeError$1 = _global.TypeError; var process$2 = _global.process; -var versions = process$2 && process$2.versions; -var v8 = versions && versions.v8 || ''; var $Promise = _global[PROMISE]; var isNode$1 = _classof(process$2) == 'process'; var empty = function () { /* empty */ }; @@ -2748,13 +2731,7 @@ var USE_NATIVE = !!function () { exec(empty, empty); }; // unhandled rejections tracking support, NodeJS Promise without it fails @@species test - return (isNode$1 || typeof PromiseRejectionEvent == 'function') - && promise.then(empty) instanceof FakePromise - // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables - // https://bugs.chromium.org/p/chromium/issues/detail?id=830565 - // we can't detect it synchronously, so just check versions - && v8.indexOf('6.6') !== 0 - && _userAgent.indexOf('Chrome/66') === -1; + return (isNode$1 || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise; } catch (e) { /* empty */ } }(); @@ -2776,7 +2753,7 @@ var notify = function (promise, isReject) { var resolve = reaction.resolve; var reject = reaction.reject; var domain = reaction.domain; - var result, then, exited; + var result, then; try { if (handler) { if (!ok) { @@ -2786,11 +2763,8 @@ var notify = function (promise, isReject) { if (handler === true) result = value; else { if (domain) domain.enter(); - result = handler(value); // may throw - if (domain) { - domain.exit(); - exited = true; - } + result = handler(value); + if (domain) domain.exit(); } if (result === reaction.promise) { reject(TypeError$1('Promise-chain cycle')); @@ -2799,7 +2773,6 @@ var notify = function (promise, isReject) { } else resolve(result); } else reject(value); } catch (e) { - if (domain && !exited) domain.exit(); reject(e); } }; @@ -4182,6 +4155,10 @@ var _stringPad = function (that, maxLength, fillString, left) { return left ? stringFiller + S : S + stringFiller; }; +var navigator$1 = _global.navigator; + +var _userAgent = navigator$1 && navigator$1.userAgent || ''; + // https://github.com/tc39/proposal-string-pad-start-end @@ -5813,7 +5790,7 @@ var Storage = function () { createClass(Storage, [{ key: 'get', value: function get(key) { - if (!Storage.supported) { + if (!Storage.supported || !this.enabled) { return null; } @@ -5932,7 +5909,7 @@ var utils = { return this.instanceof(input, Event); }, cue: function cue(input) { - return this.instanceof(input, TextTrackCue) || this.instanceof(input, VTTCue); + return this.instanceof(input, window.TextTrackCue) || this.instanceof(input, window.VTTCue); }, track: function track(input) { return this.instanceof(input, TextTrack) || !this.nullOrUndefined(input) && this.string(input.kind); @@ -6043,26 +6020,25 @@ var utils = { return; } - var prefix = 'cache-'; + var prefix = 'cache'; var hasId = utils.is.string(id); var isCached = false; var exists = function exists() { - return document.querySelectorAll('#' + id).length; + return document.getElementById(id) !== null; }; - function injectSprite(data) { + var update = function update(container, data) { + container.innerHTML = data; + // Check again incase of race condition if (hasId && exists()) { return; } - // Inject content - this.innerHTML = data; - // Inject the SVG to the body - document.body.insertBefore(this, document.body.childNodes[0]); - } + document.body.insertAdjacentElement('afterbegin', container); + }; // Only load once if ID set if (!hasId || !exists()) { @@ -6078,13 +6054,12 @@ var utils = { // Check in cache if (useStorage) { - var cached = window.localStorage.getItem(prefix + id); + var cached = window.localStorage.getItem(prefix + '-' + id); isCached = cached !== null; if (isCached) { var data = JSON.parse(cached); - injectSprite.call(container, data.content); - return; + update(container, data.content); } } @@ -6095,12 +6070,12 @@ var utils = { } if (useStorage) { - window.localStorage.setItem(prefix + id, JSON.stringify({ + window.localStorage.setItem(prefix + '-' + id, JSON.stringify({ content: result })); } - injectSprite.call(container, result); + update(container, result); }).catch(function () {}); } }, @@ -6681,6 +6656,14 @@ var utils = { }, + // Get a nested value in an object + getDeep: function getDeep(object, path) { + return path.split('.').reduce(function (obj, key) { + return obj && obj[key]; + }, object); + }, + + // Get the closest value in an array closest: function closest(array, value) { if (!utils.is.array(array) || !array.length) { @@ -7100,6 +7083,13 @@ var html5 = { player.media.src = supported[0].getAttribute('src'); + // Restore time + var onLoadedMetaData = function onLoadedMetaData() { + player.currentTime = currentTime; + player.off('loadedmetadata', onLoadedMetaData); + }; + player.on('loadedmetadata', onLoadedMetaData); + // Load new source player.media.load(); @@ -7108,9 +7098,6 @@ var html5 = { player.play(); } - // Restore time - player.currentTime = currentTime; - // Trigger change event utils.dispatchEvent.call(player, player.media, 'qualitychange', false, { quality: input @@ -7152,11 +7139,15 @@ var i18n = { var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (utils.is.empty(key) || utils.is.empty(config) || !Object.keys(config.i18n).includes(key)) { + if (utils.is.empty(key) || utils.is.empty(config)) { return ''; } - var string = config.i18n[key]; + var string = utils.getDeep(config.i18n, key); + + if (utils.is.empty(string)) { + return ''; + } var replace = { '{seektime}': config.seekTime, @@ -7428,30 +7419,10 @@ var controls = { this.elements.buttons[type] = button; } - /* // Toggle aria-pressed state on a toggle button - // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles - toggleState(element, input) { - // If multiple elements passed - if (utils.is.array(element) || utils.is.nodeList(element)) { - Array.from(element).forEach(target => utils.toggleState(target, input)); - return; - } - // Bail if no target - if (!utils.is.element(element)) { - return; - } - // Get state - const pressed = element.classList.contains(this.config.className; - const state = utils.is.boolean(input) ? input : !pressed; - // Set the attribute on target - element.setAttribute('aria-pressed', state); - }, */ - + // Toggle classname when pressed property is set var className = this.config.classNames.controlPressed; - Object.defineProperty(button, 'pressed', { enumerable: true, - configurable: true, get: function get() { return utils.hasClass(button, className); }, @@ -7468,13 +7439,6 @@ var controls = { // Create an <input type='range'> createRange: function createRange(type, attributes) { - // Seek label - var label = utils.createElement('label', { - for: attributes.id, - id: attributes.id + '-label', - class: this.config.classNames.hidden - }, i18n.get(type, this.config)); - // Seek input var input = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), { type: 'range', @@ -7485,7 +7449,7 @@ var controls = { autocomplete: 'off', // A11y fixes for https://github.com/sampotts/plyr/issues/905 role: 'slider', - 'aria-labelledby': attributes.id + '-label', + 'aria-label': i18n.get(type, this.config), 'aria-valuemin': 0, 'aria-valuemax': 100, 'aria-valuenow': 0 @@ -7496,10 +7460,7 @@ var controls = { // Set the fill for webkit now controls.updateRangeFill.call(this, input); - return { - label: label, - input: input - }; + return input; }, @@ -7861,27 +7822,7 @@ var controls = { // Get the badge HTML for HD, 4K etc var getBadge = function getBadge(quality) { - var label = ''; - - switch (quality) { - case 2160: - label = '4K'; - break; - - case 1440: - case 1080: - case 720: - label = 'HD'; - break; - - case 576: - case 480: - label = 'SD'; - break; - - default: - break; - } + var label = i18n.get('qualityBadge.' + quality, _this3.config); if (!label.length) { return null; @@ -7904,7 +7845,6 @@ var controls = { // Translate a value into a nice label - // TODO: Localisation getLabel: function getLabel(setting, value) { switch (setting) { case 'speed': @@ -7912,7 +7852,13 @@ var controls = { case 'quality': if (utils.is.number(value)) { - return value + 'p'; + var label = i18n.get('qualityLabel.' + value, this.config); + + if (!label.length) { + return value + 'p'; + } + + return label; } return utils.toTitleCase(value); @@ -8072,12 +8018,7 @@ var controls = { // Generate options tracks.forEach(function (track) { - controls.createMenuItem.call(_this4, track.language, list, 'language', track.label, track.language !== 'enabled' ? controls.createBadge.call(_this4, track.language.toUpperCase()) : null, track.language.toLowerCase() === _this4.captions.language.toLowerCase()); - }); - - // Store reference - this.options.captions = tracks.map(function (track) { - return track.language; + controls.createMenuItem.call(_this4, track.language, list, 'language', track.label, track.language !== 'enabled' ? controls.createBadge.call(_this4, track.language.toUpperCase()) : null, track.language.toLowerCase() === _this4.language); }); controls.updateSetting.call(this, type, list); @@ -8346,11 +8287,9 @@ var controls = { var progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider - var seek = controls.createRange.call(this, 'seek', { + progress.appendChild(controls.createRange.call(this, 'seek', { id: 'plyr-seek-' + data.id - }); - progress.appendChild(seek.label); - progress.appendChild(seek.input); + })); // Buffer progress progress.appendChild(controls.createProgress.call(this, 'buffer')); @@ -8400,11 +8339,9 @@ var controls = { }; // Create the volume range slider - var range = controls.createRange.call(this, 'volume', utils.extend(attributes, { + volume.appendChild(controls.createRange.call(this, 'volume', utils.extend(attributes, { id: 'plyr-volume-' + data.id - })); - volume.appendChild(range.label); - volume.appendChild(range.input); + }))); this.elements.volume = volume; @@ -8680,28 +8617,6 @@ var captions = { return; } - // Set default language if not set - var stored = this.storage.get('language'); - - if (!utils.is.empty(stored)) { - this.captions.language = stored; - } - - if (utils.is.empty(this.captions.language)) { - this.captions.language = this.config.captions.language.toLowerCase(); - } - - // Set captions enabled state if not set - if (!utils.is.boolean(this.captions.active)) { - var active = this.storage.get('captions'); - - if (utils.is.boolean(active)) { - this.captions.active = active; - } else { - this.captions.active = this.config.captions.active; - } - } - // Only Vimeo and HTML5 video supported at this point if (!this.isVideo || this.isYouTube || this.isHTML5 && !support.textTracks) { // Clear menu and hide @@ -8719,17 +8634,6 @@ var captions = { utils.insertAfter(this.elements.captions, this.elements.wrapper); } - // Set the class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this))); - - // Get tracks - var tracks = captions.getTracks.call(this); - - // If no caption file exists, hide container for caption text - if (utils.is.empty(tracks)) { - return; - } - // Get browser info var browser = utils.getBrowser(); @@ -8752,14 +8656,52 @@ var captions = { }); } - // Set language - captions.setLanguage.call(this); + // Try to load the value from storage + var active = this.storage.get('captions'); - // Enable UI - captions.show.call(this); + // Otherwise fall back to the default config + if (!utils.is.boolean(active)) { + active = this.config.captions.active; + } - // Set available languages in list - if (utils.is.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) { + // Set toggled state + this.toggleCaptions(active); + + // Watch changes to textTracks and update captions menu + if (this.config.captions.update) { + utils.on(this.media.textTracks, 'addtrack removetrack', captions.update.bind(this)); + } + + // Update available languages in list next tick (the event must not be triggered before the listeners) + setTimeout(captions.update.bind(this), 0); + }, + update: function update() { + // Update tracks + var tracks = captions.getTracks.call(this); + this.options.captions = tracks.map(function (_ref) { + var language = _ref.language; + return language; + }); + + // Set language if it hasn't been set already + if (!this.language) { + var language = this.config.captions.language; + + if (language === 'auto') { + var _split = (navigator.language || navigator.userLanguage).split('-'); + + var _split2 = slicedToArray(_split, 1); + + language = _split2[0]; + } + this.language = this.storage.get('language') || (language || '').toLowerCase(); + } + + // Toggle the class hooks + utils.toggleClass(this.elements.container, this.config.classNames.captions.enabled, !utils.is.empty(captions.getTracks.call(this))); + + // Update available languages in list + if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { controls.setCaptionsMenu.call(this); } }, @@ -8920,25 +8862,6 @@ var captions = { } else { this.debug.warn('No captions element to render to'); } - }, - - - // Display captions container and button (for initialization) - show: function show() { - // Try to load the value from storage - var active = this.storage.get('captions'); - - // Otherwise fall back to the default config - if (!utils.is.boolean(active)) { - active = this.config.captions.active; - } else { - this.captions.active = active; - } - - if (active) { - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, true); - this.elements.buttons.captions.pressed = true; - } } }; @@ -9044,7 +8967,7 @@ var defaults$1 = { // Sprite (for icons) loadSprite: true, iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.3.8/plyr.svg', + iconUrl: 'https://cdn.plyr.io/3.3.10/plyr.svg', // Blank video (used to prevent errors on source change) blankVideo: 'https://cdn.plyr.io/static/blank.mp4', @@ -9083,7 +9006,10 @@ var defaults$1 = { // Captions settings captions: { active: false, - language: (navigator.language || navigator.userLanguage).split('-')[0] + language: 'auto', + // Listen to new tracks added after Plyr is initialized. + // This is needed for streaming captions, but may result in unselectable options + update: false }, // Fullscreen settings @@ -9140,7 +9066,15 @@ var defaults$1 = { reset: 'Reset', disabled: 'Disabled', enabled: 'Enabled', - advertisement: 'Ad' + advertisement: 'Ad', + qualityBadge: { + 2160: '4K', + 1440: 'HD', + 1080: 'HD', + 720: 'HD', + 576: 'SD', + 480: 'SD' + } }, // URLs @@ -9228,9 +9162,8 @@ var defaults$1 = { display: { currentTime: '.plyr__time--current', duration: '.plyr__time--duration', - buffer: '.plyr__progress--buffer', - played: '.plyr__progress--played', - loop: '.plyr__progress--loop', + buffer: '.plyr__progress__buffer', + loop: '.plyr__progress__loop', // Used later volume: '.plyr__volume--display' }, progress: '.plyr__progress', @@ -9600,8 +9533,10 @@ var ui = { // Remove native controls ui.toggleNativeControls.call(this); - // Captions - captions.setup.call(this); + // Setup captions for HTML5 + if (this.isHTML5) { + captions.setup.call(this); + } // Reset volume this.volume = null; @@ -9654,6 +9589,12 @@ var ui = { if (this.poster && this.elements.poster && !this.elements.poster.style.backgroundImage) { ui.setPoster.call(this, this.poster); } + + // Manually set the duration if user has overridden it. + // The event listeners for it doesn't get called if preload is disabled (#701) + if (this.config.duration) { + controls.durationUpdate.call(this); + } }, @@ -9847,7 +9788,7 @@ var Listeners = function () { // and if the focused element is not editable (e.g. text input) // and any that accept key input http://webaim.org/techniques/keyboard/ var focused = utils.getFocusElement(); - if (utils.is.element(focused) && utils.matches(focused, this.player.config.selectors.editable)) { + if (utils.is.element(focused) && focused !== this.player.elements.inputs.seek && utils.matches(focused, this.player.config.selectors.editable)) { return; } @@ -10341,6 +10282,12 @@ var Listeners = function () { on(this.player.elements.inputs.seek, 'mousedown mouseup keydown keyup touchstart touchend', function (event) { var seek = event.currentTarget; + var code = event.keyCode ? event.keyCode : event.which; + var eventType = event.type; + + if ((eventType === 'keydown' || eventType === 'keyup') && code !== 39 && code !== 37) { + return; + } // Was playing before? var play = seek.hasAttribute('play-on-seeked'); @@ -12715,24 +12662,19 @@ var Plyr = function () { } // If the method is called without parameter, toggle based on current value - var show = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active); - - // Nothing to change... - if (this.captions.active === show) { - return; - } - - // Set global - this.captions.active = show; + var active = utils.is.boolean(input) ? input : !this.elements.container.classList.contains(this.config.classNames.captions.active); // Toggle state - this.elements.buttons.captions.pressed = this.captions.active; + this.elements.buttons.captions.pressed = active; // Add class hook - utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.active); + utils.toggleClass(this.elements.container, this.config.classNames.captions.active, active); - // Trigger an event - utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled'); + // Update state and trigger event + if (active !== this.captions.active) { + this.captions.active = active; + utils.dispatchEvent.call(this, this.media, this.captions.active ? 'captionsenabled' : 'captionsdisabled'); + } } /** @@ -13020,21 +12962,16 @@ var Plyr = function () { }, { key: 'currentTime', set: function set(input) { - var targetTime = 0; - - if (utils.is.number(input)) { - targetTime = input; + // Bail if media duration isn't available yet + if (!this.duration) { + return; } - // Normalise targetTime - if (targetTime < 0) { - targetTime = 0; - } else if (targetTime > this.duration) { - targetTime = this.duration; - } + // Validate input + var inputIsValid = utils.is.number(input) && input > 0; // Set - this.media.currentTime = targetTime; + this.media.currentTime = inputIsValid ? Math.min(input, this.duration) : 0; // Logging this.debug.log('Seeking to ' + this.currentTime + ' seconds'); @@ -13093,11 +13030,11 @@ var Plyr = function () { // Faux duration set via config var fauxDuration = parseFloat(this.config.duration); - // True duration - var realDuration = this.media ? Number(this.media.duration) : 0; + // Media duration can be NaN before the media has loaded + var duration = (this.media || {}).duration || 0; - // If custom duration is funky, use regular duration - return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration; + // If config duration is funky, use regular duration + return fauxDuration || duration; } /** @@ -13269,7 +13206,7 @@ var Plyr = function () { quality = Number(input); } - if (!utils.is.number(quality) || quality === 0) { + if (!utils.is.number(quality)) { quality = this.storage.get('quality'); } |