Play button as toggle button, tooltip changes, docs updated, fullscreen fix

This commit is contained in:
Sam Potts 2017-11-21 13:12:36 +11:00
parent 92cd67effb
commit edfc6cd475
14 changed files with 125 additions and 140 deletions

2
demo/dist/demo.css vendored

File diff suppressed because one or more lines are too long

View File

@ -40,21 +40,25 @@
<h1>Plyr</h1> <h1>Plyr</h1>
<p>A simple, accessible and customisable media player for <p>A simple, accessible and customisable media player for
<button type="button" class="faux-link" data-source="video"> <button type="button" class="faux-link" data-source="video">
<svg class="icon" title="HTML5"> <svg class="icon">
<title>HTML5</title>
<path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path>
</svg>Video</button>, </svg>Video</button>,
<button type="button" class="faux-link" data-source="audio"> <button type="button" class="faux-link" data-source="audio">
<svg class="icon" title="HTML5"> <svg class="icon">
<title>HTML5</title>
<path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path>
</svg>Audio</button>, </svg>Audio</button>,
<button type="button" class="faux-link" data-source="youtube"> <button type="button" class="faux-link" data-source="youtube">
<svg class="icon" title="YouTube"> <svg class="icon" role="presentation">
<title>YouTube</title>
<path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 <path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8
s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z
M6,11V5l5,3L6,11z"></path> M6,11V5l5,3L6,11z"></path>
</svg>YouTube</button> and </svg>YouTube</button> and
<button type="button" class="faux-link" data-source="vimeo"> <button type="button" class="faux-link" data-source="vimeo">
<svg class="icon" title="Vimeo"> <svg class="icon" role="presentation">
<title>Vimeo</title>
<path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 <path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5
C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4 C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4
c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path> c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path>
@ -63,7 +67,7 @@
<span class="action"> <span class="action">
<a href="https://github.com/sampotts/plyr" target="_blank" class="button" data-shr-network="github"> <a href="https://github.com/sampotts/plyr" target="_blank" class="button" data-shr-network="github">
<svg class="icon"> <svg class="icon" role="presentation">
<title>GitHub</title> <title>GitHub</title>
<path d="M8,0.2c-4.4,0-8,3.6-8,8c0,3.5,2.3,6.5,5.5,7.6 <path d="M8,0.2c-4.4,0-8,3.6-8,8c0,3.5,2.3,6.5,5.5,7.6
C5.9,15.9,6,15.6,6,15.4c0-0.2,0-0.7,0-1.4C3.8,14.5,3.3,13,3.3,13c-0.4-0.9-0.9-1.2-0.9-1.2c-0.7-0.5,0.1-0.5,0.1-0.5 C5.9,15.9,6,15.6,6,15.4c0-0.2,0-0.7,0-1.4C3.8,14.5,3.3,13,3.3,13c-0.4-0.9-0.9-1.2-0.9-1.2c-0.7-0.5,0.1-0.5,0.1-0.5
@ -94,7 +98,8 @@
<ul> <ul>
<li class="plyr__cite plyr__cite--video" hidden> <li class="plyr__cite plyr__cite--video" hidden>
<small> <small>
<svg class="icon" title="HTML5"> <svg class="icon">
<title>HTML5</title>
<path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path>
</svg> </svg>
<a href="http://viewfromabluemoon.com/" target="_blank">View From A Blue Moon</a> &copy; Brainfarm <a href="http://viewfromabluemoon.com/" target="_blank">View From A Blue Moon</a> &copy; Brainfarm
@ -103,6 +108,7 @@
<li class="plyr__cite plyr__cite--audio" hidden> <li class="plyr__cite plyr__cite--audio" hidden>
<small> <small>
<svg class="icon" title="HTML5"> <svg class="icon" title="HTML5">
<title>HTML5</title>
<path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path> <path d="M14.738.326C14.548.118 14.28 0 14 0H2c-.28 0-.55.118-.738.326S.98.81 1.004 1.09l1 11c.03.317.208.603.48.767l5 3c.16.095.338.143.516.143s.356-.048.515-.143l5-3c.273-.164.452-.45.48-.767l1-11c.026-.28-.067-.557-.257-.764zM12 4H6v2h6v5.72l-4 1.334-4-1.333V9h2v1.28l2 .666 2-.667V8H4V2h8v2z"></path>
</svg> </svg>
<a href="http://www.kishibashi.com/" target="_blank">Kishi Bashi &ndash; &ldquo;It All Began With A Burst&rdquo;</a> &copy; Kishi Bashi <a href="http://www.kishibashi.com/" target="_blank">Kishi Bashi &ndash; &ldquo;It All Began With A Burst&rdquo;</a> &copy; Kishi Bashi
@ -112,7 +118,8 @@
<small> <small>
<a href="https://www.youtube.com/watch?v=bTqVqk7FSmY" target="_blank">View From A Blue Moon</a> on&nbsp; <a href="https://www.youtube.com/watch?v=bTqVqk7FSmY" target="_blank">View From A Blue Moon</a> on&nbsp;
<span class="color--youtube"> <span class="color--youtube">
<svg class="icon" title="YouTube"> <svg class="icon" role="presentation">
<title>YouTube</title>
<path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8 <path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8
s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z
M6,11V5l5,3L6,11z"></path> M6,11V5l5,3L6,11z"></path>
@ -124,7 +131,8 @@
<small> <small>
<a href="https://vimeo.com/ondemand/viewfromabluemoon4k" target="_blank">View From A Blue Moon</a> on&nbsp; <a href="https://vimeo.com/ondemand/viewfromabluemoon4k" target="_blank">View From A Blue Moon</a> on&nbsp;
<span class="color--vimeo"> <span class="color--vimeo">
<svg class="icon" title="Vimeo"> <svg class="icon" role="presentation">
<title>Vimeo</title>
<path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5 <path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5
C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4 C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4
c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path> c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"></path>

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

