aboutsummaryrefslogtreecommitdiffstats
path: root/src/js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js')
-rw-r--r--src/js/controls.js47
-rw-r--r--src/js/listeners.js168
-rw-r--r--src/js/plugins/vimeo.js39
-rw-r--r--src/js/plugins/youtube.js21
-rw-r--r--src/js/plyr.js9
-rw-r--r--src/js/source.js2
-rw-r--r--src/js/ui.js48
-rw-r--r--src/js/utils.js18
8 files changed, 201 insertions, 151 deletions
diff --git a/src/js/controls.js b/src/js/controls.js
index 1e10f2f2..c95c6197 100644
--- a/src/js/controls.js
+++ b/src/js/controls.js
@@ -4,6 +4,7 @@
import support from './support';
import utils from './utils';
+import ui from './ui';
const controls = {
// Webkit polyfill for lower fill range
@@ -300,6 +301,52 @@ const controls = {
return container;
},
+ // Update hover tooltip for seeking
+ updateSeekTooltip(event) {
+ // Bail if setting not true
+ if (
+ !this.config.tooltips.seek ||
+ !utils.is.htmlElement(this.elements.inputs.seek) ||
+ !utils.is.htmlElement(this.elements.display.seekTooltip) ||
+ this.duration === 0
+ ) {
+ return;
+ }
+
+ // Calculate percentage
+ let percent = 0;
+ const clientRect = this.elements.inputs.seek.getBoundingClientRect();
+ const visible = `${this.config.classNames.tooltip}--visible`;
+
+ // Determine percentage, if already visible
+ if (utils.is.event(event)) {
+ percent = 100 / clientRect.width * (event.pageX - clientRect.left);
+ } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {
+ percent = this.elements.display.seekTooltip.style.left.replace('%', '');
+ } else {
+ return;
+ }
+
+ // Set bounds
+ if (percent < 0) {
+ percent = 0;
+ } else if (percent > 100) {
+ percent = 100;
+ }
+
+ // Display the time a click would seek to
+ ui.updateTimeDisplay.call(this, this.duration / 100 * percent, this.elements.display.seekTooltip);
+
+ // Set position
+ this.elements.display.seekTooltip.style.left = `${percent}%`;
+
+ // Show/hide the tooltip
+ // If the event is a moues in/out and percentage is inside bounds
+ if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {
+ utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter');
+ }
+ },
+
// Hide/show a tab
toggleTab(setting, toggle) {
const tab = this.elements.settings.tabs[setting];
diff --git a/src/js/listeners.js b/src/js/listeners.js
index f3746414..bc1a6094 100644
--- a/src/js/listeners.js
+++ b/src/js/listeners.js
@@ -360,61 +360,81 @@ const listeners = {
});
// Trigger custom and default handlers
- const handlerProxy = (event, customHandler, defaultHandler) => {
+ const proxy = (event, handlerKey, defaultHandler) => {
+ const customHandler = this.config.listeners[handleKey];
+
+ // Execute custom handler
if (utils.is.function(customHandler)) {
customHandler.call(this, event);
}
- if (utils.is.function(defaultHandler)) {
+
+ // Only call default handler if not prevented in custom handler
+ if (!event.defaultPrevented && utils.is.function(defaultHandler)) {
defaultHandler.call(this, event);
}
};
// Play
- utils.proxy(this.elements.buttons.play, 'click', this.config.listeners.play, togglePlay);
- utils.proxy(this.elements.buttons.playLarge, 'click', this.config.listeners.play, togglePlay);
+ utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay));
// Pause
- utils.proxy(this.elements.buttons.pause, 'click', this.config.listeners.pause, togglePlay);
+ utils.on(this.elements.buttons.pause, 'click', event => proxy(event, 'pause', togglePlay));
// Pause
- utils.proxy(this.elements.buttons.restart, 'click', this.config.listeners.restart, () => {
- this.restart();
- });
+ utils.on(this.elements.buttons.restart, 'click', event =>
+ proxy(event, 'restart', () => {
+ this.restart();
+ })
+ );
// Rewind
- utils.proxy(this.elements.buttons.rewind, 'click', this.config.listeners.rewind, () => {
- this.rewind();
- });
+ utils.on(this.elements.buttons.rewind, 'click', event =>
+ proxy(event, 'rewind', () => {
+ this.rewind();
+ })
+ );
// Rewind
- utils.proxy(this.elements.buttons.forward, 'click', this.config.listeners.forward, () => {
- this.forward();
- });
+ utils.on(this.elements.buttons.forward, 'click', event =>
+ proxy(event, 'forward', () => {
+ this.forward();
+ })
+ );
// Mute
- utils.proxy(this.elements.buttons.mute, 'click', this.config.listeners.mute, () => {
- this.toggleMute();
- });
+ utils.on(this.elements.buttons.mute, 'click', event =>
+ proxy(event, 'mute', () => {
+ this.toggleMute();
+ })
+ );
// Captions
- utils.proxy(this.elements.buttons.captions, 'click', this.config.listeners.captions, () => {
- this.toggleCaptions();
- });
+ utils.on(this.elements.buttons.captions, 'click', event =>
+ proxy(event, 'captions', () => {
+ this.toggleCaptions();
+ })
+ );
// Fullscreen
- utils.proxy(this.elements.buttons.fullscreen, 'click', this.config.listeners.fullscreen, () => {
- this.toggleFullscreen();
- });
+ utils.on(this.elements.buttons.fullscreen, 'click', event =>
+ proxy(event, 'fullscreen', () => {
+ this.toggleFullscreen();
+ })
+ );
// Picture-in-Picture
- utils.proxy(this.elements.buttons.pip, 'click', this.config.listeners.pip, () => {
- this.togglePictureInPicture();
- });
+ utils.on(this.elements.buttons.pip, 'click', event =>
+ proxy(event, 'pip', () => {
+ this.togglePictureInPicture();
+ })
+ );
// Airplay
- utils.proxy(this.elements.buttons.airplay, 'click', this.config.listeners.airplay, () => {
- this.airPlay();
- });
+ utils.on(this.elements.buttons.airplay, 'click', event =>
+ proxy(event, 'airplay', () => {
+ this.airPlay();
+ })
+ );
// Settings menu
utils.on(this.elements.buttons.settings, 'click', event => {
@@ -434,24 +454,24 @@ const listeners = {
// Settings menu items - use event delegation as items are added/removed
// Settings - Language
if (utils.matches(event.target, this.config.selectors.inputs.language)) {
- handlerProxy.call(this, event, this.config.listeners.language, () => {
+ proxy(event, 'language', () => {
this.toggleCaptions(true);
this.language = event.target.value.toLowerCase();
});
} else if (utils.matches(event.target, this.config.selectors.inputs.quality)) {
// Settings - Quality
- handlerProxy.call(this, event, this.config.listeners.quality, () => {
+ proxy(event, 'quality', () => {
this.quality = event.target.value;
});
} else if (utils.matches(event.target, this.config.selectors.inputs.speed)) {
// Settings - Speed
- handlerProxy.call(this, event, this.config.listeners.speed, () => {
+ proxy(event, 'speed', () => {
this.speed = parseFloat(event.target.value);
});
} else if (utils.matches(event.target, this.config.selectors.buttons.loop)) {
// Settings - Looping
// TODO: use toggle buttons
- handlerProxy.call(this, event, this.config.listeners.loop, () => {
+ proxy(event, 'loop', () => {
// 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');
@@ -461,14 +481,18 @@ const listeners = {
});
// Seek
- utils.proxy(this.elements.inputs.seek, inputEvent, this.config.listeners.seek, event => {
- this.currentTime = event.target.value / event.target.max * this.duration;
- });
+ utils.on(this.elements.inputs.seek, inputEvent, event =>
+ proxy(event, 'seek', () => {
+ this.currentTime = event.target.value / event.target.max * this.duration;
+ })
+ );
// Volume
- utils.proxy(this.elements.inputs.volume, inputEvent, this.config.listeners.volume, event => {
- this.volume = event.target.value;
- });
+ utils.on(this.elements.inputs.volume, inputEvent, event =>
+ proxy(event, 'volume', () => {
+ this.volume = event.target.value;
+ })
+ );
// Polyfill for lower fill in <input type="range"> for webkit
if (this.browser.isWebkit) {
@@ -479,7 +503,7 @@ const listeners = {
// Seek tooltip
utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event =>
- ui.updateSeekTooltip.call(this, event)
+ controls.updateSeekTooltip.call(this, event)
);
// Toggle controls visibility based on mouse movement
@@ -516,44 +540,44 @@ const listeners = {
}
// Mouse wheel for volume
- utils.proxy(
+ utils.on(
this.elements.inputs.volume,
'wheel',
- this.config.listeners.volume,
- event => {
- // Detect "natural" scroll - suppored on OS X Safari only
- // Other browsers on OS X will be inverted until support improves
- const inverted = event.webkitDirectionInvertedFromDevice;
- const step = 1 / 50;
- let direction = 0;
-
- // Scroll down (or up on natural) to decrease
- if (event.deltaY < 0 || event.deltaX > 0) {
- if (inverted) {
- this.decreaseVolume(step);
- direction = -1;
- } else {
- this.increaseVolume(step);
- direction = 1;
+ event =>
+ proxy(event, 'volume', () => {
+ // Detect "natural" scroll - suppored on OS X Safari only
+ // Other browsers on OS X will be inverted until support improves
+ const inverted = event.webkitDirectionInvertedFromDevice;
+ const step = 1 / 50;
+ let direction = 0;
+
+ // Scroll down (or up on natural) to decrease
+ if (event.deltaY < 0 || event.deltaX > 0) {
+ if (inverted) {
+ this.decreaseVolume(step);
+ direction = -1;
+ } else {
+ this.increaseVolume(step);
+ direction = 1;
+ }
}
- }
- // Scroll up (or down on natural) to increase
- if (event.deltaY > 0 || event.deltaX < 0) {
- if (inverted) {
- this.increaseVolume(step);
- direction = 1;
- } else {
- this.decreaseVolume(step);
- direction = -1;
+ // Scroll up (or down on natural) to increase
+ if (event.deltaY > 0 || event.deltaX < 0) {
+ if (inverted) {
+ this.increaseVolume(step);
+ direction = 1;
+ } else {
+ this.decreaseVolume(step);
+ direction = -1;
+ }
}
- }
- // Don't break page scrolling at max and min
- if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) {
- event.preventDefault();
- }
- },
+ // Don't break page scrolling at max and min
+ if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) {
+ event.preventDefault();
+ }
+ }),
false
);
diff --git a/src/js/plugins/vimeo.js b/src/js/plugins/vimeo.js
index 12632f64..34e326e7 100644
--- a/src/js/plugins/vimeo.js
+++ b/src/js/plugins/vimeo.js
@@ -77,6 +77,34 @@ const vimeo = {
player.media.paused = true;
player.media.currentTime = 0;
+ let { currentTime } = player.media;
+
+ // Seeking
+ Object.defineProperty(player.media, 'currentTime', {
+ get() {
+ return currentTime;
+ },
+ set(time) {
+ // Get current paused state
+ const { paused } = player.media;
+
+ player.warn('called');
+
+ // Set seeking flag
+ player.media.seeking = true;
+
+ // Trigger seeking
+ utils.dispatchEvent.call(player, player.media, 'seeking');
+
+ // Seek after events
+ player.embed.setCurrentTime(time);
+
+ // Restore pause state
+ if (paused) {
+ this.pause();
+ }
+ },
+ });
// Playback speed
// Not currently supported in Vimeo
@@ -88,10 +116,10 @@ const vimeo = {
});
// Rebuild UI
- ui.build.call(player);
+ window.setTimeout(() => ui.build.call(player), 0);
player.embed.getCurrentTime().then(value => {
- player.media.currentTime = value;
+ currentTime = value;
utils.dispatchEvent.call(this, this.media, 'timeupdate');
});
@@ -103,7 +131,6 @@ const vimeo = {
// Get captions
player.embed.getTextTracks().then(tracks => {
player.captions.tracks = tracks;
-
captions.setup.call(player);
});
@@ -121,10 +148,6 @@ const vimeo = {
if (utils.is.htmlElement(player.embed.element) && player.supported.ui) {
const frame = player.embed.element;
- // Fix Vimeo controls issue
- // https://github.com/sampotts/plyr/issues/697
- // frame.src = `${frame.src}&transparent=0`;
-
// Fix keyboard focus issues
// https://github.com/sampotts/plyr/issues/317
frame.setAttribute('tabindex', -1);
@@ -144,7 +167,7 @@ const vimeo = {
this.embed.on('timeupdate', data => {
this.media.seeking = false;
- this.media.currentTime = data.seconds;
+ currentTime = data.seconds;
utils.dispatchEvent.call(this, this.media, 'timeupdate');
});
diff --git a/src/js/plugins/youtube.js b/src/js/plugins/youtube.js
index 7d5c729c..ce21433e 100644
--- a/src/js/plugins/youtube.js
+++ b/src/js/plugins/youtube.js
@@ -118,6 +118,23 @@ const youtube = {
player.media.muted = instance.isMuted();
player.media.currentTime = 0;
+ // Seeking
+ Object.defineProperty(player.media, 'currentTime', {
+ get() {
+ return Number(instance.getCurrentTime());
+ },
+ set(time) {
+ // Set seeking flag
+ player.media.seeking = true;
+
+ // Trigger seeking
+ utils.dispatchEvent.call(player, player.media, 'seeking');
+
+ // Seek after events sent
+ instance.seekTo(time);
+ },
+ });
+
// Playback speed
Object.defineProperty(player.media, 'playbackRate', {
get() {
@@ -142,7 +159,7 @@ const youtube = {
}
// Rebuild UI
- ui.build.call(player);
+ window.setTimeout(() => ui.build.call(player), 0);
utils.dispatchEvent.call(player, player.media, 'timeupdate');
utils.dispatchEvent.call(player, player.media, 'durationchange');
@@ -218,7 +235,7 @@ const youtube = {
// Poll to get playback progress
player.timers.playing = window.setInterval(() => {
- player.media.currentTime = instance.getCurrentTime();
+ // player.media.currentTime = instance.getCurrentTime();
utils.dispatchEvent.call(player, player.media, 'timeupdate');
}, 100);
diff --git a/src/js/plyr.js b/src/js/plyr.js
index f98bef1a..60960d01 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -323,7 +323,7 @@ class Plyr {
// Set the current time
// TODO: This should be included in the "adapters"
// Embeds
- if (this.isEmbed) {
+ /* if (this.isEmbed) {
// Get current paused state
const { paused } = this.media;
@@ -351,8 +351,10 @@ class Plyr {
// Trigger seeking
utils.dispatchEvent.call(this, this.media, 'seeking');
} else {
- this.media.currentTime = targetTime.toFixed(4);
- }
+
+ } */
+
+ this.media.currentTime = targetTime.toFixed(4);
// Logging
this.log(`Seeking to ${this.currentTime} seconds`);
@@ -408,6 +410,7 @@ class Plyr {
this.media.volume = volume;
// Trigger volumechange for embeds
+ // TODO: Do in adapters
if (this.isEmbed) {
// Set media volume
switch (this.type) {
diff --git a/src/js/source.js b/src/js/source.js
index d2d5f61a..d0881675 100644
--- a/src/js/source.js
+++ b/src/js/source.js
@@ -16,8 +16,6 @@ const source = {
src: attributes,
});
} else if (utils.is.array(attributes)) {
- this.warn(attributes);
-
attributes.forEach(attribute => {
utils.insertElement(type, this.media, attribute);
});
diff --git a/src/js/ui.js b/src/js/ui.js
index 2d612cdb..1ec58d29 100644
--- a/src/js/ui.js
+++ b/src/js/ui.js
@@ -114,7 +114,7 @@ const ui = {
}
// Update the tooltip (if visible)
- ui.updateSeekTooltip.call(this);
+ controls.updateSeekTooltip.call(this);
},
// Setup aria attribute for play and iframe title
@@ -330,52 +330,6 @@ const ui = {
// Playing progress
ui.updateProgress.call(this, event);
},
-
- // Update hover tooltip for seeking
- updateSeekTooltip(event) {
- // Bail if setting not true
- if (
- !this.config.tooltips.seek ||
- !utils.is.htmlElement(this.elements.inputs.seek) ||
- !utils.is.htmlElement(this.elements.display.seekTooltip) ||
- this.duration === 0
- ) {
- return;
- }
-
- // Calculate percentage
- const clientRect = this.elements.inputs.seek.getBoundingClientRect();
- let percent = 0;
- const visible = `${this.config.classNames.tooltip}--visible`;
-
- // Determine percentage, if already visible
- if (utils.is.event(event)) {
- percent = 100 / clientRect.width * (event.pageX - clientRect.left);
- } else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {
- percent = this.elements.display.seekTooltip.style.left.replace('%', '');
- } else {
- return;
- }
-
- // Set bounds
- if (percent < 0) {
- percent = 0;
- } else if (percent > 100) {
- percent = 100;
- }
-
- // Display the time a click would seek to
- ui.updateTimeDisplay.call(this, this.duration / 100 * percent, this.elements.display.seekTooltip);
-
- // Set position
- this.elements.display.seekTooltip.style.left = `${percent}%`;
-
- // Show/hide the tooltip
- // If the event is a moues in/out and percentage is inside bounds
- if (utils.is.event(event) && ['mouseenter', 'mouseleave'].includes(event.type)) {
- utils.toggleClass(this.elements.display.seekTooltip, visible, event.type === 'mouseenter');
- }
- },
};
export default ui;
diff --git a/src/js/utils.js b/src/js/utils.js
index e81954f4..4296f345 100644
--- a/src/js/utils.js
+++ b/src/js/utils.js
@@ -391,22 +391,6 @@ const utils = {
);
},
- // Bind along with custom handler
- proxy(element, eventName, customListener, defaultListener, passive, capture) {
- utils.on(
- element,
- eventName,
- event => {
- if (customListener) {
- customListener.apply(element, [event]);
- }
- defaultListener.apply(element, [event]);
- },
- passive,
- capture
- );
- },
-
// Toggle event listener
toggleListener(elements, event, callback, toggle, passive, capture) {
// Bail if no elements
@@ -415,7 +399,7 @@ const utils = {
}
// If a nodelist is passed, call itself on each node
- if (elements instanceof NodeList) {
+ if (utils.is.nodeList(elements)) {
// Create listener for each node
Array.from(elements).forEach(element => {
if (element instanceof Node) {