diff options
Diffstat (limited to 'src/js/plyr.js')
-rw-r--r-- | src/js/plyr.js | 283 |
1 files changed, 196 insertions, 87 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js index 98009041..9f966db8 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -417,7 +417,7 @@ // Set attributes function setAttributes(element, attributes) { for (var key in attributes) { - element.setAttribute(key, (is.boolean(attributes[key]) && attributes[key]) ? '' : attributes[key]); + element.setAttribute(key, attributes[key]); } } @@ -817,7 +817,7 @@ // Picture-in-picture support // Safari only currently pip: (function() { - return is.function(document.createElement('video').webkitSetPresentationMode); + return is.function(createElement('video').webkitSetPresentationMode); })(), // Airplay support // Safari only currently @@ -870,12 +870,18 @@ var plyr = this; var timers = {}; var api; + + // Elements cache var elements = { buttons: {}, display: {}, progress: {}, - inputs: {} - } + inputs: {}, + settings: { + tabs: {}, + panes: {} + } + }; // Set media plyr.media = media; @@ -901,10 +907,10 @@ } } var log = function() { - logger('log', arguments) + logger('log', arguments); }; var warn = function() { - logger('warn', arguments) + logger('warn', arguments); }; // Log config options and support @@ -961,10 +967,10 @@ insertElement(type, plyr.media, { src: attributes }); - } else if (attributes.constructor === Array) { - for (var i = attributes.length - 1; i >= 0; i--) { - insertElement(type, plyr.media, attributes[i]); - } + } else if (is.array(attributes)) { + attributes.forEach(function(attribute) { + insertElement(type, plyr.media, attribute); + }); } } @@ -976,22 +982,6 @@ }; } - // Build a list of available captions - function buildCaptionsMenu() { - var trackSubs = ''; - - if (is.array(config.tracks) && !is.empty(config.tracks)) { - config.tracks.forEach(function(track, index) { - if (is.function(track)) { - return; - } - trackSubs += '<button type="button" class="plyr__control" data-plyr="captions-lang" data-lang="' + track.srclang + '" data-index="' + index + '">' + track.label + '</button>'; - }); - } - - return trackSubs; - } - // Create <svg> icon function createIcon(type, attributes) { var namespace = 'http://www.w3.org/2000/svg'; @@ -1034,15 +1024,24 @@ } // Create a <button> - function createButton(type) { + function createButton(type, attributes) { var button = createElement('button'); - var attributes = { - class: 'plyr__control' - }; var iconDefault; var iconToggled; var labelKey; + if (!is.object(attributes)) { + attributes = {}; + } + + if ('class' in attributes) { + if (attributes.class.indexOf('plyr__control') === -1) { + attributes.class += ' plyr__control'; + } + } else { + attributes.class = 'plyr__control'; + } + // Large play button switch (type) { case 'mute': @@ -1171,6 +1170,8 @@ container.appendChild(createElement('span', getAttributesFromSelector(config.selectors.display[type]), '00:00')); + elements.display[type] = container; + return container; } @@ -1222,14 +1223,11 @@ // Seek tooltip if (config.tooltips.seek) { - //html.push('<span class="plyr__tooltip">00:00</span>'); var tooltip = createElement('span', { role: 'tooltip', class: config.classes.tooltip - }); + }, '00:00'); - var value = document.createTextNode('00:00'); - tooltip.appendChild(value); container.appendChild(tooltip); } @@ -1284,24 +1282,132 @@ // Settings button / menu if (inArray(config.controls, 'settings')) { - /* - var captionsMenuItem = ''; - if (inArray(config.controls, 'captions')) { - captionsMenuItem = '<li role="tab">'+ - '<button type="button" class="plyr__control plyr__control--forward" id="plyr-settings-{id}-captions-toggle" aria-haspopup="true" aria-controls="plyr-settings-{id}-captions" aria-expanded="false">'+ - config.i18n.captions + - '<span class="plyr__menu__value" data-captions="settings">{lang}</span>'+ - '</button>'+ - '</li>'; - } + var wrapper = createElement('span', extend(getAttributesFromSelector(config.selectors.buttons.settings), { + class: 'plyr__menu' + })); - if (is.array(config.quality.options)) { - var showQuality = '<button type="button" class="plyr__control plyr__control--forward" id="plyr-settings-{id}-quality-toggle" aria-haspopup="true" aria-controls="plyr-settings-{id}-quality" aria-expanded="false">'+ - config.i18n.quality +'<span class="plyr__menu__value">Auto</span>'+ - '</button>'; - } + wrapper.appendChild(createButton('settings', { + id: 'plyr-settings-toggle-' + data.id, + 'aria-haspopup': true, + 'aria-controls': 'plyr-settings-' + data.id, + 'aria-expanded': false + })); + + var form = createElement('form', { + class: 'plyr__menu__container', + id: 'plyr-settings-' + data.id, + 'aria-hidden': true, + 'aria-labelled-by': 'plyr-settings-toggle-' + data.id, + role: 'tablist', + tabindex: -1 + }); + + var inner = createElement('div'); + + var home = createElement('div', { + id: 'plyr-settings-' + data.id + '-home', + 'aria-hidden': false, + 'aria-labelled-by': 'plyr-settings-toggle-' + data.id, + role: 'tabpanel', + tabindex: -1 + }); + + var tabs = createElement('ul', { + role: 'tablist' + }); + + ['captions', 'quality', 'speed', 'loop'].forEach(function(type) { + var tab = createElement('li', { + role: 'tab' + }); + + var button = createElement('button', extend(getAttributesFromSelector(config.selectors.buttons.settings), { + type: 'button', + class: 'plyr__control plyr__control--forward', + id: 'plyr-settings-' + data.id + '-' + type + '-tab', + 'aria-haspopup': true, + 'aria-controls': 'plyr-settings-' + data.id + '-' + type, + 'aria-expanded': false + }), config.i18n[type]); + + var value = createElement('span', { + class: 'plyr__menu__value' + }); - html.push( + // Speed contains HTML entities + value.innerHTML = data[type]; + + button.appendChild(value); + + tab.appendChild(button); + + tabs.appendChild(tab); + }); + + home.appendChild(tabs); + + inner.appendChild(home); + + ['captions', 'quality', 'speed', 'loop'].forEach(function(type) { + var pane = createElement('div', { + id: 'plyr-settings-' + data.id + '-' + type, + 'aria-hidden': true, + 'aria-labelled-by': 'plyr-settings-tab-' + data.id, + role: 'tabpanel', + tabindex: -1 + }); + + var options = createElement('ul'); + + var option = createElement('li'); + + var back = createElement('button', { + type: 'button', + class: 'plyr__control plyr__control--back', + 'aria-haspopup': true, + 'aria-controls': 'plyr-settings-' + data.id + '-home', + 'aria-expanded': false + }, config.i18n.back); + + option.appendChild(back); + + options.appendChild(option); + + switch (type) { + case 'captions': + if (is.array(config.tracks)) { + config.tracks.forEach(function(track, index) { + if (is.function(track)) { + return; + } + + var option = createElement('li'); + + var button = createButton('language', { + 'data-language': track.srclang, + 'data-index': index + }, track.label); + + option.appendChild(button); + + options.appendChild(options); + }); + } + break; + } + + pane.appendChild(options); + + inner.appendChild(pane); + }); + + form.appendChild(inner); + + wrapper.appendChild(form); + + controls.appendChild(wrapper); + + /*html.push( '<div class="plyr__menu" data-plyr="settings">', '<button type="button" id="plyr-settings-toggle-{id}" class="plyr__control" aria-haspopup="true" aria-controls="plyr-settings-{id}" aria-expanded="false">', '<svg><use xlink:href="' + iconPath + '-settings" /></svg>', @@ -1494,6 +1600,8 @@ controls.appendChild(createButton('fullscreen')); } + elements.controls = controls; + return controls; } @@ -1958,7 +2066,7 @@ // Set global plyr.captionsEnabled = show; elements.buttons.captions_menu.innerHTML = show ? 'Off' : 'On'; - getElement('[data-captions="settings"]').innerHTML = getSubsLangValue(); + //TODO: display lang getElement('[data-captions="settings"]').innerHTML = getSubsLangValue(); // Toggle state toggleState(elements.buttons.captions, plyr.captionsEnabled); @@ -1997,15 +2105,19 @@ } // Create a unique ID - plyr.id = Math.floor(Math.random() * (10000)); + plyr.id = Math.floor(Math.random() * 10000); // Create controls var controls = createControls({ id: plyr.id, seektime: config.seekTime, speed: getSpeedDisplayValue(), + // TODO: Get current quality + quality: 'HD', // TODO: Set language automatically based on UA? - language: 'English' + captions: 'English', + // TODO: Get loop + loop: 'None' }); // Controls container @@ -2039,7 +2151,8 @@ } // Find the UI controls and store references - function findElements() { + // TODO: Restore when re-enabling custom HTML + /*function findElements() { try { elements.controls = getElement(config.selectors.controls.wrapper); @@ -2092,7 +2205,7 @@ return false; } - } + }*/ // Toggle style hook function toggleStyleHook() { @@ -2218,7 +2331,7 @@ // Inject the player wrapper if (plyr.type === 'video') { // Create the wrapper div - var wrapper = document.createElement('div'); + var wrapper = createElement('div'); wrapper.setAttribute('class', config.classes.videoWrapper); // Wrap the video in a container @@ -2237,9 +2350,9 @@ // Setup YouTube/Vimeo function setupEmbed() { - var container = document.createElement('div'), - mediaId, - id = plyr.type + '-' + Math.floor(Math.random() * (10000)); + var container = createElement('div'); + var mediaId; + var id = plyr.type + '-' + Math.floor(Math.random() * (10000)); // Parse IDs from URLs if supplied switch (plyr.type) { @@ -2322,7 +2435,7 @@ } else if (plyr.type === 'soundcloud') { // TODO: Currently unsupported and undocumented // Inject the iframe - var soundCloud = document.createElement('iframe'); + var soundCloud = createElement('iframe'); // Watch for iframe load soundCloud.loaded = false; @@ -2957,10 +3070,10 @@ // Get the duration (or custom if set) function getDuration() { // It should be a number, but parse it just incase - var duration = parseInt(config.duration), + var duration = parseInt(config.duration); - // True duration - mediaDuration = 0; + // True duration + var mediaDuration = 0; // Only if duration available if (plyr.media.duration !== null && !isNaN(plyr.media.duration)) { @@ -3597,17 +3710,17 @@ // Create new markup switch (plyr.type) { case 'video': - plyr.media = document.createElement('video'); + plyr.media = createElement('video'); break; case 'audio': - plyr.media = document.createElement('audio'); + plyr.media = createElement('audio'); break; case 'youtube': case 'vimeo': case 'soundcloud': - plyr.media = document.createElement('div'); + plyr.media = createElement('div'); plyr.embedId = source.sources[0].src; break; } @@ -3998,10 +4111,10 @@ // Settings on(elements.buttons.settings, 'click', function(event) { - var menu = this, - toggle = event.target, - target = document.getElementById(toggle.getAttribute('aria-controls')), - show = (toggle.getAttribute('aria-expanded') === 'false'); + var menu = this; + var toggle = event.target; + var target = document.getElementById(toggle.getAttribute('aria-controls')); + var show = (toggle.getAttribute('aria-expanded') === 'false'); // Nothing to show, bail if (!is.htmlElement(target)) { @@ -4009,10 +4122,10 @@ } // Are we targetting a tab? - var isTab = target.getAttribute('role') === 'tabpanel', - targetWidth, - targetHeight, - container; + var isTab = target.getAttribute('role') === 'tabpanel'; + var targetWidth; + var targetHeight; + var container; // Hide all other tabs if (isTab) { @@ -4344,7 +4457,7 @@ } // Wrap media - plyr.container = wrap(media, document.createElement('div')); + plyr.container = wrap(media, createElement('div')); // Allow focus to be captured plyr.container.setAttribute('tabindex', 0); @@ -4395,21 +4508,17 @@ } // Inject custom controls if not present - var controlsMissing = !getElements(config.selectors.controls.wrapper).length; - if (controlsMissing) { + if (!is.htmlElement(getElement(config.selectors.controls.wrapper))) { // Inject custom controls injectControls(); + controlListeners(); } // Find the elements - if (!findElements()) { + // TODO: re-enable when custom HTML is restored + /*if (!findElements()) { return; - } - - // If the controls are injected, re-bind listeners for controls - if (controlsMissing) { - controlListeners(); - } + }*/ // Media element listeners mediaListeners(); @@ -4556,7 +4665,7 @@ } // Create placeholder (to prevent loading twice) - var container = document.createElement('div'); + var container = createElement('div'); container.setAttribute('hidden', ''); if (is.string(id)) { container.setAttribute('id', id); @@ -4584,8 +4693,8 @@ isOldIE = (browser.isIE && browser.version <= 9), isIos = browser.isIos, isIphone = /iPhone|iPod/i.test(navigator.userAgent), - audio = !!document.createElement('audio').canPlayType, - video = !!document.createElement('video').canPlayType, + audio = !!createElement('audio').canPlayType, + video = !!createElement('video').canPlayType, basic, full; switch (type) { |