2
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

2
dist/plyr.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -224,7 +224,7 @@ Option | Type | Default | Description
`debug` | Boolean | `false` | Display debugging information in the console `debug` | Boolean | `false` | Display debugging information in the console
`controls` | Function or Array | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return a string of HTML for the controls. Three arguments will be passed to your function; id (the unique id for the player), seektime (the seektime step in seconds), and title (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured. `controls` | Function or Array | `['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'settings', 'pip', 'airplay', 'fullscreen']` | If a function is passed, it is assumed your method will return a string of HTML for the controls. Three arguments will be passed to your function; id (the unique id for the player), seektime (the seektime step in seconds), and title (the media title). See [controls.md](controls.md) for more info on how the html needs to be structured.
`settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu `settings` | Array | `['captions', 'quality', 'speed', 'loop']` | If you're using the default controls are used then you can specify which settings to show in the menu
`i18n` | Object | See [defaults.js](/src/js/defaults.js) | Used for internationalization (i18n) of the tooltips/labels within the buttons. `i18n` | Object | See [defaults.js](/src/js/defaults.js) | Used for internationalization (i18n) of the text within the UI.
`loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself. `loadSprite` | Boolean | `true` | Load the SVG sprite specified as the `iconUrl` option (if a URL). If `false`, it is assumed you are handling sprite loading yourself.
`iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info. `iconUrl` | String | `null` | Specify a URL or path to the SVG sprite. See the [SVG section](#svg) for more info.
`iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option. `iconPrefix` | String | `plyr` | Specify the id prefix for the icons used in the default controls (e.g. "plyr-play" would be "plyr"). This is to prevent clashes if you're using your own SVG sprite but with the default controls. Most people can ignore this option.
@ -280,12 +280,6 @@ An example method:
player.pause(); player.pause();
``` ```
Methods are chainable so you can do the following:
```javascript
player.restart().play();
```
Method | Parameters | Description Method | Parameters | Description
-------- | ---------- | ----------- -------- | ---------- | -----------
`play()` | - | Start playback. `play()` | - | Start playback.
@ -325,6 +319,8 @@ Property | Getter | Setter | Description
`isHTML5` | ✔ | - | Returns a boolean indicating if the current player is HTML5. `isHTML5` | ✔ | - | Returns a boolean indicating if the current player is HTML5.
`isEmbed` | ✔ | - | Returns a boolean indicating if the current player is an embedded player. `isEmbed` | ✔ | - | Returns a boolean indicating if the current player is an embedded player.
`paused` | ✔ | - | Returns a boolean indicating if the current player is paused. `paused` | ✔ | - | Returns a boolean indicating if the current player is paused.
`playing` | ✔ | - | Returns a boolean indicating if the current player is playing.
`ended` | ✔ | - | Returns a boolean indicating if the current player has finished playback.
`currentTime` | ✔ | ✔ | Gets or sets the currentTime for the player. The setter accepts a float in seconds. `currentTime` | ✔ | ✔ | Gets or sets the currentTime for the player. The setter accepts a float in seconds.
`seeking` | ✔ | - | Returns a boolean indicating if the current player is seeking. `seeking` | ✔ | - | Returns a boolean indicating if the current player is seeking.
`duration` | ✔ | - | Returns the duration for the current media. `duration` | ✔ | - | Returns the duration for the current media.
@ -465,7 +461,7 @@ Event Type | Description
`seeking` | Sent when a seek operation begins. `seeking` | Sent when a seek operation begins.
`seeked` | Sent when a seek operation completes. `seeked` | Sent when a seek operation completes.
`ratechange` | Sent when the playback speed changes. `ratechange` | Sent when the playback speed changes.
`ended` | Sent when playback completes. `ended` | Sent when playback completes. *Note:* This does not fire if `autoplay` is true.
`enterfullscreen` | Sent when the player enters fullscreen mode (either the proper fullscreen or full-window fallback for older browsers). `enterfullscreen` | Sent when the player enters fullscreen mode (either the proper fullscreen or full-window fallback for older browsers).
`exitfullscreen` | Sent when the player exits fullscreen mode. `exitfullscreen` | Sent when the player exits fullscreen mode.
`captionsenabled` | Sent when captions are enabled. `captionsenabled` | Sent when captions are enabled.

111
src/js/controls.js vendored
View File

@ -92,8 +92,9 @@ const controls = {
}, },
// Create hidden text label // Create hidden text label
createLabel(type) { createLabel(type, attr) {
let text = this.config.i18n[type]; let text = this.config.i18n[type];
const attributes = Object.assign({}, attr);
switch (type) { switch (type) {
case 'pip': case 'pip':
@ -108,13 +109,13 @@ const controls = {
break; break;
} }
return utils.createElement( if ('class' in attributes) {
'span', attributes.class += ` ${this.config.classNames.hidden}`;
{ } else {
class: this.config.classNames.hidden, attributes.class = this.config.classNames.hidden;
}, }
text
); return utils.createElement('span', attributes, text);
}, },
// Create a badge // Create a badge
@ -145,16 +146,19 @@ const controls = {
const button = utils.createElement('button'); const button = utils.createElement('button');
const attributes = Object.assign({}, attr); const attributes = Object.assign({}, attr);
let type = buttonType; let type = buttonType;
let iconDefault;
let iconToggled; let toggle = false;
let labelKey; let label;
let icon;
let labelPressed;
let iconPressed;
if (!('type' in attributes)) { if (!('type' in attributes)) {
attributes.type = 'button'; attributes.type = 'button';
} }
if ('class' in attributes) { if ('class' in attributes) {
if (attributes.class.indexOf(this.config.classNames.control) === -1) { if (attributes.class.includes(this.config.classNames.control)) {
attributes.class += ` ${this.config.classNames.control}`; attributes.class += ` ${this.config.classNames.control}`;
} }
} else { } else {
@ -163,57 +167,71 @@ const controls = {
// Large play button // Large play button
switch (type) { switch (type) {
case 'play':
toggle = true;
label = 'play';
labelPressed = 'pause';
icon = 'play';
iconPressed = 'pause';
break;
case 'mute': case 'mute':
labelKey = 'toggleMute'; toggle = true;
iconDefault = 'volume'; label = 'mute';
iconToggled = 'muted'; labelPressed = 'unmute';
icon = 'volume';
iconPressed = 'muted';
break; break;
case 'captions': case 'captions':
labelKey = 'toggleCaptions'; toggle = true;
iconDefault = 'captions-off'; label = 'enableCaptions';
iconToggled = 'captions-on'; labelPressed = 'disableCaptions';
icon = 'captions-off';
iconPressed = 'captions-on';
break; break;
case 'fullscreen': case 'fullscreen':
labelKey = 'toggleFullscreen'; toggle = true;
iconDefault = 'enter-fullscreen'; label = 'enterFullscreen';
iconToggled = 'exit-fullscreen'; labelPressed = 'exitFullscreen';
icon = 'enter-fullscreen';
iconPressed = 'exit-fullscreen';
break; break;
case 'play-large': case 'play-large':
attributes.class = 'plyr__play-large'; attributes.class += ` ${this.config.classNames.control}--overlaid`;
type = 'play'; type = 'play';
labelKey = 'play'; label = 'play';
iconDefault = 'play'; icon = 'play';
break; break;
default: default:
labelKey = type; label = type;
iconDefault = type; icon = type;
}
// Setup toggle icon and labels
if (toggle) {
// Icon
button.appendChild(controls.createIcon.call(this, iconPressed, { class: 'icon--pressed' }));
button.appendChild(controls.createIcon.call(this, icon, { class: 'icon--not-pressed' }));
// Label/Tooltip
button.appendChild(controls.createLabel.call(this, labelPressed, { class: 'label--pressed' }));
button.appendChild(controls.createLabel.call(this, label, { class: 'label--not-pressed' }));
// Add aria attributes
attributes['aria-pressed'] = false;
attributes['aria-label'] = this.config.i18n[label];
} else {
button.appendChild(controls.createIcon.call(this, icon));
button.appendChild(controls.createLabel.call(this, label));
} }
// Merge attributes // Merge attributes
utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes)); utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes));
// Add toggle icon if needed
if (utils.is.string(iconToggled)) {
button.appendChild(
controls.createIcon.call(this, iconToggled, {
class: 'icon--pressed',
})
);
button.appendChild(
controls.createIcon.call(this, iconDefault, {
class: 'icon--not-pressed',
})
);
} else {
button.appendChild(controls.createIcon.call(this, iconDefault));
}
button.appendChild(controls.createLabel.call(this, labelKey));
utils.setAttributes(button, attributes); utils.setAttributes(button, attributes);
this.elements.buttons[type] = button; this.elements.buttons[type] = button;
@ -909,10 +927,10 @@ const controls = {
container.appendChild(controls.createButton.call(this, 'rewind')); container.appendChild(controls.createButton.call(this, 'rewind'));
} }
// Play Pause button // Play/Pause button
if (this.config.controls.includes('play')) { if (this.config.controls.includes('play')) {
container.appendChild(controls.createButton.call(this, 'play')); container.appendChild(controls.createButton.call(this, 'play'));
container.appendChild(controls.createButton.call(this, 'pause')); // container.appendChild(controls.createButton.call(this, 'pause'));
} }
// Fast forward button // Fast forward button
@ -1233,6 +1251,7 @@ const controls = {
Array.from(labels).forEach(label => { Array.from(labels).forEach(label => {
utils.toggleClass(label, this.config.classNames.hidden, false); utils.toggleClass(label, this.config.classNames.hidden, false);
utils.toggleClass(label, this.config.classNames.tooltip, true); utils.toggleClass(label, this.config.classNames.tooltip, true);
label.setAttribute('role', 'tooltip');
}); });
} }
}, },

