Utils broken down into seperate files and exports
This commit is contained in:
320
src/js/controls.js
vendored
320
src/js/controls.js
vendored
@ -6,14 +6,17 @@ import captions from './captions';
|
||||
import html5 from './html5';
|
||||
import i18n from './i18n';
|
||||
import support from './support';
|
||||
import utils from './utils';
|
||||
|
||||
// Sniff out the browser
|
||||
const browser = utils.getBrowser();
|
||||
import { repaint, transitionEndEvent } from './utils/animation';
|
||||
import browser from './utils/browser';
|
||||
import { createElement, emptyElement, getAttributesFromSelector, getElement, getElements, hasClass, removeElement, setAttributes, toggleClass, toggleHidden, toggleState } from './utils/elements';
|
||||
import { off, on } from './utils/events';
|
||||
import is from './utils/is';
|
||||
import loadSprite from './utils/loadSprite';
|
||||
import { extend } from './utils/objects';
|
||||
import { getPercentage, replaceAll, toCamelCase, toTitleCase } from './utils/strings';
|
||||
import { formatTime, getHours } from './utils/time';
|
||||
|
||||
const controls = {
|
||||
|
||||
|
||||
// Get icon URL
|
||||
getIconUrl() {
|
||||
const url = new URL(this.config.iconUrl, window.location);
|
||||
@ -29,41 +32,41 @@ const controls = {
|
||||
// TODO: Allow settings menus with custom controls
|
||||
findElements() {
|
||||
try {
|
||||
this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);
|
||||
this.elements.controls = getElement.call(this, this.config.selectors.controls.wrapper);
|
||||
|
||||
// Buttons
|
||||
this.elements.buttons = {
|
||||
play: utils.getElements.call(this, this.config.selectors.buttons.play),
|
||||
pause: utils.getElement.call(this, this.config.selectors.buttons.pause),
|
||||
restart: utils.getElement.call(this, this.config.selectors.buttons.restart),
|
||||
rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),
|
||||
fastForward: utils.getElement.call(this, this.config.selectors.buttons.fastForward),
|
||||
mute: utils.getElement.call(this, this.config.selectors.buttons.mute),
|
||||
pip: utils.getElement.call(this, this.config.selectors.buttons.pip),
|
||||
airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),
|
||||
settings: utils.getElement.call(this, this.config.selectors.buttons.settings),
|
||||
captions: utils.getElement.call(this, this.config.selectors.buttons.captions),
|
||||
fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),
|
||||
play: getElements.call(this, this.config.selectors.buttons.play),
|
||||
pause: getElement.call(this, this.config.selectors.buttons.pause),
|
||||
restart: getElement.call(this, this.config.selectors.buttons.restart),
|
||||
rewind: getElement.call(this, this.config.selectors.buttons.rewind),
|
||||
fastForward: getElement.call(this, this.config.selectors.buttons.fastForward),
|
||||
mute: getElement.call(this, this.config.selectors.buttons.mute),
|
||||
pip: getElement.call(this, this.config.selectors.buttons.pip),
|
||||
airplay: getElement.call(this, this.config.selectors.buttons.airplay),
|
||||
settings: getElement.call(this, this.config.selectors.buttons.settings),
|
||||
captions: getElement.call(this, this.config.selectors.buttons.captions),
|
||||
fullscreen: getElement.call(this, this.config.selectors.buttons.fullscreen),
|
||||
};
|
||||
|
||||
// Progress
|
||||
this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);
|
||||
this.elements.progress = getElement.call(this, this.config.selectors.progress);
|
||||
|
||||
// Inputs
|
||||
this.elements.inputs = {
|
||||
seek: utils.getElement.call(this, this.config.selectors.inputs.seek),
|
||||
volume: utils.getElement.call(this, this.config.selectors.inputs.volume),
|
||||
seek: getElement.call(this, this.config.selectors.inputs.seek),
|
||||
volume: getElement.call(this, this.config.selectors.inputs.volume),
|
||||
};
|
||||
|
||||
// Display
|
||||
this.elements.display = {
|
||||
buffer: utils.getElement.call(this, this.config.selectors.display.buffer),
|
||||
currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),
|
||||
duration: utils.getElement.call(this, this.config.selectors.display.duration),
|
||||
buffer: getElement.call(this, this.config.selectors.display.buffer),
|
||||
currentTime: getElement.call(this, this.config.selectors.display.currentTime),
|
||||
duration: getElement.call(this, this.config.selectors.display.duration),
|
||||
};
|
||||
|
||||
// Seek tooltip
|
||||
if (utils.is.element(this.elements.progress)) {
|
||||
if (is.element(this.elements.progress)) {
|
||||
this.elements.display.seekTooltip = this.elements.progress.querySelector(`.${this.config.classNames.tooltip}`);
|
||||
}
|
||||
|
||||
@ -87,9 +90,9 @@ const controls = {
|
||||
|
||||
// Create <svg>
|
||||
const icon = document.createElementNS(namespace, 'svg');
|
||||
utils.setAttributes(
|
||||
setAttributes(
|
||||
icon,
|
||||
utils.extend(attributes, {
|
||||
extend(attributes, {
|
||||
role: 'presentation',
|
||||
focusable: 'false',
|
||||
}),
|
||||
@ -138,21 +141,21 @@ const controls = {
|
||||
attributes.class = this.config.classNames.hidden;
|
||||
}
|
||||
|
||||
return utils.createElement('span', attributes, text);
|
||||
return createElement('span', attributes, text);
|
||||
},
|
||||
|
||||
// Create a badge
|
||||
createBadge(text) {
|
||||
if (utils.is.empty(text)) {
|
||||
if (is.empty(text)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const badge = utils.createElement('span', {
|
||||
const badge = createElement('span', {
|
||||
class: this.config.classNames.menu.value,
|
||||
});
|
||||
|
||||
badge.appendChild(
|
||||
utils.createElement(
|
||||
createElement(
|
||||
'span',
|
||||
{
|
||||
class: this.config.classNames.menu.badge,
|
||||
@ -166,9 +169,9 @@ const controls = {
|
||||
|
||||
// Create a <button>
|
||||
createButton(buttonType, attr) {
|
||||
const button = utils.createElement('button');
|
||||
const button = createElement('button');
|
||||
const attributes = Object.assign({}, attr);
|
||||
let type = utils.toCamelCase(buttonType);
|
||||
let type = toCamelCase(buttonType);
|
||||
|
||||
let toggle = false;
|
||||
let label;
|
||||
@ -252,13 +255,13 @@ const controls = {
|
||||
}
|
||||
|
||||
// Merge attributes
|
||||
utils.extend(attributes, utils.getAttributesFromSelector(this.config.selectors.buttons[type], attributes));
|
||||
extend(attributes, getAttributesFromSelector(this.config.selectors.buttons[type], attributes));
|
||||
|
||||
utils.setAttributes(button, attributes);
|
||||
setAttributes(button, attributes);
|
||||
|
||||
// We have multiple play buttons
|
||||
if (type === 'play') {
|
||||
if (!utils.is.array(this.elements.buttons[type])) {
|
||||
if (!is.array(this.elements.buttons[type])) {
|
||||
this.elements.buttons[type] = [];
|
||||
}
|
||||
|
||||
@ -273,7 +276,7 @@ const controls = {
|
||||
// Create an <input type='range'>
|
||||
createRange(type, attributes) {
|
||||
// Seek label
|
||||
const label = utils.createElement(
|
||||
const label = createElement(
|
||||
'label',
|
||||
{
|
||||
for: attributes.id,
|
||||
@ -284,10 +287,10 @@ const controls = {
|
||||
);
|
||||
|
||||
// Seek input
|
||||
const input = utils.createElement(
|
||||
const input = createElement(
|
||||
'input',
|
||||
utils.extend(
|
||||
utils.getAttributesFromSelector(this.config.selectors.inputs[type]),
|
||||
extend(
|
||||
getAttributesFromSelector(this.config.selectors.inputs[type]),
|
||||
{
|
||||
type: 'range',
|
||||
min: 0,
|
||||
@ -319,10 +322,10 @@ const controls = {
|
||||
|
||||
// Create a <progress>
|
||||
createProgress(type, attributes) {
|
||||
const progress = utils.createElement(
|
||||
const progress = createElement(
|
||||
'progress',
|
||||
utils.extend(
|
||||
utils.getAttributesFromSelector(this.config.selectors.display[type]),
|
||||
extend(
|
||||
getAttributesFromSelector(this.config.selectors.display[type]),
|
||||
{
|
||||
min: 0,
|
||||
max: 100,
|
||||
@ -336,7 +339,7 @@ const controls = {
|
||||
|
||||
// Create the label inside
|
||||
if (type !== 'volume') {
|
||||
progress.appendChild(utils.createElement('span', null, '0'));
|
||||
progress.appendChild(createElement('span', null, '0'));
|
||||
|
||||
let suffix = '';
|
||||
switch (type) {
|
||||
@ -362,12 +365,16 @@ const controls = {
|
||||
|
||||
// Create time display
|
||||
createTime(type) {
|
||||
const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
|
||||
const attributes = getAttributesFromSelector(this.config.selectors.display[type]);
|
||||
|
||||
const container = utils.createElement('div', utils.extend(attributes, {
|
||||
class: `plyr__time ${attributes.class}`,
|
||||
'aria-label': i18n.get(type, this.config),
|
||||
}), '00:00');
|
||||
const container = createElement(
|
||||
'div',
|
||||
extend(attributes, {
|
||||
class: `plyr__time ${attributes.class}`,
|
||||
'aria-label': i18n.get(type, this.config),
|
||||
}),
|
||||
'00:00',
|
||||
);
|
||||
|
||||
// Reference for updates
|
||||
this.elements.display[type] = container;
|
||||
@ -376,16 +383,16 @@ const controls = {
|
||||
},
|
||||
|
||||
// Create a settings menu item
|
||||
createMenuItem({value, list, type, title, badge = null, checked = false}) {
|
||||
const item = utils.createElement('li');
|
||||
createMenuItem({ value, list, type, title, badge = null, checked = false }) {
|
||||
const item = createElement('li');
|
||||
|
||||
const label = utils.createElement('label', {
|
||||
const label = createElement('label', {
|
||||
class: this.config.classNames.control,
|
||||
});
|
||||
|
||||
const radio = utils.createElement(
|
||||
const radio = createElement(
|
||||
'input',
|
||||
utils.extend(utils.getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
||||
extend(getAttributesFromSelector(this.config.selectors.inputs[type]), {
|
||||
type: 'radio',
|
||||
name: `plyr-${type}`,
|
||||
value,
|
||||
@ -394,13 +401,13 @@ const controls = {
|
||||
}),
|
||||
);
|
||||
|
||||
const faux = utils.createElement('span', { hidden: '' });
|
||||
const faux = createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
label.insertAdjacentHTML('beforeend', title);
|
||||
|
||||
if (utils.is.element(badge)) {
|
||||
if (is.element(badge)) {
|
||||
label.appendChild(badge);
|
||||
}
|
||||
|
||||
@ -411,15 +418,15 @@ const controls = {
|
||||
// Update the displayed time
|
||||
updateTimeDisplay(target = null, time = 0, inverted = false) {
|
||||
// Bail if there's no element to display or the value isn't a number
|
||||
if (!utils.is.element(target) || !utils.is.number(time)) {
|
||||
if (!is.element(target) || !is.number(time)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always display hours if duration is over an hour
|
||||
const forceHours = utils.getHours(this.duration) > 0;
|
||||
const forceHours = getHours(this.duration) > 0;
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
target.innerText = utils.formatTime(time, forceHours, inverted);
|
||||
target.innerText = formatTime(time, forceHours, inverted);
|
||||
},
|
||||
|
||||
// Update volume UI and storage
|
||||
@ -429,19 +436,19 @@ const controls = {
|
||||
}
|
||||
|
||||
// Update range
|
||||
if (utils.is.element(this.elements.inputs.volume)) {
|
||||
if (is.element(this.elements.inputs.volume)) {
|
||||
controls.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);
|
||||
}
|
||||
|
||||
// Update mute state
|
||||
if (utils.is.element(this.elements.buttons.mute)) {
|
||||
utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);
|
||||
if (is.element(this.elements.buttons.mute)) {
|
||||
toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);
|
||||
}
|
||||
},
|
||||
|
||||
// Update seek value and lower fill
|
||||
setRange(target, value = 0) {
|
||||
if (!utils.is.element(target)) {
|
||||
if (!is.element(target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -454,23 +461,23 @@ const controls = {
|
||||
|
||||
// Update <progress> elements
|
||||
updateProgress(event) {
|
||||
if (!this.supported.ui || !utils.is.event(event)) {
|
||||
if (!this.supported.ui || !is.event(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value = 0;
|
||||
|
||||
const setProgress = (target, input) => {
|
||||
const value = utils.is.number(input) ? input : 0;
|
||||
const progress = utils.is.element(target) ? target : this.elements.display.buffer;
|
||||
const value = is.number(input) ? input : 0;
|
||||
const progress = is.element(target) ? target : this.elements.display.buffer;
|
||||
|
||||
// Update value and label
|
||||
if (utils.is.element(progress)) {
|
||||
if (is.element(progress)) {
|
||||
progress.value = value;
|
||||
|
||||
// Update text label inside
|
||||
const label = progress.getElementsByTagName('span')[0];
|
||||
if (utils.is.element(label)) {
|
||||
if (is.element(label)) {
|
||||
label.childNodes[0].nodeValue = value;
|
||||
}
|
||||
}
|
||||
@ -482,7 +489,7 @@ const controls = {
|
||||
case 'timeupdate':
|
||||
case 'seeking':
|
||||
case 'seeked':
|
||||
value = utils.getPercentage(this.currentTime, this.duration);
|
||||
value = getPercentage(this.currentTime, this.duration);
|
||||
|
||||
// Set seek range value only if it's a 'natural' time event
|
||||
if (event.type === 'timeupdate') {
|
||||
@ -507,10 +514,10 @@ const controls = {
|
||||
// Webkit polyfill for lower fill range
|
||||
updateRangeFill(target) {
|
||||
// Get range from event if event passed
|
||||
const range = utils.is.event(target) ? target.target : target;
|
||||
const range = is.event(target) ? target.target : target;
|
||||
|
||||
// Needs to be a valid <input type='range'>
|
||||
if (!utils.is.element(range) || range.getAttribute('type') !== 'range') {
|
||||
if (!is.element(range) || range.getAttribute('type') !== 'range') {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -529,12 +536,7 @@ const controls = {
|
||||
// Update hover tooltip for seeking
|
||||
updateSeekTooltip(event) {
|
||||
// Bail if setting not true
|
||||
if (
|
||||
!this.config.tooltips.seek ||
|
||||
!utils.is.element(this.elements.inputs.seek) ||
|
||||
!utils.is.element(this.elements.display.seekTooltip) ||
|
||||
this.duration === 0
|
||||
) {
|
||||
if (!this.config.tooltips.seek || !is.element(this.elements.inputs.seek) || !is.element(this.elements.display.seekTooltip) || this.duration === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -544,7 +546,7 @@ const controls = {
|
||||
const visible = `${this.config.classNames.tooltip}--visible`;
|
||||
|
||||
const toggle = toggle => {
|
||||
utils.toggleClass(this.elements.display.seekTooltip, visible, toggle);
|
||||
toggleClass(this.elements.display.seekTooltip, visible, toggle);
|
||||
};
|
||||
|
||||
// Hide on touch
|
||||
@ -554,9 +556,9 @@ const controls = {
|
||||
}
|
||||
|
||||
// Determine percentage, if already visible
|
||||
if (utils.is.event(event)) {
|
||||
if (is.event(event)) {
|
||||
percent = 100 / clientRect.width * (event.pageX - clientRect.left);
|
||||
} else if (utils.hasClass(this.elements.display.seekTooltip, visible)) {
|
||||
} else if (hasClass(this.elements.display.seekTooltip, visible)) {
|
||||
percent = parseFloat(this.elements.display.seekTooltip.style.left, 10);
|
||||
} else {
|
||||
return;
|
||||
@ -577,7 +579,7 @@ const controls = {
|
||||
|
||||
// Show/hide the tooltip
|
||||
// If the event is a moues in/out and percentage is inside bounds
|
||||
if (utils.is.event(event) && [
|
||||
if (is.event(event) && [
|
||||
'mouseenter',
|
||||
'mouseleave',
|
||||
].includes(event.type)) {
|
||||
@ -588,7 +590,7 @@ const controls = {
|
||||
// Handle time change event
|
||||
timeUpdate(event) {
|
||||
// Only invert if only one time element is displayed and used for both duration and currentTime
|
||||
const invert = !utils.is.element(this.elements.display.duration) && this.config.invertTime;
|
||||
const invert = !is.element(this.elements.display.duration) && this.config.invertTime;
|
||||
|
||||
// Duration
|
||||
controls.updateTimeDisplay.call(this, this.elements.display.currentTime, invert ? this.duration - this.currentTime : this.currentTime, invert);
|
||||
@ -610,7 +612,7 @@ const controls = {
|
||||
}
|
||||
|
||||
// If there's a spot to display duration
|
||||
const hasDuration = utils.is.element(this.elements.display.duration);
|
||||
const hasDuration = is.element(this.elements.display.duration);
|
||||
|
||||
// If there's only one time display, display duration there
|
||||
if (!hasDuration && this.config.displayDuration && this.paused) {
|
||||
@ -628,14 +630,14 @@ const controls = {
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab(setting, toggle) {
|
||||
utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
},
|
||||
|
||||
// Set the quality menu
|
||||
// TODO: Vimeo support
|
||||
setQualityMenu(options) {
|
||||
// Menu required
|
||||
if (!utils.is.element(this.elements.settings.panes.quality)) {
|
||||
if (!is.element(this.elements.settings.panes.quality)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -643,12 +645,12 @@ const controls = {
|
||||
const list = this.elements.settings.panes.quality.querySelector('ul');
|
||||
|
||||
// Set options if passed and filter based on config
|
||||
if (utils.is.array(options)) {
|
||||
if (is.array(options)) {
|
||||
this.options.quality = options.filter(quality => this.config.quality.options.includes(quality));
|
||||
}
|
||||
|
||||
// Toggle the pane and tab
|
||||
const toggle = !utils.is.empty(this.options.quality) && this.options.quality.length > 1;
|
||||
const toggle = !is.empty(this.options.quality) && this.options.quality.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
@ -660,7 +662,7 @@ const controls = {
|
||||
}
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
emptyElement(list);
|
||||
|
||||
// Get the badge HTML for HD, 4K etc
|
||||
const getBadge = quality => {
|
||||
@ -699,7 +701,7 @@ const controls = {
|
||||
return value === 1 ? i18n.get('normal', this.config) : `${value}×`;
|
||||
|
||||
case 'quality':
|
||||
if (utils.is.number(value)) {
|
||||
if (is.number(value)) {
|
||||
const label = i18n.get(`qualityLabel.${value}`, this.config);
|
||||
|
||||
if (!label.length) {
|
||||
@ -709,7 +711,7 @@ const controls = {
|
||||
return label;
|
||||
}
|
||||
|
||||
return utils.toTitleCase(value);
|
||||
return toTitleCase(value);
|
||||
|
||||
case 'captions':
|
||||
return captions.getLabel.call(this);
|
||||
@ -731,15 +733,15 @@ const controls = {
|
||||
break;
|
||||
|
||||
default:
|
||||
value = !utils.is.empty(input) ? input : this[setting];
|
||||
value = !is.empty(input) ? input : this[setting];
|
||||
|
||||
// Get default
|
||||
if (utils.is.empty(value)) {
|
||||
if (is.empty(value)) {
|
||||
value = this.config[setting].default;
|
||||
}
|
||||
|
||||
// Unsupported value
|
||||
if (!utils.is.empty(this.options[setting]) && !this.options[setting].includes(value)) {
|
||||
if (!is.empty(this.options[setting]) && !this.options[setting].includes(value)) {
|
||||
this.debug.warn(`Unsupported value of '${value}' for ${setting}`);
|
||||
return;
|
||||
}
|
||||
@ -754,12 +756,12 @@ const controls = {
|
||||
}
|
||||
|
||||
// Get the list if we need to
|
||||
if (!utils.is.element(list)) {
|
||||
if (!is.element(list)) {
|
||||
list = pane && pane.querySelector('ul');
|
||||
}
|
||||
|
||||
// If there's no list it means it's not been rendered...
|
||||
if (!utils.is.element(list)) {
|
||||
if (!is.element(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -770,7 +772,7 @@ const controls = {
|
||||
// Find the radio option and check it
|
||||
const target = list && list.querySelector(`input[value="${value}"]`);
|
||||
|
||||
if (utils.is.element(target)) {
|
||||
if (is.element(target)) {
|
||||
target.checked = true;
|
||||
}
|
||||
},
|
||||
@ -778,7 +780,7 @@ const controls = {
|
||||
// Set the looping options
|
||||
/* setLoopMenu() {
|
||||
// Menu required
|
||||
if (!utils.is.element(this.elements.settings.panes.loop)) {
|
||||
if (!is.element(this.elements.settings.panes.loop)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -786,22 +788,22 @@ const controls = {
|
||||
const list = this.elements.settings.panes.loop.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
utils.toggleHidden(this.elements.settings.tabs.loop, false);
|
||||
utils.toggleHidden(this.elements.settings.panes.loop, false);
|
||||
toggleHidden(this.elements.settings.tabs.loop, false);
|
||||
toggleHidden(this.elements.settings.panes.loop, false);
|
||||
|
||||
// Toggle the pane and tab
|
||||
const toggle = !utils.is.empty(this.loop.options);
|
||||
const toggle = !is.empty(this.loop.options);
|
||||
controls.toggleTab.call(this, 'loop', toggle);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
emptyElement(list);
|
||||
|
||||
options.forEach(option => {
|
||||
const item = utils.createElement('li');
|
||||
const item = createElement('li');
|
||||
|
||||
const button = utils.createElement(
|
||||
const button = createElement(
|
||||
'button',
|
||||
utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.loop), {
|
||||
extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {
|
||||
type: 'button',
|
||||
class: this.config.classNames.control,
|
||||
'data-plyr-loop-action': option,
|
||||
@ -833,7 +835,7 @@ const controls = {
|
||||
controls.toggleTab.call(this, type, tracks.length);
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
emptyElement(list);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
controls.checkMenu.call(this);
|
||||
@ -876,14 +878,14 @@ const controls = {
|
||||
}
|
||||
|
||||
// Menu required
|
||||
if (!utils.is.element(this.elements.settings.panes.speed)) {
|
||||
if (!is.element(this.elements.settings.panes.speed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const type = 'speed';
|
||||
|
||||
// Set the speed options
|
||||
if (utils.is.array(options)) {
|
||||
if (is.array(options)) {
|
||||
this.options.speed = options;
|
||||
} else if (this.isHTML5 || this.isVimeo) {
|
||||
this.options.speed = [
|
||||
@ -901,7 +903,7 @@ const controls = {
|
||||
this.options.speed = this.options.speed.filter(speed => this.config.speed.options.includes(speed));
|
||||
|
||||
// Toggle the pane and tab
|
||||
const toggle = !utils.is.empty(this.options.speed) && this.options.speed.length > 1;
|
||||
const toggle = !is.empty(this.options.speed) && this.options.speed.length > 1;
|
||||
controls.toggleTab.call(this, type, toggle);
|
||||
|
||||
// Check if we need to toggle the parent
|
||||
@ -916,7 +918,7 @@ const controls = {
|
||||
const list = this.elements.settings.panes.speed.querySelector('ul');
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
emptyElement(list);
|
||||
|
||||
// Create items
|
||||
this.options.speed.forEach(speed => {
|
||||
@ -934,9 +936,9 @@ const controls = {
|
||||
// Check if we need to hide/show the settings menu
|
||||
checkMenu() {
|
||||
const { tabs } = this.elements.settings;
|
||||
const visible = !utils.is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden);
|
||||
const visible = !is.empty(tabs) && Object.values(tabs).some(tab => !tab.hidden);
|
||||
|
||||
utils.toggleHidden(this.elements.settings.menu, !visible);
|
||||
toggleHidden(this.elements.settings.menu, !visible);
|
||||
},
|
||||
|
||||
// Show/hide menu
|
||||
@ -945,14 +947,14 @@ const controls = {
|
||||
const button = this.elements.buttons.settings;
|
||||
|
||||
// Menu and button are required
|
||||
if (!utils.is.element(form) || !utils.is.element(button)) {
|
||||
if (!is.element(form) || !is.element(button)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');
|
||||
const show = is.boolean(event) ? event : is.element(form) && form.hasAttribute('hidden');
|
||||
|
||||
if (utils.is.event(event)) {
|
||||
const isMenuItem = utils.is.element(form) && form.contains(event.target);
|
||||
if (is.event(event)) {
|
||||
const isMenuItem = is.element(form) && form.contains(event.target);
|
||||
const isButton = event.target === this.elements.buttons.settings;
|
||||
|
||||
// If the click was inside the form or if the click
|
||||
@ -969,13 +971,13 @@ const controls = {
|
||||
}
|
||||
|
||||
// Set form and button attributes
|
||||
if (utils.is.element(button)) {
|
||||
if (is.element(button)) {
|
||||
button.setAttribute('aria-expanded', show);
|
||||
}
|
||||
|
||||
if (utils.is.element(form)) {
|
||||
utils.toggleHidden(form, !show);
|
||||
utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||
if (is.element(form)) {
|
||||
toggleHidden(form, !show);
|
||||
toggleClass(this.elements.container, this.config.classNames.menu.open, show);
|
||||
|
||||
if (show) {
|
||||
form.removeAttribute('tabindex');
|
||||
@ -1006,7 +1008,7 @@ const controls = {
|
||||
const height = clone.scrollHeight;
|
||||
|
||||
// Remove from the DOM
|
||||
utils.removeElement(clone);
|
||||
removeElement(clone);
|
||||
|
||||
return {
|
||||
width,
|
||||
@ -1020,7 +1022,7 @@ const controls = {
|
||||
const pane = document.getElementById(target);
|
||||
|
||||
// Nothing to show, bail
|
||||
if (!utils.is.element(pane)) {
|
||||
if (!is.element(pane)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1064,11 +1066,11 @@ const controls = {
|
||||
container.style.height = '';
|
||||
|
||||
// Only listen once
|
||||
utils.off(container, utils.transitionEndEvent, restore);
|
||||
off(container, transitionEndEvent, restore);
|
||||
};
|
||||
|
||||
// Listen for the transition finishing and restore auto height/width
|
||||
utils.on(container, utils.transitionEndEvent, restore);
|
||||
on(container, transitionEndEvent, restore);
|
||||
|
||||
// Set dimensions to target
|
||||
container.style.width = `${size.width}px`;
|
||||
@ -1076,13 +1078,13 @@ const controls = {
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
utils.toggleHidden(current, true);
|
||||
toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
utils.toggleHidden(pane, false);
|
||||
toggleHidden(pane, false);
|
||||
|
||||
const tabs = utils.getElements.call(this, `[aria-controls="${target}"]`);
|
||||
const tabs = getElements.call(this, `[aria-controls="${target}"]`);
|
||||
Array.from(tabs).forEach(tab => {
|
||||
tab.setAttribute('aria-expanded', true);
|
||||
});
|
||||
@ -1096,12 +1098,12 @@ const controls = {
|
||||
// TODO: Set order based on order in the config.controls array?
|
||||
create(data) {
|
||||
// Do nothing if we want no controls
|
||||
if (utils.is.empty(this.config.controls)) {
|
||||
if (is.empty(this.config.controls)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create the container
|
||||
const container = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.controls.wrapper));
|
||||
const container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));
|
||||
|
||||
// Restart button
|
||||
if (this.config.controls.includes('restart')) {
|
||||
@ -1125,7 +1127,7 @@ const controls = {
|
||||
|
||||
// Progress
|
||||
if (this.config.controls.includes('progress')) {
|
||||
const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress));
|
||||
const progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress));
|
||||
|
||||
// Seek range slider
|
||||
const seek = controls.createRange.call(this, 'seek', {
|
||||
@ -1141,7 +1143,7 @@ const controls = {
|
||||
|
||||
// Seek tooltip
|
||||
if (this.config.tooltips.seek) {
|
||||
const tooltip = utils.createElement(
|
||||
const tooltip = createElement(
|
||||
'span',
|
||||
{
|
||||
class: this.config.classNames.tooltip,
|
||||
@ -1174,7 +1176,7 @@ const controls = {
|
||||
|
||||
// Volume range control
|
||||
if (this.config.controls.includes('volume')) {
|
||||
const volume = utils.createElement('div', {
|
||||
const volume = createElement('div', {
|
||||
class: 'plyr__volume',
|
||||
});
|
||||
|
||||
@ -1189,7 +1191,7 @@ const controls = {
|
||||
const range = controls.createRange.call(
|
||||
this,
|
||||
'volume',
|
||||
utils.extend(attributes, {
|
||||
extend(attributes, {
|
||||
id: `plyr-volume-${data.id}`,
|
||||
}),
|
||||
);
|
||||
@ -1207,8 +1209,8 @@ const controls = {
|
||||
}
|
||||
|
||||
// Settings button / menu
|
||||
if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {
|
||||
const menu = utils.createElement('div', {
|
||||
if (this.config.controls.includes('settings') && !is.empty(this.config.settings)) {
|
||||
const menu = createElement('div', {
|
||||
class: 'plyr__menu',
|
||||
hidden: '',
|
||||
});
|
||||
@ -1222,7 +1224,7 @@ const controls = {
|
||||
}),
|
||||
);
|
||||
|
||||
const form = utils.createElement('form', {
|
||||
const form = createElement('form', {
|
||||
class: 'plyr__menu__container',
|
||||
id: `plyr-settings-${data.id}`,
|
||||
hidden: '',
|
||||
@ -1231,29 +1233,29 @@ const controls = {
|
||||
tabindex: -1,
|
||||
});
|
||||
|
||||
const inner = utils.createElement('div');
|
||||
const inner = createElement('div');
|
||||
|
||||
const home = utils.createElement('div', {
|
||||
const home = createElement('div', {
|
||||
id: `plyr-settings-${data.id}-home`,
|
||||
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
||||
role: 'tabpanel',
|
||||
});
|
||||
|
||||
// Create the tab list
|
||||
const tabs = utils.createElement('ul', {
|
||||
const tabs = createElement('ul', {
|
||||
role: 'tablist',
|
||||
});
|
||||
|
||||
// Build the tabs
|
||||
this.config.settings.forEach(type => {
|
||||
const tab = utils.createElement('li', {
|
||||
const tab = createElement('li', {
|
||||
role: 'tab',
|
||||
hidden: '',
|
||||
});
|
||||
|
||||
const button = utils.createElement(
|
||||
const button = createElement(
|
||||
'button',
|
||||
utils.extend(utils.getAttributesFromSelector(this.config.selectors.buttons.settings), {
|
||||
extend(getAttributesFromSelector(this.config.selectors.buttons.settings), {
|
||||
type: 'button',
|
||||
class: `${this.config.classNames.control} ${this.config.classNames.control}--forward`,
|
||||
id: `plyr-settings-${data.id}-${type}-tab`,
|
||||
@ -1264,7 +1266,7 @@ const controls = {
|
||||
i18n.get(type, this.config),
|
||||
);
|
||||
|
||||
const value = utils.createElement('span', {
|
||||
const value = createElement('span', {
|
||||
class: this.config.classNames.menu.value,
|
||||
});
|
||||
|
||||
@ -1283,7 +1285,7 @@ const controls = {
|
||||
|
||||
// Build the panes
|
||||
this.config.settings.forEach(type => {
|
||||
const pane = utils.createElement('div', {
|
||||
const pane = createElement('div', {
|
||||
id: `plyr-settings-${data.id}-${type}`,
|
||||
hidden: '',
|
||||
'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,
|
||||
@ -1291,7 +1293,7 @@ const controls = {
|
||||
tabindex: -1,
|
||||
});
|
||||
|
||||
const back = utils.createElement(
|
||||
const back = createElement(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
@ -1305,7 +1307,7 @@ const controls = {
|
||||
|
||||
pane.appendChild(back);
|
||||
|
||||
const options = utils.createElement('ul');
|
||||
const options = createElement('ul');
|
||||
|
||||
pane.appendChild(options);
|
||||
inner.appendChild(pane);
|
||||
@ -1360,7 +1362,7 @@ const controls = {
|
||||
|
||||
// Only load external sprite using AJAX
|
||||
if (icon.cors) {
|
||||
utils.loadSprite(icon.url, 'sprite-plyr');
|
||||
loadSprite(icon.url, 'sprite-plyr');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1379,10 +1381,10 @@ const controls = {
|
||||
};
|
||||
let update = true;
|
||||
|
||||
if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {
|
||||
if (is.string(this.config.controls) || is.element(this.config.controls)) {
|
||||
// String or HTMLElement passed as the option
|
||||
container = this.config.controls;
|
||||
} else if (utils.is.function(this.config.controls)) {
|
||||
} else if (is.function(this.config.controls)) {
|
||||
// A custom function to build controls
|
||||
// The function can return a HTMLElement or String
|
||||
container = this.config.controls.call(this, props);
|
||||
@ -1408,7 +1410,7 @@ const controls = {
|
||||
key,
|
||||
value,
|
||||
]) => {
|
||||
result = utils.replaceAll(result, `{${key}}`, value);
|
||||
result = replaceAll(result, `{${key}}`, value);
|
||||
});
|
||||
|
||||
return result;
|
||||
@ -1416,9 +1418,9 @@ const controls = {
|
||||
|
||||
// Update markup
|
||||
if (update) {
|
||||
if (utils.is.string(this.config.controls)) {
|
||||
if (is.string(this.config.controls)) {
|
||||
container = replace(container);
|
||||
} else if (utils.is.element(container)) {
|
||||
} else if (is.element(container)) {
|
||||
container.innerHTML = replace(container.innerHTML);
|
||||
}
|
||||
}
|
||||
@ -1427,35 +1429,35 @@ const controls = {
|
||||
let target;
|
||||
|
||||
// Inject to custom location
|
||||
if (utils.is.string(this.config.selectors.controls.container)) {
|
||||
if (is.string(this.config.selectors.controls.container)) {
|
||||
target = document.querySelector(this.config.selectors.controls.container);
|
||||
}
|
||||
|
||||
// Inject into the container by default
|
||||
if (!utils.is.element(target)) {
|
||||
if (!is.element(target)) {
|
||||
target = this.elements.container;
|
||||
}
|
||||
|
||||
// Inject controls HTML
|
||||
if (utils.is.element(container)) {
|
||||
if (is.element(container)) {
|
||||
target.appendChild(container);
|
||||
} else if (container) {
|
||||
target.insertAdjacentHTML('beforeend', container);
|
||||
}
|
||||
|
||||
// Find the elements if need be
|
||||
if (!utils.is.element(this.elements.controls)) {
|
||||
if (!is.element(this.elements.controls)) {
|
||||
controls.findElements.call(this);
|
||||
}
|
||||
|
||||
// Edge sometimes doesn't finish the paint so force a redraw
|
||||
if (window.navigator.userAgent.includes('Edge')) {
|
||||
utils.repaint(target);
|
||||
repaint(target);
|
||||
}
|
||||
|
||||
// Setup tooltips
|
||||
if (this.config.tooltips.controls) {
|
||||
const labels = utils.getElements.call(
|
||||
const labels = getElements.call(
|
||||
this,
|
||||
[
|
||||
this.config.selectors.controls.wrapper,
|
||||
@ -1467,8 +1469,8 @@ const controls = {
|
||||
);
|
||||
|
||||
Array.from(labels).forEach(label => {
|
||||
utils.toggleClass(label, this.config.classNames.hidden, false);
|
||||
utils.toggleClass(label, this.config.classNames.tooltip, true);
|
||||
toggleClass(label, this.config.classNames.hidden, false);
|
||||
toggleClass(label, this.config.classNames.tooltip, true);
|
||||
label.setAttribute('role', 'tooltip');
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user