Cleanup events and references

This commit is contained in:
Sam Potts
2017-04-16 13:00:57 +10:00
parent 546cdaad92
commit ff2d27f8e5
3 changed files with 181 additions and 107 deletions

View File

@ -21,7 +21,17 @@
captions: { captions: {
defaultActive: true defaultActive: true
}, },
controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'fullscreen'] controls: [
'play-large',
'play',
'progress',
'current-time',
'mute',
'volume',
'captions',
'settings',
'fullscreen'
]
}); });
plyr.loadSprite('dist/demo.svg'); plyr.loadSprite('dist/demo.svg');

4
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

View File

@ -89,15 +89,15 @@
rewind: '[data-plyr="rewind"]', rewind: '[data-plyr="rewind"]',
forward: '[data-plyr="fast-forward"]', forward: '[data-plyr="fast-forward"]',
mute: '[data-plyr="mute"]', mute: '[data-plyr="mute"]',
captions: '[data-plyr="captions"]',
fullscreen: '[data-plyr="fullscreen"]', fullscreen: '[data-plyr="fullscreen"]',
settings: '[data-plyr="settings"]',
pip: '[data-plyr="pip"]', pip: '[data-plyr="pip"]',
airplay: '[data-plyr="airplay"]', airplay: '[data-plyr="airplay"]',
settings: '[data-plyr="settings"]',
speed: '[data-plyr="speed"]', speed: '[data-plyr="speed"]',
loop: '[data-plyr="loop"]', loop: '[data-plyr="loop"]',
captions: '[data-plyr="captions"]', language: '[data-plyr="language"]',
//captions_menu: '[data-plyr="captions_menu"]', quality: '[data-plyr="quality"]'
//captions_lang: '[data-plyr="captions_lang"]',
}, },
inputs: { inputs: {
seek: '[data-plyr="seek"]', seek: '[data-plyr="seek"]',
@ -160,7 +160,19 @@
enabled: true, enabled: true,
key: 'plyr' key: 'plyr'
}, },
controls: ['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen'], controls: [
'play-large',
'play',
'progress',
'current-time',
'mute',
'volume',
'captions',
'settings',
'pip',
'airplay',
'fullscreen'
],
i18n: { i18n: {
restart: 'Restart', restart: 'Restart',
rewind: 'Rewind {seektime} secs', rewind: 'Rewind {seektime} secs',
@ -214,10 +226,13 @@
mute: null, mute: null,
volume: null, volume: null,
captions: null, captions: null,
//captions_lang: null,
fullscreen: null, fullscreen: null,
pip: null,
airplay: null,
speed: null, speed: null,
loop: null quality: null,
loop: null,
language: null
}, },
// Events to watch on HTML5 media elements // Events to watch on HTML5 media elements
events: [ events: [
@ -272,7 +287,7 @@
return input !== null && typeof input === 'function'; return input !== null && typeof input === 'function';
}, },
event: function(input) { event: function(input) {
return input !== null && typeof input === 'object' && (input.constructor === Event || input.constructor === CustomEvent); return input !== null && input instanceof Event;
}, },
undefined: function(input) { undefined: function(input) {
return input !== null && typeof input === 'undefined'; return input !== null && typeof input === 'undefined';
@ -581,10 +596,10 @@
} }
// Bind along with custom handler // Bind along with custom handler
function proxy(element, eventName, userListener, defaultListener, useCapture) { function proxy(element, eventName, customListener, defaultListener, useCapture) {
on(element, eventName, function(event) { on(element, eventName, function(event) {
if (userListener) { if (customListener) {
userListener.apply(element, [event]); customListener.apply(element, [event]);
} }
defaultListener.apply(element, [event]); defaultListener.apply(element, [event]);
}, useCapture); }, useCapture);
@ -909,8 +924,9 @@
progress: {}, progress: {},
inputs: {}, inputs: {},
settings: { settings: {
tabs: {}, menu: null,
panes: {} panes: {},
tabs: {}
}, },
media: media media: media
}; };
@ -1265,6 +1281,7 @@
}, '00:00'); }, '00:00');
container.appendChild(tooltip); container.appendChild(tooltip);
player.elements.display.seekTooltip = tooltip;
} }
player.elements.progress = container; player.elements.progress = container;
@ -1318,11 +1335,11 @@
// Settings button / menu // Settings button / menu
if (inArray(config.controls, 'settings')) { if (inArray(config.controls, 'settings')) {
var wrapper = createElement('span', extend(getAttributesFromSelector(config.selectors.buttons.settings), { var menu = createElement('span', extend(getAttributesFromSelector(config.selectors.buttons.settings), {
class: 'plyr__menu' class: 'plyr__menu'
})); }));
wrapper.appendChild(createButton('settings', { menu.appendChild(createButton('settings', {
id: 'plyr-settings-toggle-' + data.id, id: 'plyr-settings-toggle-' + data.id,
'aria-haspopup': true, 'aria-haspopup': true,
'aria-controls': 'plyr-settings-' + data.id, 'aria-controls': 'plyr-settings-' + data.id,
@ -1378,6 +1395,8 @@
tab.appendChild(button); tab.appendChild(button);
tabs.appendChild(tab); tabs.appendChild(tab);
player.elements.settings.tabs[type] = tab;
}); });
home.appendChild(tabs); home.appendChild(tabs);
@ -1435,13 +1454,17 @@
pane.appendChild(options); pane.appendChild(options);
inner.appendChild(pane); inner.appendChild(pane);
player.elements.settings.panes[type] = pane;
}); });
form.appendChild(inner); form.appendChild(inner);
wrapper.appendChild(form); menu.appendChild(form);
controls.appendChild(wrapper); controls.appendChild(menu);
player.elements.settings.menu = menu;
/*html.push( /*html.push(
'<div class="plyr__menu" data-plyr="settings">', '<div class="plyr__menu" data-plyr="settings">',
@ -1732,7 +1755,7 @@
'</li>' '</li>'
].join('')); ].join(''));
getElement(config.selectors.menu.quality).innerHTML = list.join(''); player.elements.settings.panes.quality.innerHTML = list.join('');
} }
} }
@ -2549,7 +2572,8 @@
// Get the instance // Get the instance
var instance = event.target; var instance = event.target;
var quality = player.getPlaybackQuality(); // Get current quality
var quality = instance.getPlaybackQuality();
// var set = player.setPlaybackQuality(); // var set = player.setPlaybackQuality();
console.warn(quality); console.warn(quality);
@ -2560,30 +2584,30 @@
// Create a faux HTML5 API using the YouTube API // Create a faux HTML5 API using the YouTube API
player.elements.media.play = function() { player.elements.media.play = function() {
player.playVideo(); instance.playVideo();
player.elements.media.paused = false; player.elements.media.paused = false;
}; };
player.elements.media.pause = function() { player.elements.media.pause = function() {
player.pauseVideo(); instance.pauseVideo();
player.elements.media.paused = true; player.elements.media.paused = true;
}; };
player.elements.media.stop = function() { player.elements.media.stop = function() {
player.stopVideo(); instance.stopVideo();
player.elements.media.paused = true; player.elements.media.paused = true;
}; };
player.elements.media.duration = player.getDuration(); player.elements.media.duration = instance.getDuration();
player.elements.media.paused = true; player.elements.media.paused = true;
player.elements.media.currentTime = 0; player.elements.media.currentTime = 0;
player.elements.media.muted = player.isMuted(); player.elements.media.muted = instance.isMuted();
// Get available speeds // Get available speeds
var speed = player.getPlaybackRate(); var speed = instance.getPlaybackRate();
var speedOptions = player.getAvailablePlaybackRates(); var speedOptions = instance.getAvailablePlaybackRates();
//var set = player.setPlaybackRate(); //var set = instance.setPlaybackRate();
console.warn(speed, speedOptions); console.warn(speed, speedOptions);
// Set title // Set title
config.title = player.getVideoData().title; config.title = instance.getVideoData().title;
// Set the tabindex // Set the tabindex
if (player.supported.full) { if (player.supported.full) {
@ -2605,7 +2629,7 @@
// Setup buffering // Setup buffering
timers.buffering = window.setInterval(function() { timers.buffering = window.setInterval(function() {
// Get loaded % from YouTube // Get loaded % from YouTube
player.elements.media.buffered = player.getVideoLoadedFraction(); player.elements.media.buffered = instance.getVideoLoadedFraction();
// Trigger progress only when we actually buffer something // Trigger progress only when we actually buffer something
if (player.elements.media.lastBuffered === null || player.elements.media.lastBuffered < player.elements.media.buffered) { if (player.elements.media.lastBuffered === null || player.elements.media.lastBuffered < player.elements.media.buffered) {
@ -2659,7 +2683,7 @@
// Poll to get playback progress // Poll to get playback progress
timers.playing = window.setInterval(function() { timers.playing = window.setInterval(function() {
// Set the current time // Set the current time
player.elements.media.currentTime = player.getCurrentTime(); player.elements.media.currentTime = instance.getCurrentTime();
// Trigger timeupdate // Trigger timeupdate
trigger(player.elements.media, 'timeupdate'); trigger(player.elements.media, 'timeupdate');
@ -2668,14 +2692,14 @@
// Check duration again due to YouTube bug // Check duration again due to YouTube bug
// https://github.com/Selz/plyr/issues/374 // https://github.com/Selz/plyr/issues/374
// https://code.google.com/p/gdata-issues/issues/detail?id=8690 // https://code.google.com/p/gdata-issues/issues/detail?id=8690
if (player.elements.media.duration !== player.getDuration()) { if (player.elements.media.duration !== instance.getDuration()) {
player.elements.media.duration = player.getDuration(); player.elements.media.duration = instance.getDuration();
trigger(player.elements.media, 'durationchange'); trigger(player.elements.media, 'durationchange');
} }
// Get quality // Get quality
var qualityOptions = player.getAvailableQualityLevels(); var qualityOptions = instance.getAvailableQualityLevels();
var quality = player.getPlaybackQuality(); var quality = instance.getPlaybackQuality();
setQualityMenu(qualityOptions, quality); setQualityMenu(qualityOptions, quality);
break; break;
@ -2975,7 +2999,7 @@
} }
} }
// Speed-up // Set playback speed
function setSpeed(speed) { function setSpeed(speed) {
// Load speed from storage or default value // Load speed from storage or default value
if (is.undefined(speed)) { if (is.undefined(speed)) {
@ -3042,9 +3066,9 @@
// Seek to time // Seek to time
// The input parameter can be an event or a number // The input parameter can be an event or a number
function seek(input) { function seek(input) {
var targetTime = 0, var targetTime = 0;
paused = player.elements.media.paused, var paused = player.elements.media.paused;
duration = getDuration(); var duration = getDuration();
if (is.number(input)) { if (is.number(input)) {
targetTime = input; targetTime = input;
@ -3244,6 +3268,11 @@
var max = 10; var max = 10;
var min = 0; var min = 0;
// If volume is event, get from input
if (is.event(volume)) {
volume = volume.target.value;
}
// Load volume from storage if no value specified // Load volume from storage if no value specified
if (is.undefined(volume)) { if (is.undefined(volume)) {
volume = player.storage.volume; volume = player.storage.volume;
@ -3476,7 +3505,7 @@
mins = ('0' + mins).slice(-2); mins = ('0' + mins).slice(-2);
// Generate display // Generate display
var label = (displayHours ? hours + ':' : '') + mins + ':' + secs; var display = (displayHours ? hours + ':' : '') + mins + ':' + secs;
// Render // Render
element.textContent = display; element.textContent = display;
@ -3548,24 +3577,24 @@
var duration = getDuration(); var duration = getDuration();
// Bail if setting not true // Bail if setting not true
if (!config.tooltips.seek || !player.elements.progress.container || duration === 0) { if (!config.tooltips.seek || !is.htmlElement(player.elements.inputs.seek) || !is.htmlElement(player.elements.display.seekTooltip) || duration === 0) {
return; return;
} }
// Calculate percentage // Calculate percentage
var clientRect = player.elements.progress.container.getBoundingClientRect(), var clientRect = player.elements.inputs.seek.getBoundingClientRect();
percent = 0, var percent = 0;
visible = config.classes.tooltip + '--visible'; var visible = config.classes.tooltip + '--visible';
// Determine percentage, if already visible // Determine percentage, if already visible
if (!event) { if (is.event(event)) {
percent = ((100 / clientRect.width) * (event.pageX - clientRect.left));
} else {
if (hasClass(player.elements.display.seekTooltip, visible)) { if (hasClass(player.elements.display.seekTooltip, visible)) {
percent = player.elements.display.seekTooltip.style.left.replace('%', ''); percent = player.elements.display.seekTooltip.style.left.replace('%', '');
} else { } else {
return; return;
} }
} else {
percent = ((100 / clientRect.width) * (event.pageX - clientRect.left));
} }
// Set bounds // Set bounds
@ -3583,7 +3612,7 @@
// Show/hide the tooltip // Show/hide the tooltip
// If the event is a moues in/out and percentage is inside bounds // If the event is a moues in/out and percentage is inside bounds
if (event && inArray(['mouseenter', 'mouseleave'], event.type)) { if (is.event(event) && inArray(['mouseenter', 'mouseleave'], event.type)) {
toggleClass(player.elements.display.seekTooltip, visible, (event.type === 'mouseenter')); toggleClass(player.elements.display.seekTooltip, visible, (event.type === 'mouseenter'));
} }
} }
@ -3595,10 +3624,10 @@
return; return;
} }
var delay = 0, var delay = 0;
isEnterFullscreen = false, var isEnterFullscreen = false;
show = toggle, var show = toggle;
loading = hasClass(player.elements.container, config.classes.loading); var loading = hasClass(player.elements.container, config.classes.loading);
// Default to false if no boolean // Default to false if no boolean
if (!is.boolean(toggle)) { if (!is.boolean(toggle)) {
@ -4072,8 +4101,8 @@
// Focus/tab management // Focus/tab management
on(window, 'keyup', function(event) { on(window, 'keyup', function(event) {
var code = getKeyCode(event), var code = getKeyCode(event);
focused = getFocusElement(); var focused = getFocusElement();
if (code === 9) { if (code === 9) {
checkTabFocus(focused); checkTabFocus(focused);
@ -4090,6 +4119,16 @@
}); });
} }
// Trigger custom and default handlers
var handlerProxy = function(event, customHandler, defaultHandler) {
if (is.function(customHandler)) {
customHandler.call(this, event);
}
if (is.function(defaultHandler)) {
defaultHandler.call(this, event);
}
}
// Play // Play
proxy(player.elements.buttons.play, 'click', config.listeners.play, _togglePlay); proxy(player.elements.buttons.play, 'click', config.listeners.play, _togglePlay);
proxy(player.elements.buttons.playLarge, 'click', config.listeners.play, _togglePlay); proxy(player.elements.buttons.playLarge, 'click', config.listeners.play, _togglePlay);
@ -4097,61 +4136,33 @@
// Pause // Pause
proxy(player.elements.buttons.pause, 'click', config.listeners.pause, _togglePlay); proxy(player.elements.buttons.pause, 'click', config.listeners.pause, _togglePlay);
// Restart // Pause
proxy(player.elements.buttons.restart, 'click', config.listeners.restart, seek); proxy(player.elements.buttons.restart, 'click', config.listeners.restart, seek);
// Rewind // Rewind
proxy(player.elements.buttons.rewind, 'click', config.listeners.rewind, rewind); proxy(player.elements.buttons.rewind, 'click', config.listeners.rewind, rewind);
// Fast forward // Rewind
proxy(player.elements.buttons.forward, 'click', config.listeners.forward, forward); proxy(player.elements.buttons.forward, 'click', config.listeners.forward, forward);
// Speed-up
proxy(player.elements.buttons.speed, 'click', config.listeners.speed, function() {
//var speedValue = document.querySelector('[data-plyr="speed"]:checked').value;
//setSpeed(Number(speedValue));
});
// Seek
proxy(player.elements.inputs.seek, inputEvent, config.listeners.seek, seek);
// Set volume
proxy(player.elements.inputs.volume, inputEvent, config.listeners.volume, function() {
setVolume(player.elements.inputs.volume.value);
});
// Mute // Mute
proxy(player.elements.buttons.mute, 'click', config.listeners.mute, toggleMute); proxy(player.elements.buttons.mute, 'click', config.listeners.mute, toggleMute);
// Captions
proxy(player.elements.buttons.captions, 'click', config.listeners.captions, toggleCaptions);
// Fullscreen // Fullscreen
proxy(player.elements.buttons.fullscreen, 'click', config.listeners.fullscreen, toggleFullscreen); proxy(player.elements.buttons.fullscreen, 'click', config.listeners.fullscreen, toggleFullscreen);
// Looping // Picture-in-Picture
proxy(player.elements.buttons.loop, 'click', config.listeners.loop, function(event) { proxy(player.elements.buttons.pip, 'click', config.listeners.pip, function(event) {
var value = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type'); // TODO: Check support here
player.elements.media.webkitSetPresentationMode(player.elements.media.webkitPresentationMode === 'picture-in-picture' ? 'inline' : 'picture-in-picture');
if (inArray(['start', 'end', 'all', 'none'], value)) {
toggleLoop(value);
}
}); });
// Handle user exiting fullscreen by escaping etc // Settings menu
if (support.fullscreen) { on(player.elements.settings.menu, 'click', function(event) {
on(document, fullscreen.eventType, toggleFullscreen); // Settings menu
}
// Captions
proxy(player.elements.buttons.captions, 'click', config.listeners.captions, toggleCaptions);
// TODO: ??
// on(player.elements.buttons.captions_menu, 'click', toggleCaptions);
// Language
proxy(player.elements.buttons.lang, 'click', config.listeners.lang, function(e) {
var langIndex = e.target.attributes.getNamedItem("data-index").value;
setCaptionIndex(langIndex);
});
// Settings
on(player.elements.buttons.settings, 'click', function(event) {
var menu = this; var menu = this;
var toggle = event.target; var toggle = event.target;
var target = document.getElementById(toggle.getAttribute('aria-controls')); var target = document.getElementById(toggle.getAttribute('aria-controls'));
@ -4210,14 +4221,53 @@
} }
}); });
// Picture in picture // Settings menu items - use event delegation as items are added/removed
on(player.elements.buttons.pip, 'click', function() { on(player.elements.settings.menu, 'click', function(event) {
// TODO: Check support here // Settings - Speed
player.elements.media.webkitSetPresentationMode(player.elements.media.webkitPresentationMode === 'picture-in-picture' ? 'inline' : 'picture-in-picture'); if (matches(event.target, config.selectors.buttons.speed)) {
handlerProxy.call(this, event, config.listeners.speed, function() {
//var speedValue = document.querySelector('[data-plyr="speed"]:checked').value;
//setSpeed(Number(speedValue));
});
}
// Settings - Quality
else if (matches(event.target, config.selectors.buttons.quality)) {
handlerProxy.call(this, event, config.listeners.quality, function() {
console.warn("Set quality");
});
}
// Settings - Looping
else if (matches(event.target, config.selectors.buttons.loop)) {
handlerProxy.call(this, event, config.listeners.loop, function() {
// TODO: This should be done in the method itself I think
var value = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type');
if (inArray(['start', 'end', 'all', 'none'], value)) {
toggleLoop(value);
}
});
}
// Settings - Language
else if (matches(event.target, config.selectors.buttons.language)) {
handlerProxy.call(this, event, config.listeners.language, function(event) {
// TODO: This should be done in the method itself I think
var index = event.target.attributes.getNamedItem("data-index").value;
setCaptionIndex(index);
});
}
}); });
// Seek
proxy(player.elements.inputs.seek, inputEvent, config.listeners.seek, seek);
// Seek
proxy(player.elements.inputs.volume, inputEvent, config.listeners.volume, setVolume);
// Seek tooltip // Seek tooltip
on(player.elements.progress.container, 'mouseenter mouseleave mousemove', updateSeekTooltip); on(player.elements.progress, 'mouseenter mouseleave mousemove', updateSeekTooltip);
// Toggle controls visibility based on mouse movement // Toggle controls visibility based on mouse movement
if (config.hideControls) { if (config.hideControls) {
@ -4238,21 +4288,22 @@
on(player.elements.controls, 'focus blur', toggleControls, true); on(player.elements.controls, 'focus blur', toggleControls, true);
} }
// Adjust volume on scroll // Mouse wheel for volume
on(player.elements.inputs.volume, 'wheel', function(event) { proxy(player.elements.inputs.volume, 'wheel', config.listeners.volume, function(event) {
event.preventDefault();
// Detect "natural" scroll - suppored on OS X Safari only // Detect "natural" scroll - suppored on OS X Safari only
// Other browsers on OS X will be inverted until support improves // Other browsers on OS X will be inverted until support improves
var inverted = event.webkitDirectionInvertedFromDevice, var inverted = event.webkitDirectionInvertedFromDevice;
step = (1 / 5); var step = (1 / 5);
var direction = 0;
// Scroll down (or up on natural) to decrease // Scroll down (or up on natural) to decrease
if (event.deltaY < 0 || event.deltaX > 0) { if (event.deltaY < 0 || event.deltaX > 0) {
if (inverted) { if (inverted) {
decreaseVolume(step); decreaseVolume(step);
direction = -1;
} else { } else {
increaseVolume(step); increaseVolume(step);
direction = 1;
} }
} }
@ -4260,11 +4311,24 @@
if (event.deltaY > 0 || event.deltaX < 0) { if (event.deltaY > 0 || event.deltaX < 0) {
if (inverted) { if (inverted) {
increaseVolume(step); increaseVolume(step);
direction = 1;
} else { } else {
decreaseVolume(step); decreaseVolume(step);
direction = -1;
} }
} }
// Don't break page scrolling at max and min
if ((direction === 1 && player.elements.media.volume < 1) ||
(direction === -1 && player.elements.media.volume > 0)) {
event.preventDefault();
}
}); });
// Handle user exiting fullscreen by escaping etc
if (support.fullscreen) {
on(document, fullscreen.eventType, toggleFullscreen);
}
} }
// Listen for media events // Listen for media events