View File

@ -133,9 +133,13 @@ const defaults = {
currentTime: 'Current time', currentTime: 'Current time',
duration: 'Duration', duration: 'Duration',
volume: 'Volume', volume: 'Volume',
toggleMute: 'Toggle Mute', mute: 'Mute',
toggleCaptions: 'Toggle Captions', unmute: 'Unmute',
toggleFullscreen: 'Toggle Fullscreen', enableCaptions: 'Enable captions',
disableCaptions: 'Disable captions',
fullscreen: 'Fullscreen',
enterFullscreen: 'Enter fullscreen',
exitFullscreen: 'Exit fullscreen',
frameTitle: 'Player for {title}', frameTitle: 'Player for {title}',
captions: 'Captions', captions: 'Captions',
settings: 'Settings', settings: 'Settings',

View File

@ -217,11 +217,11 @@ const listeners = {
} }
// Handle user exiting fullscreen by escaping etc // Handle user exiting fullscreen by escaping etc
/* if (fullscreen.enabled) { if (fullscreen.enabled) {
utils.on(document, fullscreen.eventType, event => { utils.on(document, fullscreen.eventType, event => {
this.toggleFullscreen(event); this.toggleFullscreen(event);
}); });
} */ }
}, },
// Listen for media events // Listen for media events
@ -372,24 +372,12 @@ const listeners = {
} }
}; };
// Click play/pause helper // Play/pause toggle
const togglePlay = () => { utils.on(this.elements.buttons.play, 'click', event =>
const play = this.togglePlay(); proxy(event, 'play', () => {
this.togglePlay();
// Determine which buttons })
const target = this.elements.buttons[play ? 'pause' : 'play']; );
// Transfer focus
if (utils.is.htmlElement(target)) {
target.focus();
}
};
// Play
utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay));
// Pause
utils.on(this.elements.buttons.pause, 'click', event => proxy(event, 'pause', togglePlay));
// Pause // Pause
utils.on(this.elements.buttons.restart, 'click', event => utils.on(this.elements.buttons.restart, 'click', event =>
@ -412,21 +400,21 @@ const listeners = {
}) })
); );
// Mute // Mute toggle
utils.on(this.elements.buttons.mute, 'click', event => utils.on(this.elements.buttons.mute, 'click', event =>
proxy(event, 'mute', () => { proxy(event, 'mute', () => {
this.muted = !this.muted; this.muted = !this.muted;
}) })
); );
// Captions // Captions toggle
utils.on(this.elements.buttons.captions, 'click', event => utils.on(this.elements.buttons.captions, 'click', event =>
proxy(event, 'captions', () => { proxy(event, 'captions', () => {
this.toggleCaptions(); this.toggleCaptions();
}) })
); );
// Fullscreen // Fullscreen toggle
utils.on(this.elements.buttons.fullscreen, 'click', event => utils.on(this.elements.buttons.fullscreen, 'click', event =>
proxy(event, 'fullscreen', () => { proxy(event, 'fullscreen', () => {
this.toggleFullscreen(); this.toggleFullscreen();

View File

@ -710,22 +710,17 @@ class Plyr {
toggleFullscreen(event) { toggleFullscreen(event) {
// Check for native support // Check for native support
if (fullscreen.enabled) { if (fullscreen.enabled) {
// If it's a fullscreen change event, update the UI
if (utils.is.event(event) && event.type === fullscreen.eventType) { if (utils.is.event(event) && event.type === fullscreen.eventType) {
// If it's a fullscreen change event, update the state
this.fullscreen.active = fullscreen.isFullScreen(this.elements.container); this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);
} else { } else {
// Else it's a user request to enter or exit // Else it's a user request to enter or exit
if (!this.fullscreen.active) { if (!this.fullscreen.active) {
// Request full screen
fullscreen.requestFullScreen(this.elements.container); fullscreen.requestFullScreen(this.elements.container);
} else { } else {
// Bail from fullscreen
fullscreen.cancelFullScreen(); fullscreen.cancelFullScreen();
} }
// Check if we're actually full screen (it could fail)
this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);
return this; return this;
} }
} else { } else {
@ -754,7 +749,7 @@ class Plyr {
} }
// Set button state // Set button state
if (this.elements.buttons && this.elements.buttons.fullscreen) { if (utils.is.htmlElement(this.elements.buttons.fullscreen)) {
utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active); utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active);
} }

View File

@ -139,10 +139,14 @@ const ui = {
// Check playing state // Check playing state
checkPlaying() { checkPlaying() {
window.setTimeout(() => { window.setTimeout(() => {
// Class hooks
utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing); utils.toggleClass(this.elements.container, this.config.classNames.playing, this.playing);
utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused); utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);
// Set aria state
Array.from(this.elements.buttons.play).forEach(button => utils.toggleState(button, this.playing));
// Toggle controls
this.toggleControls(!this.playing); this.toggleControls(!this.playing);
}, 100); }, 100);
}, },

View File

@ -20,11 +20,6 @@
pointer-events: none; pointer-events: none;
} }
// Hide toggle icons by default
.icon--pressed {
display: none;
}
// Default focus // Default focus
&:focus { &:focus {
outline: 0; outline: 0;
@ -37,10 +32,10 @@
} }
// Change icons on state change // Change icons on state change
.plyr__control[aria-pressed='true'] .icon--pressed { .plyr__control[aria-pressed='false'] .icon--pressed,
display: block; .plyr__control[aria-pressed='true'] .icon--not-pressed,
} .plyr__control[aria-pressed='false'] .label--pressed,
.plyr__control[aria-pressed='true'] .icon--not-pressed { .plyr__control[aria-pressed='true'] .label--not-pressed {
display: none; display: none;
} }
@ -55,7 +50,7 @@
} }
// Large play button (video only) // Large play button (video only)
.plyr__play-large { .plyr__control--overlaid {
display: none; display: none;
position: absolute; position: absolute;
z-index: 3; z-index: 3;
@ -68,37 +63,25 @@
border-radius: 100%; border-radius: 100%;
box-shadow: 0 1px 1px fade(#000, 15%); box-shadow: 0 1px 1px fade(#000, 15%);
color: @plyr-video-control-color; color: @plyr-video-control-color;
transition: all 0.3s ease;
svg { svg {
position: relative; position: relative;
left: 2px; left: 2px;
width: 20px; width: @plyr-control-icon-size-large;
height: 20px; height: @plyr-control-icon-size-large;
display: block;
fill: currentColor;
pointer-events: none;
} }
&:hover, &:hover,
&:focus { &:focus {
background: @plyr-video-control-bg-hover; background: @plyr-video-control-bg-hover;
} }
&:focus {
outline: 0;
} }
&.plyr__tab-focus { .plyr--full-ui.plyr--video .plyr__control--overlaid {
.plyr-tab-focus();
}
}
.plyr--full-ui.plyr--video .plyr__play-large {
display: inline-block; display: inline-block;
} }
.plyr--playing .plyr__play-large { .plyr--playing .plyr__control--overlaid {
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
} }

View File

@ -91,17 +91,6 @@
color: @plyr-audio-control-color; color: @plyr-audio-control-color;
} }
// States
.plyr__controls [data-plyr='pause'] {
display: none;
}
.plyr--playing .plyr__controls [data-plyr='play'] {
display: none;
}
.plyr--playing .plyr__controls [data-plyr='pause'] {
display: inline-block;
}
// Some options are hidden by default // Some options are hidden by default
.plyr [data-plyr='captions'], .plyr [data-plyr='captions'],
.plyr [data-plyr='pip'], .plyr [data-plyr='pip'],

View File

@ -17,12 +17,9 @@
@plyr-font-size-small: 14px; @plyr-font-size-small: 14px;
@plyr-font-size-time: 14px; @plyr-font-size-time: 14px;
@plyr-font-size-badge: 10px; @plyr-font-size-badge: 10px;
@plyr-font-weight-regular: 500; @plyr-font-weight-regular: 500;
@plyr-font-weight-bold: 600; @plyr-font-weight-bold: 600;
@plyr-line-height: 1.7; @plyr-line-height: 1.7;
@plyr-font-smoothing: on; @plyr-font-smoothing: on;
// Focus // Focus
@ -38,6 +35,7 @@
// Controls // Controls
@plyr-control-icon-size: 18px; @plyr-control-icon-size: 18px;
@plyr-control-icon-size-large: 20px;
@plyr-control-spacing: 10px; @plyr-control-spacing: 10px;
@plyr-control-padding: (@plyr-control-spacing * 0.7); @plyr-control-padding: (@plyr-control-spacing * 0.7);
@plyr-video-controls-bg: #000; @plyr-video-controls-bg: #000;
@ -49,6 +47,7 @@
@plyr-audio-control-color: #565d64; @plyr-audio-control-color: #565d64;
@plyr-audio-control-color-hover: #fff; @plyr-audio-control-color-hover: #fff;
@plyr-audio-control-bg-hover: @plyr-color-main; @plyr-audio-control-bg-hover: @plyr-color-main;
// Tooltips // Tooltips
@plyr-tooltip-bg: fade(#fff, 90%); @plyr-tooltip-bg: fade(#fff, 90%);
@plyr-tooltip-color: #565d64; @plyr-tooltip-color: #565d64;