From d80be3b903adaf768a8e1c0cf206628f0eb10043 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sun, 12 Nov 2017 07:45:52 +0000 Subject: [PATCH 1/7] More docs, event renamed --- dist/plyr.js | 2 +- dist/plyr.js.map | 2 +- readme.md | 246 ++++++++++++-------------------------------- src/js/defaults.js | 2 +- src/js/listeners.js | 2 +- src/js/plyr.js | 2 +- 6 files changed, 68 insertions(+), 188 deletions(-) diff --git a/dist/plyr.js b/dist/plyr.js index 49e09fa9..62a63c0d 100644 --- a/dist/plyr.js +++ b/dist/plyr.js @@ -1,3 +1,3 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";function e(){var e=window.localStorage.getItem(this.config.storage.key);return s.is.empty(e)?{}:JSON.parse(e)}function t(t){if(a.storage&&this.config.storage.enabled&&s.is.object(t)){var i=e.call(this);s.extend(i,t),window.localStorage.setItem(this.config.storage.key,JSON.stringify(i))}}var i={enabled:!0,title:"",debug:!1,autoplay:!1,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,showPosterOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/2.0.10/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:"default",options:["hd2160","hd1440","hd1080","hd720","large","medium","small","tiny","default"]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:window.navigator.language.split("-")[0]},fullscreen:{enabled:!0,fallback:!0},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed","loop"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",seek:"Seek",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",toggleMute:"Toggle Mute",toggleCaptions:"Toggle Captions",toggleFullscreen:"Toggle Fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",speed:"Speed",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",none:"None",disabled:"Disabled"},urls:{vimeo:{api:"https://player.vimeo.com/api/player.js"},youtube:{api:"https://www.youtube.com/iframe_api"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,forward:null,mute:null,volume:null,captions:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","captionchange","controlshidden","controlsshown","ready","statechange","qualitychange","qualityrequested"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',forward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress--buffer",played:".plyr__progress--played",loop:".plyr__progress--loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{video:"plyr__video-wrapper",embed:"plyr__video-embed",control:"plyr__control",type:"plyr--{0}",stopped:"plyr--stopped",playing:"plyr--playing",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",menu:{value:"plyr__menu__value",badge:"plyr__badge"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus"}},n={embed:["youtube","vimeo"],html5:["video","audio"]},s={is:{object:function(e){return this.getConstructor(e)===Object},number:function(e){return this.getConstructor(e)===Number&&!Number.isNaN(e)},string:function(e){return this.getConstructor(e)===String},boolean:function(e){return this.getConstructor(e)===Boolean},function:function(e){return this.getConstructor(e)===Function},array:function(e){return!this.undefined(e)&&Array.isArray(e)},nodeList:function(e){return!this.undefined(e)&&e instanceof NodeList},htmlElement:function(e){return!this.undefined(e)&&e instanceof HTMLElement},event:function(e){return!this.undefined(e)&&e instanceof Event},cue:function(e){return this.instanceOf(e,window.TextTrackCue)||this.instanceOf(e,window.VTTCue)},track:function(e){return!this.undefined(e)&&(this.instanceOf(e,window.TextTrack)||"string"==typeof e.kind)},undefined:function(e){return null!==e&&void 0===e},empty:function(e){return null===e||void 0===e||(this.string(e)||this.array(e)||this.nodeList(e))&&0===e.length||this.object(e)&&0===Object.keys(e).length},getConstructor:function(e){return null===e||void 0===e?null:e.constructor},instanceOf:function(e,t){return Boolean(e&&t&&e instanceof t)}},getBrowser:function(){return{isIE:!!document.documentMode,isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)}},loadScript:function(e,t){if(!document.querySelectorAll('script[src="'+e+'"]').length){var i=document.createElement("script");i.src=e;var n=document.getElementsByTagName("script")[0];s.is.function(t)&&i.addEventListener("load",function(e){return t.call(null,e)},!1),n.parentNode.insertBefore(i,n)}},loadSprite:function(e,t){function i(e){this.innerHTML=e,document.body.insertBefore(this,document.body.childNodes[0])}if("string"==typeof e){var n="string"==typeof t;if(!n||!document.querySelectorAll("#"+t).length){var s=document.createElement("div");if(s.setAttribute("hidden",""),n&&s.setAttribute("id",t),a.storage){var l=window.localStorage.getItem("cache-"+t);if(null!==l){var o=JSON.parse(l);i.call(s,o.content)}}var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.open("GET",e,!0),r.onload=function(){a.storage&&window.localStorage.setItem("cache-"+t,JSON.stringify({content:r.responseText})),i.call(s,r.responseText)},r.send()}}},generateId:function(e){return e+"-"+Math.floor(1e4*Math.random())},inFrame:function(){try{return window.self!==window.top}catch(e){return!0}},wrap:function(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,s=e.parentNode,a=e.nextSibling;n.appendChild(e),a?s.insertBefore(n,a):s.appendChild(n)})},removeElement:function(e){return s.is.htmlElement(e)&&s.is.htmlElement(e.parentNode)?(e.parentNode.removeChild(e),e):null},insertAfter:function(e,t){t.parentNode.insertBefore(e,t.nextSibling)},createElement:function(e,t,i){var n=document.createElement(e);return s.is.object(t)&&s.setAttributes(n,t),s.is.string(i)&&(n.textContent=i),n},insertElement:function(e,t,i,n){t.appendChild(s.createElement(e,i,n))},emptyElement:function(e){for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1},setAttributes:function(e,t){Object.keys(t).forEach(function(i){e.setAttribute(i,t[i])})},getAttributesFromSelector:function(e,t){if(!s.is.string(e)||s.is.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),a=t.replace(".",""),l=t.replace(/[[\]]/g,"").split("="),o=l[0],r=l.length>1?l[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":s.is.object(n)&&s.is.string(n.class)&&(n.class+=" "+a),i.class=a;break;case"#":i.id=t.replace("#","");break;case"[":i[o]=r}}),i},toggleClass:function(e,t,i){if(s.is.htmlElement(e)){var n=e.classList.contains(t);return e.classList[i?"add":"remove"](t),i&&!n||!i&&n}return null},hasClass:function(e,t){return s.is.htmlElement(e)&&e.classList.contains(t)},matches:function(e,t){var i={Element:Element},n=i.matches||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||function(){return Array.from(document.querySelectorAll(t)).includes(this)};return n.call(e,t)},getElements:function(e){return this.elements.container.querySelectorAll(e)},getElement:function(e){return this.elements.container.querySelector(e)},findElements:function(){try{return this.elements.controls=s.getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:s.getElements.call(this,this.config.selectors.buttons.play),pause:s.getElement.call(this,this.config.selectors.buttons.pause),restart:s.getElement.call(this,this.config.selectors.buttons.restart),rewind:s.getElement.call(this,this.config.selectors.buttons.rewind),forward:s.getElement.call(this,this.config.selectors.buttons.forward),mute:s.getElement.call(this,this.config.selectors.buttons.mute),pip:s.getElement.call(this,this.config.selectors.buttons.pip),airplay:s.getElement.call(this,this.config.selectors.buttons.airplay),settings:s.getElement.call(this,this.config.selectors.buttons.settings),captions:s.getElement.call(this,this.config.selectors.buttons.captions),fullscreen:s.getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=s.getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:s.getElement.call(this,this.config.selectors.inputs.seek),volume:s.getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:s.getElement.call(this,this.config.selectors.display.buffer),duration:s.getElement.call(this,this.config.selectors.display.duration),currentTime:s.getElement.call(this,this.config.selectors.display.currentTime)},s.is.htmlElement(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector("."+this.config.classNames.tooltip)),!0}catch(e){return this.console.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},getFocusElement:function(){var e=document.activeElement;return e=e&&e!==document.body?document.querySelector(":focus"):null},trapFocus:function(){var e=this,t=s.getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=t[0],n=t[t.length-1];s.on(this.elements.container,"keydown",function(t){if("Tab"===t.key&&9===t.keyCode&&e.fullscreen.active){var a=s.getFocusElement();a!==n||t.shiftKey?a===i&&t.shiftKey&&(n.focus(),t.preventDefault()):(i.focus(),t.preventDefault())}},!1)},toggleListener:function(e,t,i,n,l,o){if(null!==e&&!s.is.undefined(e))if(s.is.nodeList(e))Array.from(e).forEach(function(e){e instanceof Node&&s.toggleListener.call(null,e,t,i,n,l,o)});else{var r=t.split(" "),c=!!s.is.boolean(o)&&o;a.passiveListeners&&(c={passive:!s.is.boolean(l)||l,capture:!!s.is.boolean(o)&&o}),r.forEach(function(t){e[n?"addEventListener":"removeEventListener"](t,i,c)})}},on:function(e,t,i,n,a){s.toggleListener(e,t,i,!0,n,a)},off:function(e,t,i,n,a){s.toggleListener(e,t,i,!1,n,a)},dispatchEvent:function(e,t,i,n){if(e&&t){var a=new CustomEvent(t,{bubbles:!!s.is.boolean(i)&&i,detail:Object.assign({},n,{plyr:this instanceof Plyr?this:null})});e.dispatchEvent(a)}},toggleState:function(e,t){if(s.is.htmlElement(e)){var i=s.is.boolean(t)?t:!e.getAttribute("aria-pressed");e.setAttribute("aria-pressed",i)}},getPercentage:function(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)},extend:function(){for(var e=arguments.length,t=Array(e),i=0;i0)&&(i?(e.decreaseVolume(.02),n=-1):(e.increaseVolume(.02),n=1)),(t.deltaY>0||t.deltaX<0)&&(i?(e.increaseVolume(.02),n=1):(e.decreaseVolume(.02),n=-1)),(1===n&&e.media.volume<1||-1===n&&e.media.volume>0)&&t.preventDefault()})},!1)}},d={addStyleHook:function(){s.toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),s.toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(e){e&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){if(u.media.call(this),!this.supported.ui)return this.console.warn("Basic support only for "+this.type),s.removeElement.call(this,"controls"),s.removeElement.call(this,"buttons.play"),void d.toggleNativeControls.call(this,!0);s.is.htmlElement(this.elements.controls)||(h.inject.call(this),u.controls.call(this)),s.is.htmlElement(this.elements.controls)&&(d.toggleNativeControls.call(this),o.setup.call(this),m.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.options.quality=[],d.timeUpdate.call(this),d.checkPlaying.call(this),this.ready=!0,s.dispatchEvent.call(this,this.media,"ready"))},displayDuration:function(){this.supported.ui&&(!this.elements.display.duration&&this.config.displayDuration&&this.paused&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.currentTime),this.elements.display.duration&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.duration),h.updateSeekTooltip.call(this))},setTitle:function(){var e=this.config.i18n.play;if(s.is.string(this.config.title)&&!s.is.empty(this.config.title)&&(e+=", "+this.config.title,this.elements.container.setAttribute("aria-label",this.config.title)),this.supported.ui&&(s.is.htmlElement(this.elements.buttons.play)&&this.elements.buttons.play.setAttribute("aria-label",e),s.is.htmlElement(this.elements.buttons.playLarge)&&this.elements.buttons.playLarge.setAttribute("aria-label",e)),this.isEmbed){var t=s.getElement.call(this,"iframe");if(!s.is.htmlElement(t))return;var i=s.is.empty(this.config.title)?"video":this.config.title;t.setAttribute("title",this.config.i18n.frameTitle.replace("{title}",i))}},checkPlaying:function(){s.toggleClass(this.elements.container,this.config.classNames.playing,!this.paused),s.toggleClass(this.elements.container,this.config.classNames.stopped,this.paused),this.toggleControls(this.paused)},updateVolume:function(){this.supported.ui&&(s.is.htmlElement(this.elements.inputs.volume)&&d.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),s.is.htmlElement(this.elements.buttons.mute)&&s.toggleState(this.elements.buttons.mute,this.muted||0===this.volume))},checkLoading:function(e){var t=this;this.loading="waiting"===e.type,clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){s.toggleClass(t.elements.container,t.config.classNames.loading,t.loading),t.toggleControls(t.loading)},this.loading?250:0)},setRange:function(e,t){s.is.htmlElement(e)&&(e.value=t,h.updateRangeFill.call(this,e))},setProgress:function(e,t){var i=s.is.undefined(t)?0:t,n=s.is.undefined(e)?this.elements.display.buffer:e;if(s.is.htmlElement(n)){n.value=i;var a=n.getElementsByTagName("span")[0];s.is.htmlElement(a)&&(a.childNodes[0].nodeValue=i)}},updateProgress:function(e){var t=this;if(this.supported.ui){var i=0;if(e)switch(e.type){case"timeupdate":case"seeking":i=s.getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&d.setRange.call(this,this.elements.inputs.seek,i);break;case"playing":case"progress":i=function(){var e=t.media.buffered;return e&&e.length?s.getPercentage(e.end(0),t.duration):s.is.number(e)?100*e:0}(),d.setProgress.call(this,this.elements.display.buffer,i)}}},updateTimeDisplay:function(e,t){if(!s.is.htmlElement(t))return null;var i=Number.isNaN(e)?0:e,n=parseInt(i%60,10),a=parseInt(i/60%60,10),l=parseInt(i/60/60%60,10),o=parseInt(this.duration/60/60%60,10)>0;n=("0"+n).slice(-2),a=("0"+a).slice(-2);var r=(o?l+":":"")+a+":"+n;return t.textContent=r,r},timeUpdate:function(e){d.updateTimeDisplay.call(this,this.currentTime,this.elements.display.currentTime),e&&"timeupdate"===e.type&&this.media.seeking||d.updateProgress.call(this,e)}},p=s.getBrowser(),h={updateRangeFill:function(e){if(p.isWebkit){var t=s.is.event(e)?e.target:e;if(s.is.htmlElement(t)&&"range"===t.getAttribute("type")){s.is.htmlElement(this.elements.styleSheet)||(this.elements.styleSheet=s.createElement("style"),this.elements.container.appendChild(this.elements.styleSheet));var i=this.elements.styleSheet.sheet,n=t.value/t.max*100,a="#"+t.id+"::-webkit-slider-runnable-track",l="{ background-image: linear-gradient(to right, currentColor "+n+"%, transparent "+n+"%) }",o=Array.from(i.rules).findIndex(function(e){return e.selectorText===a});-1!==o&&i.deleteRule(o),i.insertRule([a,l].join(" "))}}},getIconUrl:function(){return{url:this.config.iconUrl,absolute:0===this.config.iconUrl.indexOf("http")||p.isIE&&!window.svg4everybody}},createIcon:function(e,t){var i=h.getIconUrl.call(this),n=(i.absolute?"":i.url)+"#"+this.config.iconPrefix,a=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttributes(a,s.extend(t,{role:"presentation"}));var l=document.createElementNS("http://www.w3.org/2000/svg","use"),o=n+"-"+e;return"href"in l?l.setAttribute("href",o):l.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),a.appendChild(l),a},createLabel:function(e){var t=this.config.i18n[e];switch(e){case"pip":t="PIP";break;case"airplay":t="AirPlay"}return s.createElement("span",{class:this.config.classNames.hidden},t)},createBadge:function(e){var t=s.createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(s.createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=s.createElement("button"),n=Object.assign({},t),a=e,l=void 0,o=void 0,r=void 0;switch("type"in n||(n.type="button"),"class"in n?-1===n.class.indexOf(this.config.classNames.control)&&(n.class+=" "+this.config.classNames.control):n.class=this.config.classNames.control,a){case"mute":r="toggleMute",l="volume",o="muted";break;case"captions":r="toggleCaptions",l="captions-off",o="captions-on";break;case"fullscreen":r="toggleFullscreen",l="enter-fullscreen",o="exit-fullscreen";break;case"play-large":n.class="plyr__play-large",a="play",r="play",l="play";break;default:r=a,l=a}return s.extend(n,s.getAttributesFromSelector(this.config.selectors.buttons[a],n)),s.is.string(o)?(i.appendChild(h.createIcon.call(this,o,{class:"icon--pressed"})),i.appendChild(h.createIcon.call(this,l,{class:"icon--not-pressed"}))):i.appendChild(h.createIcon.call(this,l)),i.appendChild(h.createLabel.call(this,r)),s.setAttributes(i,n),this.elements.buttons[a]=i,i},createRange:function(e,t){var i=s.createElement("label",{for:t.id,class:this.config.classNames.hidden},this.config.i18n[e]),n=s.createElement("input",s.extend(s.getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off"},t));return this.elements.inputs[e]=n,h.updateRangeFill.call(this,n),{label:i,input:n}},createProgress:function(e,t){var i=s.createElement("progress",s.extend(s.getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0},t));if("volume"!==e){i.appendChild(s.createElement("span",null,"0"));var n="";switch(e){case"played":n=this.config.i18n.played;break;case"buffer":n=this.config.i18n.buffered}i.textContent="% "+n.toLowerCase()}return this.elements.display[e]=i,i},createTime:function(e){var t=s.createElement("span",{class:"plyr__time"});return t.appendChild(s.createElement("span",{class:this.config.classNames.hidden},this.config.i18n[e])),t.appendChild(s.createElement("span",s.getAttributesFromSelector(this.config.selectors.display[e]),"00:00")),this.elements.display[e]=t,t},updateSeekTooltip:function(e){if(this.config.tooltips.seek&&s.is.htmlElement(this.elements.inputs.seek)&&s.is.htmlElement(this.elements.display.seekTooltip)&&0!==this.duration){var t=0,i=this.elements.inputs.seek.getBoundingClientRect(),n=this.config.classNames.tooltip+"--visible";if(s.is.event(e))t=100/i.width*(e.pageX-i.left);else{if(!s.hasClass(this.elements.display.seekTooltip,n))return;t=this.elements.display.seekTooltip.style.left.replace("%","")}t<0?t=0:t>100&&(t=100),d.updateTimeDisplay.call(this,this.duration/100*t,this.elements.display.seekTooltip),this.elements.display.seekTooltip.style.left=t+"%",s.is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&s.toggleClass(this.elements.display.seekTooltip,n,"mouseenter"===e.type)}},toggleTab:function(e,t){var i=this.elements.settings.tabs[e],n=this.elements.settings.panes[e];s.is.htmlElement(i)&&(t?i.removeAttribute("hidden"):i.setAttribute("hidden","")),s.is.htmlElement(n)&&(t?n.removeAttribute("hidden"):n.setAttribute("hidden",""))},setQualityMenu:function(e){var t=this,i=this.elements.settings.panes.quality.querySelector("ul");s.is.array(e)?this.options.quality=e.filter(function(e){return t.config.quality.options.includes(e)}):this.options.quality=this.config.quality.options;var n=!s.is.empty(this.options.quality)&&"youtube"===this.type;if(h.toggleTab.call(this,"quality",n),n){s.emptyElement(i);var a=function(e){var i="";switch(e){case"hd2160":i="4K";break;case"hd1440":i="WQHD";break;case"hd1080":case"hd720":i="HD"}return i.length?h.createBadge.call(t,i):null};this.options.quality.forEach(function(e){var n=s.createElement("li"),l=s.createElement("label",{class:t.config.classNames.control}),o=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.quality),{type:"radio",name:"plyr-quality",value:e}));l.appendChild(o),l.appendChild(document.createTextNode(h.getLabel.call(t,"quality",e)));var r=a(e);s.is.htmlElement(r)&&l.appendChild(r),n.appendChild(l),i.appendChild(n)}),h.updateSetting.call(this,"quality",i)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?"Normal":t+"×";case"quality":switch(t){case"hd2160":return"2160P";case"hd1440":return"1440P";case"hd1080":return"1080P";case"hd720":return"720P";case"large":return"480P";case"medium":return"360P";case"small":return"240P";case"tiny":return"Tiny";case"default":return"Auto";default:return t}case"captions":return h.getLanguage.call(this);default:return null}},updateSetting:function(e,t){var i=this.elements.settings.panes[e],n=null,a=t;switch(e){case"captions":n=this.captions.language,this.captions.enabled||(n="");break;default:if(n=this[e],s.is.empty(n)&&(n=this.config[e].default),!this.options[e].includes(n))return void this.console.warn("Unsupported value of '"+n+"' for "+e);if(!this.config[e].options.includes(n))return void this.console.warn("Disabled value of '"+n+"' for "+e)}s.is.htmlElement(a)||(a=i&&i.querySelector("ul"));var l=a&&a.querySelector('input[value="'+n+'"]');s.is.htmlElement(l)&&(l.checked=!0,this.elements.settings.tabs[e].querySelector("."+this.config.classNames.menu.value).innerHTML=h.getLabel.call(this,e,n))},setLoopMenu:function(){var e=this,t=this.elements.settings.panes.loop.querySelector("ul");this.elements.settings.tabs.loop.removeAttribute("hidden"),this.elements.settings.panes.loop.removeAttribute("hidden");var i=!s.is.empty(this.loop.options);h.toggleTab.call(this,"loop",i),s.emptyElement(t),["start","end","all","reset"].forEach(function(i){var n=s.createElement("li"),a=s.createElement("button",s.extend(s.getAttributesFromSelector(e.config.selectors.buttons.loop),{type:"button",class:e.config.classNames.control,"data-plyr-loop-action":i}),e.config.i18n[i]);if(["start","end"].includes(i)){var l=h.createBadge.call(e,"00:00");a.appendChild(l)}n.appendChild(a),t.appendChild(n)})},getLanguage:function(){return this.supported.ui?!a.textTracks||s.is.empty(this.captions.tracks)?this.config.i18n.none:this.captions.enabled?this.captions.currentTrack.label:this.config.i18n.disabled:null},setCaptionsMenu:function(){var e=this,t=this.elements.settings.panes.captions.querySelector("ul"),i=!s.is.empty(this.captions.tracks);if(h.toggleTab.call(this,"captions",i),s.emptyElement(t),!s.is.empty(this.captions.tracks)){var n=Array.from(this.captions.tracks).map(function(e){return{language:e.language,badge:!0,label:s.is.empty(e.label)?e.language.toUpperCase():e.label}});n.unshift({language:"",label:this.config.i18n.none}),n.forEach(function(i){var n=s.createElement("li"),a=s.createElement("label",{class:e.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(e.config.selectors.inputs.language),{type:"radio",name:"plyr-language",value:i.language}));i.language.toLowerCase()===e.captions.language.toLowerCase()&&(l.checked=!0),a.appendChild(l),a.appendChild(document.createTextNode(i.label||i.language)),i.badge&&a.appendChild(h.createBadge.call(e,i.language.toUpperCase())),n.appendChild(a),t.appendChild(n)}),h.updateSetting.call(this,"captions",t)}},setSpeedMenu:function(e){var t=this;s.is.array(e)?this.options.speed=e.filter(function(e){return t.config.speed.options.includes(e)}):this.options.speed=this.config.speed.options;var i=!s.is.empty(this.options.speed);if(h.toggleTab.call(this,"speed",i),i){var n=this.elements.settings.panes.speed.querySelector("ul");this.elements.settings.tabs.speed.removeAttribute("hidden"),this.elements.settings.panes.speed.removeAttribute("hidden"),s.emptyElement(n),this.options.speed.forEach(function(e){var i=s.createElement("li"),a=s.createElement("label",{class:t.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.speed),{type:"radio",name:"plyr-speed",value:e}));a.appendChild(l),a.insertAdjacentHTML("beforeend",h.getLabel.call(t,"speed",e)),i.appendChild(a),n.appendChild(i)}),h.updateSetting.call(this,"speed",n)}},toggleMenu:function(e){var t=this.elements.settings.form,i=this.elements.buttons.settings,n=s.is.boolean(e)?e:t&&"true"===t.getAttribute("aria-hidden");if(s.is.event(e)){var a=t&&t.contains(e.target),l=e.target===this.elements.buttons.settings;if(a||!a&&!l&&n)return;l&&e.stopPropagation()}i&&i.setAttribute("aria-expanded",n),t&&(t.setAttribute("aria-hidden",!n),n?t.removeAttribute("tabindex"):t.setAttribute("tabindex",-1))},getTabSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.setAttribute("aria-hidden",!1),Array.from(t.querySelectorAll("input[name]")).forEach(function(e){var t=e.getAttribute("name");e.setAttribute("name",t+"-clone")}),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return s.removeElement(t),{width:i,height:n}},showTab:function(e){var t=this.elements.settings.menu,i=e.target,n="false"===i.getAttribute("aria-expanded"),l=document.getElementById(i.getAttribute("aria-controls"));if(s.is.htmlElement(l)&&"tabpanel"===l.getAttribute("role")){var o=t.querySelector('[role="tabpanel"][aria-hidden="false"]'),r=o.parentNode;if(Array.from(t.querySelectorAll('[aria-controls="'+o.getAttribute("id")+'"]')).forEach(function(e){e.setAttribute("aria-expanded",!1)}),a.transitions&&!a.reducedMotion){r.style.width=o.scrollWidth+"px",r.style.height=o.scrollHeight+"px";var c=h.getTabSize.call(this,l),u=function e(t){t.target===r&&["width","height"].includes(t.propertyName)&&(r.style.width="",r.style.height="",s.off(r,s.transitionEnd,e))};s.on(r,s.transitionEnd,u),r.style.width=c.width+"px",r.style.height=c.height+"px"}o.setAttribute("aria-hidden",!0),o.setAttribute("tabindex",-1),l.setAttribute("aria-hidden",!n),i.setAttribute("aria-expanded",n),l.removeAttribute("tabindex")}},create:function(e){var t=this;if(s.is.empty(this.config.controls))return null;var i=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(h.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(h.createButton.call(this,"rewind")),this.config.controls.includes("play")&&(i.appendChild(h.createButton.call(this,"play")),i.appendChild(h.createButton.call(this,"pause"))),this.config.controls.includes("fast-forward")&&i.appendChild(h.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=s.createElement("span",s.getAttributesFromSelector(this.config.selectors.progress)),l=h.createRange.call(this,"seek",{id:"plyr-seek-"+e.id});if(n.appendChild(l.label),n.appendChild(l.input),n.appendChild(h.createProgress.call(this,"buffer")),this.config.tooltips.seek){var o=s.createElement("span",{role:"tooltip",class:this.config.classNames.tooltip},"00:00");n.appendChild(o),this.elements.display.seekTooltip=o}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(h.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(h.createTime.call(this,"duration")),this.config.controls.includes("mute")&&i.appendChild(h.createButton.call(this,"mute")),this.config.controls.includes("volume")){var r=s.createElement("span",{class:"plyr__volume"}),c={max:1,step:.05,value:this.config.volume},u=h.createRange.call(this,"volume",s.extend(c,{id:"plyr-volume-"+e.id}));r.appendChild(u.label),r.appendChild(u.input),i.appendChild(r)}if(this.config.controls.includes("captions")&&i.appendChild(h.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!s.is.empty(this.config.settings)){var d=s.createElement("div",{class:"plyr__menu"});d.appendChild(h.createButton.call(this,"settings",{id:"plyr-settings-toggle-"+e.id,"aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id,"aria-expanded":!1}));var p=s.createElement("form",{class:"plyr__menu__container",id:"plyr-settings-"+e.id,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tablist",tabindex:-1}),m=s.createElement("div"),g=s.createElement("div",{id:"plyr-settings-"+e.id+"-home","aria-hidden":!1,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tabpanel"}),f=s.createElement("ul",{role:"tablist"});this.config.settings.forEach(function(i){var n=s.createElement("li",{role:"tab",hidden:""}),a=s.createElement("button",s.extend(s.getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--forward",id:"plyr-settings-"+e.id+"-"+i+"-tab","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-"+i,"aria-expanded":!1}),t.config.i18n[i]),l=s.createElement("span",{class:t.config.classNames.menu.value});l.innerHTML=e[i],a.appendChild(l),n.appendChild(a),f.appendChild(n),t.elements.settings.tabs[i]=n}),g.appendChild(f),m.appendChild(g),this.config.settings.forEach(function(i){var n=s.createElement("div",{id:"plyr-settings-"+e.id+"-"+i,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-"+e.id+"-"+i+"-tab",role:"tabpanel",tabindex:-1,hidden:""}),a=s.createElement("button",{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--back","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-home","aria-expanded":!1},t.config.i18n[i]);n.appendChild(a);var l=s.createElement("ul");n.appendChild(l),m.appendChild(n),t.elements.settings.panes[i]=n}),p.appendChild(m),d.appendChild(p),i.appendChild(d),this.elements.settings.form=p,this.elements.settings.menu=d}return this.config.controls.includes("pip")&&a.pip&&i.appendChild(h.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&a.airplay&&i.appendChild(h.createButton.call(this,"airplay")),this.config.controls.includes("fullscreen")&&i.appendChild(h.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(h.createButton.call(this,"play-large")),this.elements.controls=i,this.config.controls.includes("settings")&&this.config.settings.includes("speed")&&h.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=h.getIconUrl.call(this);t.absolute&&s.loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;i=s.is.string(this.config.controls)?this.config.controls:s.is.function(this.config.controls)?this.config.controls({id:this.id,seektime:this.config.seekTime,title:this.config.title}):h.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:h.getLanguage.call(this)});var n=void 0;if(s.is.string(this.config.selectors.controls.container)&&(n=document.querySelector(this.config.selectors.controls.container)),s.is.htmlElement(n)||(n=this.elements.container),s.is.htmlElement(i)?n.appendChild(i):n.insertAdjacentHTML("beforeend",i),s.is.htmlElement(this.elements.controls)&&s.findElements.call(this),this.config.tooltips.controls){var a=s.getElements.call(this,[this.config.selectors.controls.wrapper," ",this.config.selectors.labels," .",this.config.classNames.hidden].join(""));Array.from(a).forEach(function(t){s.toggleClass(t,e.config.classNames.hidden,!1),s.toggleClass(t,e.config.classNames.tooltip,!0)})}}},m={setup:function(){var e=this;if(this.supported.ui){if(s.is.empty(r.get.call(this).language)?s.is.empty(this.captions.language)&&(this.captions.language=this.config.captions.language.toLowerCase()):this.captions.language=r.get.call(this).language,s.is.boolean(this.captions.enabled)||(s.is.empty(r.get.call(this).language)?this.captions.enabled=this.config.captions.active:this.captions.enabled=r.get.call(this).captions),!["video","vimeo"].includes(this.type)||"video"===this.type&&!a.textTracks)return this.captions.tracks=null,void(this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this));if(s.is.htmlElement(this.elements.captions)||(this.elements.captions=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.captions)),s.insertAfter(this.elements.captions,this.elements.wrapper)),"video"===this.type&&(this.captions.tracks=this.media.textTracks),s.toggleClass(this.elements.container,this.config.classNames.captions.enabled,!s.is.empty(this.captions.tracks)),!s.is.empty(this.captions.tracks)){m.show.call(this);var t=function(){e.captions.currentTrack=null,Array.from(e.captions.tracks).forEach(function(t){t.language===e.captions.language.toLowerCase()&&(e.captions.currentTrack=t)})};if(t(),!s.is.track(this.captions.currentTrack)){var i=this.config.captions.language;this.captions.language=i,t(),s.is.track(this.captions.currentTrack)||this.toggleCaptions(!1),h.updateSetting.call(this,"captions")}if("video"===this.type){Array.from(this.captions.tracks).forEach(function(t){s.off(t,"cuechange",function(t){return m.setCue.call(e,t)}),t.mode="hidden"});var n=this.captions.currentTrack&&["captions","subtitles"].includes(this.captions.currentTrack.kind);s.is.track(this.captions.currentTrack)&&n&&(s.on(this.captions.currentTrack,"cuechange",function(t){return m.setCue.call(e,t)}),this.captions.currentTrack.activeCues&&this.captions.currentTrack.activeCues.length>0&&m.setCue.call(this,this.captions.currentTrack))}else"vimeo"===this.type&&this.captions.active&&this.embed.enableTextTrack(this.captions.language);this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this)}}},setCue:function(e){var t=(s.is.event(e)?e.target:e).activeCues[0];s.is.cue(t)?m.set.call(this,t.getCueAsHTML()):m.set.call(this),s.dispatchEvent.call(this,this.media,"cuechange")},set:function(e){if(this.supported.ui)if(s.is.htmlElement(this.elements.captions)){var t=s.createElement("span");s.emptyElement(this.elements.captions);var i=s.is.undefined(e)?"":e;s.is.string(i)?t.textContent=i.trim():t.appendChild(i),this.elements.captions.appendChild(t)}else this.console.warn("No captions element to render to")},show:function(){if(s.is.htmlElement(this.elements.buttons.captions)){var e=r.get.call(this).captions;s.is.boolean(e)?this.captions.active=e:e=this.config.captions.active,e&&(s.toggleClass(this.elements.container,this.config.classNames.captions.active,!0),s.toggleState(this.elements.buttons.captions,!0))}}},g={setup:function(){var e=this,t=s.parseYouTubeId(this.embedId),i=s.getElements.call(this,'[id^="'+this.type+'-"]');Array.from(i).forEach(s.removeElement),s.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),g.setAspectRatio.call(this),this.media.setAttribute("id",s.generateId(this.type)),s.is.object(window.YT)?g.ready.call(this,t):(s.loadScript(this.config.urls.youtube.api),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){g.ready.call(e,t)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},setAspectRatio:function(){var e=this.config.ratio.split(":");this.elements.wrapper.style.paddingBottom=100/e[0]*e[1]+"%"},ready:function(e){var t=this;t.embed=new window.YT.Player(t.media.id,{videoId:e,playerVars:{autoplay:t.config.autoplay?1:0,controls:t.supported.ui?0:1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1,disablekb:1,playsinline:1,origin:window&&window.location.hostname,widget_referrer:window&&window.location.href,cc_load_policy:this.captions.active?1:0,cc_lang_pref:this.config.captions.language},events:{onError:function(e){s.dispatchEvent.call(t,t.media,"error",!0,{code:e.data,embed:e.target})},onPlaybackQualityChange:function(e){var i=e.target;t.media.quality=i.getPlaybackQuality(),s.dispatchEvent.call(t,t.media,"qualitychange")},onPlaybackRateChange:function(e){var i=e.target;t.media.playbackRate=i.getPlaybackRate(),s.dispatchEvent.call(t,t.media,"ratechange")},onReady:function(e){var i=e.target;t.media.play=function(){i.playVideo(),t.media.paused=!1},t.media.pause=function(){i.pauseVideo(),t.media.paused=!0},t.media.stop=function(){i.stopVideo(),t.media.paused=!0},t.media.duration=i.getDuration(),t.media.paused=!0,t.media.currentTime=0,Object.defineProperty(t.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(e){t.media.seeking=!0,s.dispatchEvent.call(t,t.media,"seeking"),i.seekTo(e)}}),Object.defineProperty(t.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}}),Object.defineProperty(t.media,"quality",{get:function(){return i.getPlaybackQuality()},set:function(e){s.dispatchEvent.call(t,t.media,"qualityrequested",!1,{quality:e}),i.setPlaybackQuality(e)}});var n=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return n},set:function(e){n=e,i.setVolume(100*n),s.dispatchEvent.call(t,t.media,"volumechange")}});var a=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return a},set:function(e){var n=s.is.boolean(e)?e:a;a=n,i[n?"mute":"unMute"](),s.dispatchEvent.call(t,t.media,"volumechange")}}),Object.defineProperty(t.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),t.config.controls.includes("settings")&&t.config.settings.includes("speed")&&h.setSpeedMenu.call(t,i.getAvailablePlaybackRates()),t.config.title=i.getVideoData().title,t.supported.ui&&t.media.setAttribute("tabindex",-1),s.dispatchEvent.call(t,t.media,"timeupdate"),s.dispatchEvent.call(t,t.media,"durationchange"),window.clearInterval(t.timers.buffering),t.timers.buffering=window.setInterval(function(){t.media.buffered=i.getVideoLoadedFraction(),(null===t.media.lastBuffered||t.media.lastBuffered1&&void 0!==arguments[1]&&arguments[1],n=function(){if(document.body.style.overflow="",t.embed=null,t.embedId=null,i)Object.keys(t.elements).length&&(t.elements.buttons&&t.elements.buttons.play&&Array.from(t.elements.buttons.play).forEach(function(e){return s.removeElement(e)}),s.removeElement(t.elements.captions),s.removeElement(t.elements.controls),s.removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),s.is.function(e)&&e();else{var n=t.elements.container.parentNode;s.is.htmlElement(n)&&n.replaceChild(t.elements.original,t.elements.container),s.dispatchEvent.call(t,t.elements.original,"destroyed",!0),s.is.function(e)&&e.call(t.elements.original),t.elements=null}};switch(this.type){case"youtube":window.clearInterval(this.timers.buffering),window.clearInterval(this.timers.playing),this.embed.destroy(),n();break;case"vimeo":this.embed.unload().then(n),window.setTimeout(n,200);break;case"video":case"audio":d.toggleNativeControls.call(this,!0),n()}}},{key:"isHTML5",get:function(){return n.html5.includes(this.type)}},{key:"isEmbed",get:function(){return n.embed.includes(this.type)}},{key:"paused",get:function(){return this.media.paused}},{key:"currentTime",set:function(e){var t=0;s.is.number(e)&&(t=e),t<0?t=0:t>this.duration&&(t=this.duration),this.media.currentTime=t.toFixed(4),this.console.log("Seeking to "+this.currentTime+" seconds")},get:function(){return Number(this.media.currentTime)}},{key:"seeking",get:function(){return this.media.seeking}},{key:"duration",get:function(){var e=parseInt(this.config.duration,10),t=Number(this.media.duration);return Number.isNaN(e)?t:e}},{key:"volume",set:function(e){var t=e;s.is.string(t)&&(t=Number(t)),s.is.number(t)||(t=r.get.call(this).volume),s.is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,this.muted&&t>0&&(this.muted=!1)},get:function(){return this.media.volume}},{key:"muted",set:function(e){var t=e;s.is.boolean(t)||(t=r.get.call(this).muted),s.is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return this.media.muted}},{key:"speed",set:function(e){var t=null;(t=s.is.number(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).speed:this.config.speed.selected)<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.console.warn("Unsupported speed ("+t+")")},get:function(){return this.media.playbackRate}},{key:"quality",set:function(e){var t=null;t=s.is.string(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).quality:this.config.quality.selected,this.options.quality.includes(t)?(this.config.quality.selected=t,this.media.quality=t):this.console.warn("Unsupported quality option ("+t+")")},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=s.is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return this.media.loop}},{key:"source",set:function(e){v.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"poster",set:function(e){"video"===this.type?s.is.string(e)&&this.media.setAttribute("poster",e):this.console.warn("Poster can only be set on HTML5 video")},get:function(){return"video"!==this.type?null:this.media.getAttribute("poster")}},{key:"autoplay",get:function(){return this.config.autoplay},set:function(e){var t=s.is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t}},{key:"language",set:function(e){if(s.is.string(e)){var t=e.toLowerCase();this.captions.language!==t&&(this.toggleCaptions(!0),this.captions.language=t,s.dispatchEvent.call(this,this.media,"captionchange"),m.set.call(this),m.setup.call(this))}},get:function(){return this.captions.language}},{key:"pip",set:function(e){var t={pip:"picture-in-picture",inline:"inline"};if(a.pip){var i=s.is.boolean(e)?e:this.pip===t.inline;this.media.webkitSetPresentationMode(i?t.pip:t.inline)}},get:function(){return a.pip?this.media.webkitPresentationMode:null}}]),e}()}); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";function e(){var e=window.localStorage.getItem(this.config.storage.key);return s.is.empty(e)?{}:JSON.parse(e)}function t(t){if(a.storage&&this.config.storage.enabled&&s.is.object(t)){var i=e.call(this);s.extend(i,t),window.localStorage.setItem(this.config.storage.key,JSON.stringify(i))}}var i={enabled:!0,title:"",debug:!1,autoplay:!1,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,showPosterOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/2.0.10/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:"default",options:["hd2160","hd1440","hd1080","hd720","large","medium","small","tiny","default"]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:window.navigator.language.split("-")[0]},fullscreen:{enabled:!0,fallback:!0},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed","loop"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",seek:"Seek",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",toggleMute:"Toggle Mute",toggleCaptions:"Toggle Captions",toggleFullscreen:"Toggle Fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",speed:"Speed",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",none:"None",disabled:"Disabled"},urls:{vimeo:{api:"https://player.vimeo.com/api/player.js"},youtube:{api:"https://www.youtube.com/iframe_api"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,forward:null,mute:null,volume:null,captions:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","qualityrequested"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',forward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress--buffer",played:".plyr__progress--played",loop:".plyr__progress--loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{video:"plyr__video-wrapper",embed:"plyr__video-embed",control:"plyr__control",type:"plyr--{0}",stopped:"plyr--stopped",playing:"plyr--playing",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",menu:{value:"plyr__menu__value",badge:"plyr__badge"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus"}},n={embed:["youtube","vimeo"],html5:["video","audio"]},s={is:{object:function(e){return this.getConstructor(e)===Object},number:function(e){return this.getConstructor(e)===Number&&!Number.isNaN(e)},string:function(e){return this.getConstructor(e)===String},boolean:function(e){return this.getConstructor(e)===Boolean},function:function(e){return this.getConstructor(e)===Function},array:function(e){return!this.undefined(e)&&Array.isArray(e)},nodeList:function(e){return!this.undefined(e)&&e instanceof NodeList},htmlElement:function(e){return!this.undefined(e)&&e instanceof HTMLElement},event:function(e){return!this.undefined(e)&&e instanceof Event},cue:function(e){return this.instanceOf(e,window.TextTrackCue)||this.instanceOf(e,window.VTTCue)},track:function(e){return!this.undefined(e)&&(this.instanceOf(e,window.TextTrack)||"string"==typeof e.kind)},undefined:function(e){return null!==e&&void 0===e},empty:function(e){return null===e||void 0===e||(this.string(e)||this.array(e)||this.nodeList(e))&&0===e.length||this.object(e)&&0===Object.keys(e).length},getConstructor:function(e){return null===e||void 0===e?null:e.constructor},instanceOf:function(e,t){return Boolean(e&&t&&e instanceof t)}},getBrowser:function(){return{isIE:!!document.documentMode,isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)}},loadScript:function(e,t){if(!document.querySelectorAll('script[src="'+e+'"]').length){var i=document.createElement("script");i.src=e;var n=document.getElementsByTagName("script")[0];s.is.function(t)&&i.addEventListener("load",function(e){return t.call(null,e)},!1),n.parentNode.insertBefore(i,n)}},loadSprite:function(e,t){function i(e){this.innerHTML=e,document.body.insertBefore(this,document.body.childNodes[0])}if("string"==typeof e){var n="string"==typeof t;if(!n||!document.querySelectorAll("#"+t).length){var s=document.createElement("div");if(s.setAttribute("hidden",""),n&&s.setAttribute("id",t),a.storage){var l=window.localStorage.getItem("cache-"+t);if(null!==l){var o=JSON.parse(l);i.call(s,o.content)}}var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.open("GET",e,!0),r.onload=function(){a.storage&&window.localStorage.setItem("cache-"+t,JSON.stringify({content:r.responseText})),i.call(s,r.responseText)},r.send()}}},generateId:function(e){return e+"-"+Math.floor(1e4*Math.random())},inFrame:function(){try{return window.self!==window.top}catch(e){return!0}},wrap:function(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,s=e.parentNode,a=e.nextSibling;n.appendChild(e),a?s.insertBefore(n,a):s.appendChild(n)})},removeElement:function(e){return s.is.htmlElement(e)&&s.is.htmlElement(e.parentNode)?(e.parentNode.removeChild(e),e):null},insertAfter:function(e,t){t.parentNode.insertBefore(e,t.nextSibling)},createElement:function(e,t,i){var n=document.createElement(e);return s.is.object(t)&&s.setAttributes(n,t),s.is.string(i)&&(n.textContent=i),n},insertElement:function(e,t,i,n){t.appendChild(s.createElement(e,i,n))},emptyElement:function(e){for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1},setAttributes:function(e,t){Object.keys(t).forEach(function(i){e.setAttribute(i,t[i])})},getAttributesFromSelector:function(e,t){if(!s.is.string(e)||s.is.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),a=t.replace(".",""),l=t.replace(/[[\]]/g,"").split("="),o=l[0],r=l.length>1?l[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":s.is.object(n)&&s.is.string(n.class)&&(n.class+=" "+a),i.class=a;break;case"#":i.id=t.replace("#","");break;case"[":i[o]=r}}),i},toggleClass:function(e,t,i){if(s.is.htmlElement(e)){var n=e.classList.contains(t);return e.classList[i?"add":"remove"](t),i&&!n||!i&&n}return null},hasClass:function(e,t){return s.is.htmlElement(e)&&e.classList.contains(t)},matches:function(e,t){var i={Element:Element},n=i.matches||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||function(){return Array.from(document.querySelectorAll(t)).includes(this)};return n.call(e,t)},getElements:function(e){return this.elements.container.querySelectorAll(e)},getElement:function(e){return this.elements.container.querySelector(e)},findElements:function(){try{return this.elements.controls=s.getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:s.getElements.call(this,this.config.selectors.buttons.play),pause:s.getElement.call(this,this.config.selectors.buttons.pause),restart:s.getElement.call(this,this.config.selectors.buttons.restart),rewind:s.getElement.call(this,this.config.selectors.buttons.rewind),forward:s.getElement.call(this,this.config.selectors.buttons.forward),mute:s.getElement.call(this,this.config.selectors.buttons.mute),pip:s.getElement.call(this,this.config.selectors.buttons.pip),airplay:s.getElement.call(this,this.config.selectors.buttons.airplay),settings:s.getElement.call(this,this.config.selectors.buttons.settings),captions:s.getElement.call(this,this.config.selectors.buttons.captions),fullscreen:s.getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=s.getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:s.getElement.call(this,this.config.selectors.inputs.seek),volume:s.getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:s.getElement.call(this,this.config.selectors.display.buffer),duration:s.getElement.call(this,this.config.selectors.display.duration),currentTime:s.getElement.call(this,this.config.selectors.display.currentTime)},s.is.htmlElement(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector("."+this.config.classNames.tooltip)),!0}catch(e){return this.console.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},getFocusElement:function(){var e=document.activeElement;return e=e&&e!==document.body?document.querySelector(":focus"):null},trapFocus:function(){var e=this,t=s.getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=t[0],n=t[t.length-1];s.on(this.elements.container,"keydown",function(t){if("Tab"===t.key&&9===t.keyCode&&e.fullscreen.active){var a=s.getFocusElement();a!==n||t.shiftKey?a===i&&t.shiftKey&&(n.focus(),t.preventDefault()):(i.focus(),t.preventDefault())}},!1)},toggleListener:function(e,t,i,n,l,o){if(null!==e&&!s.is.undefined(e))if(s.is.nodeList(e))Array.from(e).forEach(function(e){e instanceof Node&&s.toggleListener.call(null,e,t,i,n,l,o)});else{var r=t.split(" "),c=!!s.is.boolean(o)&&o;a.passiveListeners&&(c={passive:!s.is.boolean(l)||l,capture:!!s.is.boolean(o)&&o}),r.forEach(function(t){e[n?"addEventListener":"removeEventListener"](t,i,c)})}},on:function(e,t,i,n,a){s.toggleListener(e,t,i,!0,n,a)},off:function(e,t,i,n,a){s.toggleListener(e,t,i,!1,n,a)},dispatchEvent:function(e,t,i,n){if(e&&t){var a=new CustomEvent(t,{bubbles:!!s.is.boolean(i)&&i,detail:Object.assign({},n,{plyr:this instanceof Plyr?this:null})});e.dispatchEvent(a)}},toggleState:function(e,t){if(s.is.htmlElement(e)){var i=s.is.boolean(t)?t:!e.getAttribute("aria-pressed");e.setAttribute("aria-pressed",i)}},getPercentage:function(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)},extend:function(){for(var e=arguments.length,t=Array(e),i=0;i0)&&(i?(e.decreaseVolume(.02),n=-1):(e.increaseVolume(.02),n=1)),(t.deltaY>0||t.deltaX<0)&&(i?(e.increaseVolume(.02),n=1):(e.decreaseVolume(.02),n=-1)),(1===n&&e.media.volume<1||-1===n&&e.media.volume>0)&&t.preventDefault()})},!1)}},d={addStyleHook:function(){s.toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),s.toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(e){e&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){if(u.media.call(this),!this.supported.ui)return this.console.warn("Basic support only for "+this.type),s.removeElement.call(this,"controls"),s.removeElement.call(this,"buttons.play"),void d.toggleNativeControls.call(this,!0);s.is.htmlElement(this.elements.controls)||(h.inject.call(this),u.controls.call(this)),s.is.htmlElement(this.elements.controls)&&(d.toggleNativeControls.call(this),o.setup.call(this),m.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.options.quality=[],d.timeUpdate.call(this),d.checkPlaying.call(this),this.ready=!0,s.dispatchEvent.call(this,this.media,"ready"))},displayDuration:function(){this.supported.ui&&(!this.elements.display.duration&&this.config.displayDuration&&this.paused&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.currentTime),this.elements.display.duration&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.duration),h.updateSeekTooltip.call(this))},setTitle:function(){var e=this.config.i18n.play;if(s.is.string(this.config.title)&&!s.is.empty(this.config.title)&&(e+=", "+this.config.title,this.elements.container.setAttribute("aria-label",this.config.title)),this.supported.ui&&(s.is.htmlElement(this.elements.buttons.play)&&this.elements.buttons.play.setAttribute("aria-label",e),s.is.htmlElement(this.elements.buttons.playLarge)&&this.elements.buttons.playLarge.setAttribute("aria-label",e)),this.isEmbed){var t=s.getElement.call(this,"iframe");if(!s.is.htmlElement(t))return;var i=s.is.empty(this.config.title)?"video":this.config.title;t.setAttribute("title",this.config.i18n.frameTitle.replace("{title}",i))}},checkPlaying:function(){s.toggleClass(this.elements.container,this.config.classNames.playing,!this.paused),s.toggleClass(this.elements.container,this.config.classNames.stopped,this.paused),this.toggleControls(this.paused)},updateVolume:function(){this.supported.ui&&(s.is.htmlElement(this.elements.inputs.volume)&&d.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),s.is.htmlElement(this.elements.buttons.mute)&&s.toggleState(this.elements.buttons.mute,this.muted||0===this.volume))},checkLoading:function(e){var t=this;this.loading="waiting"===e.type,clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){s.toggleClass(t.elements.container,t.config.classNames.loading,t.loading),t.toggleControls(t.loading)},this.loading?250:0)},setRange:function(e,t){s.is.htmlElement(e)&&(e.value=t,h.updateRangeFill.call(this,e))},setProgress:function(e,t){var i=s.is.undefined(t)?0:t,n=s.is.undefined(e)?this.elements.display.buffer:e;if(s.is.htmlElement(n)){n.value=i;var a=n.getElementsByTagName("span")[0];s.is.htmlElement(a)&&(a.childNodes[0].nodeValue=i)}},updateProgress:function(e){var t=this;if(this.supported.ui){var i=0;if(e)switch(e.type){case"timeupdate":case"seeking":i=s.getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&d.setRange.call(this,this.elements.inputs.seek,i);break;case"playing":case"progress":i=function(){var e=t.media.buffered;return e&&e.length?s.getPercentage(e.end(0),t.duration):s.is.number(e)?100*e:0}(),d.setProgress.call(this,this.elements.display.buffer,i)}}},updateTimeDisplay:function(e,t){if(!s.is.htmlElement(t))return null;var i=Number.isNaN(e)?0:e,n=parseInt(i%60,10),a=parseInt(i/60%60,10),l=parseInt(i/60/60%60,10),o=parseInt(this.duration/60/60%60,10)>0;n=("0"+n).slice(-2),a=("0"+a).slice(-2);var r=(o?l+":":"")+a+":"+n;return t.textContent=r,r},timeUpdate:function(e){d.updateTimeDisplay.call(this,this.currentTime,this.elements.display.currentTime),e&&"timeupdate"===e.type&&this.media.seeking||d.updateProgress.call(this,e)}},p=s.getBrowser(),h={updateRangeFill:function(e){if(p.isWebkit){var t=s.is.event(e)?e.target:e;if(s.is.htmlElement(t)&&"range"===t.getAttribute("type")){s.is.htmlElement(this.elements.styleSheet)||(this.elements.styleSheet=s.createElement("style"),this.elements.container.appendChild(this.elements.styleSheet));var i=this.elements.styleSheet.sheet,n=t.value/t.max*100,a="#"+t.id+"::-webkit-slider-runnable-track",l="{ background-image: linear-gradient(to right, currentColor "+n+"%, transparent "+n+"%) }",o=Array.from(i.rules).findIndex(function(e){return e.selectorText===a});-1!==o&&i.deleteRule(o),i.insertRule([a,l].join(" "))}}},getIconUrl:function(){return{url:this.config.iconUrl,absolute:0===this.config.iconUrl.indexOf("http")||p.isIE&&!window.svg4everybody}},createIcon:function(e,t){var i=h.getIconUrl.call(this),n=(i.absolute?"":i.url)+"#"+this.config.iconPrefix,a=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttributes(a,s.extend(t,{role:"presentation"}));var l=document.createElementNS("http://www.w3.org/2000/svg","use"),o=n+"-"+e;return"href"in l?l.setAttribute("href",o):l.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),a.appendChild(l),a},createLabel:function(e){var t=this.config.i18n[e];switch(e){case"pip":t="PIP";break;case"airplay":t="AirPlay"}return s.createElement("span",{class:this.config.classNames.hidden},t)},createBadge:function(e){var t=s.createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(s.createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=s.createElement("button"),n=Object.assign({},t),a=e,l=void 0,o=void 0,r=void 0;switch("type"in n||(n.type="button"),"class"in n?-1===n.class.indexOf(this.config.classNames.control)&&(n.class+=" "+this.config.classNames.control):n.class=this.config.classNames.control,a){case"mute":r="toggleMute",l="volume",o="muted";break;case"captions":r="toggleCaptions",l="captions-off",o="captions-on";break;case"fullscreen":r="toggleFullscreen",l="enter-fullscreen",o="exit-fullscreen";break;case"play-large":n.class="plyr__play-large",a="play",r="play",l="play";break;default:r=a,l=a}return s.extend(n,s.getAttributesFromSelector(this.config.selectors.buttons[a],n)),s.is.string(o)?(i.appendChild(h.createIcon.call(this,o,{class:"icon--pressed"})),i.appendChild(h.createIcon.call(this,l,{class:"icon--not-pressed"}))):i.appendChild(h.createIcon.call(this,l)),i.appendChild(h.createLabel.call(this,r)),s.setAttributes(i,n),this.elements.buttons[a]=i,i},createRange:function(e,t){var i=s.createElement("label",{for:t.id,class:this.config.classNames.hidden},this.config.i18n[e]),n=s.createElement("input",s.extend(s.getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off"},t));return this.elements.inputs[e]=n,h.updateRangeFill.call(this,n),{label:i,input:n}},createProgress:function(e,t){var i=s.createElement("progress",s.extend(s.getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0},t));if("volume"!==e){i.appendChild(s.createElement("span",null,"0"));var n="";switch(e){case"played":n=this.config.i18n.played;break;case"buffer":n=this.config.i18n.buffered}i.textContent="% "+n.toLowerCase()}return this.elements.display[e]=i,i},createTime:function(e){var t=s.createElement("span",{class:"plyr__time"});return t.appendChild(s.createElement("span",{class:this.config.classNames.hidden},this.config.i18n[e])),t.appendChild(s.createElement("span",s.getAttributesFromSelector(this.config.selectors.display[e]),"00:00")),this.elements.display[e]=t,t},updateSeekTooltip:function(e){if(this.config.tooltips.seek&&s.is.htmlElement(this.elements.inputs.seek)&&s.is.htmlElement(this.elements.display.seekTooltip)&&0!==this.duration){var t=0,i=this.elements.inputs.seek.getBoundingClientRect(),n=this.config.classNames.tooltip+"--visible";if(s.is.event(e))t=100/i.width*(e.pageX-i.left);else{if(!s.hasClass(this.elements.display.seekTooltip,n))return;t=this.elements.display.seekTooltip.style.left.replace("%","")}t<0?t=0:t>100&&(t=100),d.updateTimeDisplay.call(this,this.duration/100*t,this.elements.display.seekTooltip),this.elements.display.seekTooltip.style.left=t+"%",s.is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&s.toggleClass(this.elements.display.seekTooltip,n,"mouseenter"===e.type)}},toggleTab:function(e,t){var i=this.elements.settings.tabs[e],n=this.elements.settings.panes[e];s.is.htmlElement(i)&&(t?i.removeAttribute("hidden"):i.setAttribute("hidden","")),s.is.htmlElement(n)&&(t?n.removeAttribute("hidden"):n.setAttribute("hidden",""))},setQualityMenu:function(e){var t=this,i=this.elements.settings.panes.quality.querySelector("ul");s.is.array(e)?this.options.quality=e.filter(function(e){return t.config.quality.options.includes(e)}):this.options.quality=this.config.quality.options;var n=!s.is.empty(this.options.quality)&&"youtube"===this.type;if(h.toggleTab.call(this,"quality",n),n){s.emptyElement(i);var a=function(e){var i="";switch(e){case"hd2160":i="4K";break;case"hd1440":i="WQHD";break;case"hd1080":case"hd720":i="HD"}return i.length?h.createBadge.call(t,i):null};this.options.quality.forEach(function(e){var n=s.createElement("li"),l=s.createElement("label",{class:t.config.classNames.control}),o=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.quality),{type:"radio",name:"plyr-quality",value:e}));l.appendChild(o),l.appendChild(document.createTextNode(h.getLabel.call(t,"quality",e)));var r=a(e);s.is.htmlElement(r)&&l.appendChild(r),n.appendChild(l),i.appendChild(n)}),h.updateSetting.call(this,"quality",i)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?"Normal":t+"×";case"quality":switch(t){case"hd2160":return"2160P";case"hd1440":return"1440P";case"hd1080":return"1080P";case"hd720":return"720P";case"large":return"480P";case"medium":return"360P";case"small":return"240P";case"tiny":return"Tiny";case"default":return"Auto";default:return t}case"captions":return h.getLanguage.call(this);default:return null}},updateSetting:function(e,t){var i=this.elements.settings.panes[e],n=null,a=t;switch(e){case"captions":n=this.captions.language,this.captions.enabled||(n="");break;default:if(n=this[e],s.is.empty(n)&&(n=this.config[e].default),!this.options[e].includes(n))return void this.console.warn("Unsupported value of '"+n+"' for "+e);if(!this.config[e].options.includes(n))return void this.console.warn("Disabled value of '"+n+"' for "+e)}s.is.htmlElement(a)||(a=i&&i.querySelector("ul"));var l=a&&a.querySelector('input[value="'+n+'"]');s.is.htmlElement(l)&&(l.checked=!0,this.elements.settings.tabs[e].querySelector("."+this.config.classNames.menu.value).innerHTML=h.getLabel.call(this,e,n))},setLoopMenu:function(){var e=this,t=this.elements.settings.panes.loop.querySelector("ul");this.elements.settings.tabs.loop.removeAttribute("hidden"),this.elements.settings.panes.loop.removeAttribute("hidden");var i=!s.is.empty(this.loop.options);h.toggleTab.call(this,"loop",i),s.emptyElement(t),["start","end","all","reset"].forEach(function(i){var n=s.createElement("li"),a=s.createElement("button",s.extend(s.getAttributesFromSelector(e.config.selectors.buttons.loop),{type:"button",class:e.config.classNames.control,"data-plyr-loop-action":i}),e.config.i18n[i]);if(["start","end"].includes(i)){var l=h.createBadge.call(e,"00:00");a.appendChild(l)}n.appendChild(a),t.appendChild(n)})},getLanguage:function(){return this.supported.ui?!a.textTracks||s.is.empty(this.captions.tracks)?this.config.i18n.none:this.captions.enabled?this.captions.currentTrack.label:this.config.i18n.disabled:null},setCaptionsMenu:function(){var e=this,t=this.elements.settings.panes.captions.querySelector("ul"),i=!s.is.empty(this.captions.tracks);if(h.toggleTab.call(this,"captions",i),s.emptyElement(t),!s.is.empty(this.captions.tracks)){var n=Array.from(this.captions.tracks).map(function(e){return{language:e.language,badge:!0,label:s.is.empty(e.label)?e.language.toUpperCase():e.label}});n.unshift({language:"",label:this.config.i18n.none}),n.forEach(function(i){var n=s.createElement("li"),a=s.createElement("label",{class:e.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(e.config.selectors.inputs.language),{type:"radio",name:"plyr-language",value:i.language}));i.language.toLowerCase()===e.captions.language.toLowerCase()&&(l.checked=!0),a.appendChild(l),a.appendChild(document.createTextNode(i.label||i.language)),i.badge&&a.appendChild(h.createBadge.call(e,i.language.toUpperCase())),n.appendChild(a),t.appendChild(n)}),h.updateSetting.call(this,"captions",t)}},setSpeedMenu:function(e){var t=this;s.is.array(e)?this.options.speed=e.filter(function(e){return t.config.speed.options.includes(e)}):this.options.speed=this.config.speed.options;var i=!s.is.empty(this.options.speed);if(h.toggleTab.call(this,"speed",i),i){var n=this.elements.settings.panes.speed.querySelector("ul");this.elements.settings.tabs.speed.removeAttribute("hidden"),this.elements.settings.panes.speed.removeAttribute("hidden"),s.emptyElement(n),this.options.speed.forEach(function(e){var i=s.createElement("li"),a=s.createElement("label",{class:t.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.speed),{type:"radio",name:"plyr-speed",value:e}));a.appendChild(l),a.insertAdjacentHTML("beforeend",h.getLabel.call(t,"speed",e)),i.appendChild(a),n.appendChild(i)}),h.updateSetting.call(this,"speed",n)}},toggleMenu:function(e){var t=this.elements.settings.form,i=this.elements.buttons.settings,n=s.is.boolean(e)?e:t&&"true"===t.getAttribute("aria-hidden");if(s.is.event(e)){var a=t&&t.contains(e.target),l=e.target===this.elements.buttons.settings;if(a||!a&&!l&&n)return;l&&e.stopPropagation()}i&&i.setAttribute("aria-expanded",n),t&&(t.setAttribute("aria-hidden",!n),n?t.removeAttribute("tabindex"):t.setAttribute("tabindex",-1))},getTabSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.setAttribute("aria-hidden",!1),Array.from(t.querySelectorAll("input[name]")).forEach(function(e){var t=e.getAttribute("name");e.setAttribute("name",t+"-clone")}),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return s.removeElement(t),{width:i,height:n}},showTab:function(e){var t=this.elements.settings.menu,i=e.target,n="false"===i.getAttribute("aria-expanded"),l=document.getElementById(i.getAttribute("aria-controls"));if(s.is.htmlElement(l)&&"tabpanel"===l.getAttribute("role")){var o=t.querySelector('[role="tabpanel"][aria-hidden="false"]'),r=o.parentNode;if(Array.from(t.querySelectorAll('[aria-controls="'+o.getAttribute("id")+'"]')).forEach(function(e){e.setAttribute("aria-expanded",!1)}),a.transitions&&!a.reducedMotion){r.style.width=o.scrollWidth+"px",r.style.height=o.scrollHeight+"px";var c=h.getTabSize.call(this,l),u=function e(t){t.target===r&&["width","height"].includes(t.propertyName)&&(r.style.width="",r.style.height="",s.off(r,s.transitionEnd,e))};s.on(r,s.transitionEnd,u),r.style.width=c.width+"px",r.style.height=c.height+"px"}o.setAttribute("aria-hidden",!0),o.setAttribute("tabindex",-1),l.setAttribute("aria-hidden",!n),i.setAttribute("aria-expanded",n),l.removeAttribute("tabindex")}},create:function(e){var t=this;if(s.is.empty(this.config.controls))return null;var i=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(h.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(h.createButton.call(this,"rewind")),this.config.controls.includes("play")&&(i.appendChild(h.createButton.call(this,"play")),i.appendChild(h.createButton.call(this,"pause"))),this.config.controls.includes("fast-forward")&&i.appendChild(h.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=s.createElement("span",s.getAttributesFromSelector(this.config.selectors.progress)),l=h.createRange.call(this,"seek",{id:"plyr-seek-"+e.id});if(n.appendChild(l.label),n.appendChild(l.input),n.appendChild(h.createProgress.call(this,"buffer")),this.config.tooltips.seek){var o=s.createElement("span",{role:"tooltip",class:this.config.classNames.tooltip},"00:00");n.appendChild(o),this.elements.display.seekTooltip=o}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(h.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(h.createTime.call(this,"duration")),this.config.controls.includes("mute")&&i.appendChild(h.createButton.call(this,"mute")),this.config.controls.includes("volume")){var r=s.createElement("span",{class:"plyr__volume"}),c={max:1,step:.05,value:this.config.volume},u=h.createRange.call(this,"volume",s.extend(c,{id:"plyr-volume-"+e.id}));r.appendChild(u.label),r.appendChild(u.input),i.appendChild(r)}if(this.config.controls.includes("captions")&&i.appendChild(h.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!s.is.empty(this.config.settings)){var d=s.createElement("div",{class:"plyr__menu"});d.appendChild(h.createButton.call(this,"settings",{id:"plyr-settings-toggle-"+e.id,"aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id,"aria-expanded":!1}));var p=s.createElement("form",{class:"plyr__menu__container",id:"plyr-settings-"+e.id,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tablist",tabindex:-1}),m=s.createElement("div"),g=s.createElement("div",{id:"plyr-settings-"+e.id+"-home","aria-hidden":!1,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tabpanel"}),f=s.createElement("ul",{role:"tablist"});this.config.settings.forEach(function(i){var n=s.createElement("li",{role:"tab",hidden:""}),a=s.createElement("button",s.extend(s.getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--forward",id:"plyr-settings-"+e.id+"-"+i+"-tab","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-"+i,"aria-expanded":!1}),t.config.i18n[i]),l=s.createElement("span",{class:t.config.classNames.menu.value});l.innerHTML=e[i],a.appendChild(l),n.appendChild(a),f.appendChild(n),t.elements.settings.tabs[i]=n}),g.appendChild(f),m.appendChild(g),this.config.settings.forEach(function(i){var n=s.createElement("div",{id:"plyr-settings-"+e.id+"-"+i,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-"+e.id+"-"+i+"-tab",role:"tabpanel",tabindex:-1,hidden:""}),a=s.createElement("button",{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--back","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-home","aria-expanded":!1},t.config.i18n[i]);n.appendChild(a);var l=s.createElement("ul");n.appendChild(l),m.appendChild(n),t.elements.settings.panes[i]=n}),p.appendChild(m),d.appendChild(p),i.appendChild(d),this.elements.settings.form=p,this.elements.settings.menu=d}return this.config.controls.includes("pip")&&a.pip&&i.appendChild(h.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&a.airplay&&i.appendChild(h.createButton.call(this,"airplay")),this.config.controls.includes("fullscreen")&&i.appendChild(h.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(h.createButton.call(this,"play-large")),this.elements.controls=i,this.config.controls.includes("settings")&&this.config.settings.includes("speed")&&h.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=h.getIconUrl.call(this);t.absolute&&s.loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;i=s.is.string(this.config.controls)?this.config.controls:s.is.function(this.config.controls)?this.config.controls({id:this.id,seektime:this.config.seekTime,title:this.config.title}):h.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:h.getLanguage.call(this)});var n=void 0;if(s.is.string(this.config.selectors.controls.container)&&(n=document.querySelector(this.config.selectors.controls.container)),s.is.htmlElement(n)||(n=this.elements.container),s.is.htmlElement(i)?n.appendChild(i):n.insertAdjacentHTML("beforeend",i),s.is.htmlElement(this.elements.controls)&&s.findElements.call(this),this.config.tooltips.controls){var a=s.getElements.call(this,[this.config.selectors.controls.wrapper," ",this.config.selectors.labels," .",this.config.classNames.hidden].join(""));Array.from(a).forEach(function(t){s.toggleClass(t,e.config.classNames.hidden,!1),s.toggleClass(t,e.config.classNames.tooltip,!0)})}}},m={setup:function(){var e=this;if(this.supported.ui){if(s.is.empty(r.get.call(this).language)?s.is.empty(this.captions.language)&&(this.captions.language=this.config.captions.language.toLowerCase()):this.captions.language=r.get.call(this).language,s.is.boolean(this.captions.enabled)||(s.is.empty(r.get.call(this).language)?this.captions.enabled=this.config.captions.active:this.captions.enabled=r.get.call(this).captions),!["video","vimeo"].includes(this.type)||"video"===this.type&&!a.textTracks)return this.captions.tracks=null,void(this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this));if(s.is.htmlElement(this.elements.captions)||(this.elements.captions=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.captions)),s.insertAfter(this.elements.captions,this.elements.wrapper)),"video"===this.type&&(this.captions.tracks=this.media.textTracks),s.toggleClass(this.elements.container,this.config.classNames.captions.enabled,!s.is.empty(this.captions.tracks)),!s.is.empty(this.captions.tracks)){m.show.call(this);var t=function(){e.captions.currentTrack=null,Array.from(e.captions.tracks).forEach(function(t){t.language===e.captions.language.toLowerCase()&&(e.captions.currentTrack=t)})};if(t(),!s.is.track(this.captions.currentTrack)){var i=this.config.captions.language;this.captions.language=i,t(),s.is.track(this.captions.currentTrack)||this.toggleCaptions(!1),h.updateSetting.call(this,"captions")}if("video"===this.type){Array.from(this.captions.tracks).forEach(function(t){s.off(t,"cuechange",function(t){return m.setCue.call(e,t)}),t.mode="hidden"});var n=this.captions.currentTrack&&["captions","subtitles"].includes(this.captions.currentTrack.kind);s.is.track(this.captions.currentTrack)&&n&&(s.on(this.captions.currentTrack,"cuechange",function(t){return m.setCue.call(e,t)}),this.captions.currentTrack.activeCues&&this.captions.currentTrack.activeCues.length>0&&m.setCue.call(this,this.captions.currentTrack))}else"vimeo"===this.type&&this.captions.active&&this.embed.enableTextTrack(this.captions.language);this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this)}}},setCue:function(e){var t=(s.is.event(e)?e.target:e).activeCues[0];s.is.cue(t)?m.set.call(this,t.getCueAsHTML()):m.set.call(this),s.dispatchEvent.call(this,this.media,"cuechange")},set:function(e){if(this.supported.ui)if(s.is.htmlElement(this.elements.captions)){var t=s.createElement("span");s.emptyElement(this.elements.captions);var i=s.is.undefined(e)?"":e;s.is.string(i)?t.textContent=i.trim():t.appendChild(i),this.elements.captions.appendChild(t)}else this.console.warn("No captions element to render to")},show:function(){if(s.is.htmlElement(this.elements.buttons.captions)){var e=r.get.call(this).captions;s.is.boolean(e)?this.captions.active=e:e=this.config.captions.active,e&&(s.toggleClass(this.elements.container,this.config.classNames.captions.active,!0),s.toggleState(this.elements.buttons.captions,!0))}}},g={setup:function(){var e=this,t=s.parseYouTubeId(this.embedId),i=s.getElements.call(this,'[id^="'+this.type+'-"]');Array.from(i).forEach(s.removeElement),s.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),g.setAspectRatio.call(this),this.media.setAttribute("id",s.generateId(this.type)),s.is.object(window.YT)?g.ready.call(this,t):(s.loadScript(this.config.urls.youtube.api),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){g.ready.call(e,t)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},setAspectRatio:function(){var e=this.config.ratio.split(":");this.elements.wrapper.style.paddingBottom=100/e[0]*e[1]+"%"},ready:function(e){var t=this;t.embed=new window.YT.Player(t.media.id,{videoId:e,playerVars:{autoplay:t.config.autoplay?1:0,controls:t.supported.ui?0:1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1,disablekb:1,playsinline:1,origin:window&&window.location.hostname,widget_referrer:window&&window.location.href,cc_load_policy:this.captions.active?1:0,cc_lang_pref:this.config.captions.language},events:{onError:function(e){s.dispatchEvent.call(t,t.media,"error",!0,{code:e.data,embed:e.target})},onPlaybackQualityChange:function(e){var i=e.target;t.media.quality=i.getPlaybackQuality(),s.dispatchEvent.call(t,t.media,"qualitychange")},onPlaybackRateChange:function(e){var i=e.target;t.media.playbackRate=i.getPlaybackRate(),s.dispatchEvent.call(t,t.media,"ratechange")},onReady:function(e){var i=e.target;t.media.play=function(){i.playVideo(),t.media.paused=!1},t.media.pause=function(){i.pauseVideo(),t.media.paused=!0},t.media.stop=function(){i.stopVideo(),t.media.paused=!0},t.media.duration=i.getDuration(),t.media.paused=!0,t.media.currentTime=0,Object.defineProperty(t.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(e){t.media.seeking=!0,s.dispatchEvent.call(t,t.media,"seeking"),i.seekTo(e)}}),Object.defineProperty(t.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}}),Object.defineProperty(t.media,"quality",{get:function(){return i.getPlaybackQuality()},set:function(e){s.dispatchEvent.call(t,t.media,"qualityrequested",!1,{quality:e}),i.setPlaybackQuality(e)}});var n=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return n},set:function(e){n=e,i.setVolume(100*n),s.dispatchEvent.call(t,t.media,"volumechange")}});var a=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return a},set:function(e){var n=s.is.boolean(e)?e:a;a=n,i[n?"mute":"unMute"](),s.dispatchEvent.call(t,t.media,"volumechange")}}),Object.defineProperty(t.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),t.config.controls.includes("settings")&&t.config.settings.includes("speed")&&h.setSpeedMenu.call(t,i.getAvailablePlaybackRates()),t.config.title=i.getVideoData().title,t.supported.ui&&t.media.setAttribute("tabindex",-1),s.dispatchEvent.call(t,t.media,"timeupdate"),s.dispatchEvent.call(t,t.media,"durationchange"),window.clearInterval(t.timers.buffering),t.timers.buffering=window.setInterval(function(){t.media.buffered=i.getVideoLoadedFraction(),(null===t.media.lastBuffered||t.media.lastBuffered1&&void 0!==arguments[1]&&arguments[1],n=function(){if(document.body.style.overflow="",t.embed=null,t.embedId=null,i)Object.keys(t.elements).length&&(t.elements.buttons&&t.elements.buttons.play&&Array.from(t.elements.buttons.play).forEach(function(e){return s.removeElement(e)}),s.removeElement(t.elements.captions),s.removeElement(t.elements.controls),s.removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),s.is.function(e)&&e();else{var n=t.elements.container.parentNode;s.is.htmlElement(n)&&n.replaceChild(t.elements.original,t.elements.container),s.dispatchEvent.call(t,t.elements.original,"destroyed",!0),s.is.function(e)&&e.call(t.elements.original),t.elements=null}};switch(this.type){case"youtube":window.clearInterval(this.timers.buffering),window.clearInterval(this.timers.playing),this.embed.destroy(),n();break;case"vimeo":this.embed.unload().then(n),window.setTimeout(n,200);break;case"video":case"audio":d.toggleNativeControls.call(this,!0),n()}}},{key:"isHTML5",get:function(){return n.html5.includes(this.type)}},{key:"isEmbed",get:function(){return n.embed.includes(this.type)}},{key:"paused",get:function(){return this.media.paused}},{key:"currentTime",set:function(e){var t=0;s.is.number(e)&&(t=e),t<0?t=0:t>this.duration&&(t=this.duration),this.media.currentTime=t.toFixed(4),this.console.log("Seeking to "+this.currentTime+" seconds")},get:function(){return Number(this.media.currentTime)}},{key:"seeking",get:function(){return this.media.seeking}},{key:"duration",get:function(){var e=parseInt(this.config.duration,10),t=Number(this.media.duration);return Number.isNaN(e)?t:e}},{key:"volume",set:function(e){var t=e;s.is.string(t)&&(t=Number(t)),s.is.number(t)||(t=r.get.call(this).volume),s.is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,this.muted&&t>0&&(this.muted=!1)},get:function(){return this.media.volume}},{key:"muted",set:function(e){var t=e;s.is.boolean(t)||(t=r.get.call(this).muted),s.is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return this.media.muted}},{key:"speed",set:function(e){var t=null;(t=s.is.number(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).speed:this.config.speed.selected)<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.console.warn("Unsupported speed ("+t+")")},get:function(){return this.media.playbackRate}},{key:"quality",set:function(e){var t=null;t=s.is.string(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).quality:this.config.quality.selected,this.options.quality.includes(t)?(this.config.quality.selected=t,this.media.quality=t):this.console.warn("Unsupported quality option ("+t+")")},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=s.is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return this.media.loop}},{key:"source",set:function(e){v.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"poster",set:function(e){"video"===this.type?s.is.string(e)&&this.media.setAttribute("poster",e):this.console.warn("Poster can only be set on HTML5 video")},get:function(){return"video"!==this.type?null:this.media.getAttribute("poster")}},{key:"autoplay",get:function(){return this.config.autoplay},set:function(e){var t=s.is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t}},{key:"language",set:function(e){if(s.is.string(e)){var t=e.toLowerCase();this.captions.language!==t&&(this.toggleCaptions(!0),this.captions.language=t,s.dispatchEvent.call(this,this.media,"languagechange"),m.set.call(this),m.setup.call(this))}},get:function(){return this.captions.language}},{key:"pip",set:function(e){var t={pip:"picture-in-picture",inline:"inline"};if(a.pip){var i=s.is.boolean(e)?e:this.pip===t.inline;this.media.webkitSetPresentationMode(i?t.pip:t.inline)}},get:function(){return a.pip?this.media.webkitPresentationMode:null}}]),e}()}); //# sourceMappingURL=plyr.js.map diff --git a/dist/plyr.js.map b/dist/plyr.js.map index 5ba6e541..ab134fe8 100644 --- a/dist/plyr.js.map +++ b/dist/plyr.js.map @@ -1 +1 @@ -{"version":3,"file":"plyr.js","sources":["src/js/storage.js","src/js/defaults.js","src/js/types.js","src/js/utils.js","src/js/support.js","src/js/fullscreen.js","src/js/listeners.js","src/js/ui.js","src/js/controls.js","src/js/captions.js","src/js/plugins/youtube.js","src/js/plugins/vimeo.js","src/js/media.js","src/js/source.js","src/js/plyr.js"],"sourcesContent":["// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\n// Get contents of local storage\nfunction get() {\n const store = window.localStorage.getItem(this.config.storage.key);\n\n if (utils.is.empty(store)) {\n return {};\n }\n\n return JSON.parse(store);\n}\n\n// Save a value back to local storage\nfunction set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n const storage = get.call(this);\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.config.storage.key, JSON.stringify(storage));\n}\n\n// Setup localStorage\nfunction setup() {\n let value = null;\n let storage = {};\n\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return storage;\n }\n\n // Clean up old volume\n // https://github.com/sampotts/plyr/issues/171\n window.localStorage.removeItem('plyr-volume');\n\n // load value from the current key\n value = window.localStorage.getItem(this.config.storage.key);\n\n if (!value) {\n // Key wasn't set (or had been cleared), move along\n } else if (/^\\d+(\\.\\d+)?$/.test(value)) {\n // If value is a number, it's probably volume from an older\n // version of this. See: https://github.com/sampotts/plyr/pull/313\n // Update the key to be JSON\n set({\n volume: parseFloat(value),\n });\n } else {\n // Assume it's JSON from this or a later version of plyr\n storage = JSON.parse(value);\n }\n\n return storage;\n}\n\nexport default { setup, set, get };\n","// Default config\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration\n displayDuration: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video to play\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Revert to poster on finish (HTML5 - will cause reload)\n showPosterOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/2.0.10/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 'default',\n options: ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'default'],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: window.navigator.language.split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n 'play',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed', 'loop'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime} secs',\n play: 'Play',\n pause: 'Pause',\n forward: 'Forward {seektime} secs',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n toggleMute: 'Toggle Mute',\n toggleCaptions: 'Toggle Captions',\n toggleFullscreen: 'Toggle Fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n none: 'None',\n disabled: 'Disabled',\n },\n\n // URLs\n urls: {\n vimeo: {\n api: 'https://player.vimeo.com/api/player.js',\n },\n youtube: {\n api: 'https://www.youtube.com/iframe_api',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n forward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'captionchange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n forward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n control: 'plyr__control',\n type: 'plyr--{0}',\n stopped: 'plyr--stopped',\n playing: 'plyr--playing',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr supported types\n// ==========================================================================\n\nconst types = {\n embed: ['youtube', 'vimeo'],\n html5: ['video', 'audio'],\n};\n\nexport default types;\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport support from './support';\n\nconst utils = {\n // Check variable types\n is: {\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.undefined(input) && Array.isArray(input);\n },\n nodeList(input) {\n return !this.undefined(input) && input instanceof NodeList;\n },\n htmlElement(input) {\n return !this.undefined(input) && input instanceof HTMLElement;\n },\n event(input) {\n return !this.undefined(input) && input instanceof Event;\n },\n cue(input) {\n return this.instanceOf(input, window.TextTrackCue) || this.instanceOf(input, window.VTTCue);\n },\n track(input) {\n return (\n !this.undefined(input) && (this.instanceOf(input, window.TextTrack) || typeof input.kind === 'string')\n );\n },\n undefined(input) {\n return input !== null && typeof input === 'undefined';\n },\n empty(input) {\n return (\n input === null ||\n typeof input === 'undefined' ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && input.length === 0) ||\n (this.object(input) && Object.keys(input).length === 0)\n );\n },\n getConstructor(input) {\n if (input === null || typeof input === 'undefined') {\n return null;\n }\n\n return input.constructor;\n },\n instanceOf(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Load an external script\n loadScript(url, callback) {\n // Check script is not already referenced\n if (document.querySelectorAll(`script[src=\"${url}\"]`).length) {\n return;\n }\n\n // Build the element\n const element = document.createElement('script');\n element.src = url;\n\n // Find first script\n const first = document.getElementsByTagName('script')[0];\n\n // Bind callback\n if (utils.is.function(callback)) {\n element.addEventListener('load', event => callback.call(null, event), false);\n }\n\n // Inject\n first.parentNode.insertBefore(element, first);\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (typeof url !== 'string') {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = typeof id === 'string';\n let isCached = false;\n\n function updateSprite(data) {\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once\n if (!hasId || !document.querySelectorAll(`#${id}`).length) {\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n updateSprite.call(container, data.content);\n }\n }\n\n // ReSharper disable once InconsistentNaming\n const xhr = new XMLHttpRequest();\n\n // XHR for Chrome/Firefox/Opera/Safari\n if ('withCredentials' in xhr) {\n xhr.open('GET', url, true);\n } else {\n return;\n }\n\n // Once loaded, inject to container and body\n xhr.onload = () => {\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: xhr.responseText,\n })\n );\n }\n\n updateSprite.call(container, xhr.responseText);\n };\n\n xhr.send();\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Determine if we're in an iframe\n inFrame() {\n try {\n return window.self !== window.top;\n } catch (e) {\n return true;\n }\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Remove an element\n removeElement(element) {\n if (!utils.is.htmlElement(element) || !utils.is.htmlElement(element.parentNode)) {\n return null;\n }\n\n element.parentNode.removeChild(element);\n\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new \n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new \n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n Object.keys(attributes).forEach(key => {\n element.setAttribute(key, attributes[key]);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.htmlElement(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.htmlElement(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n forward: utils.getElement.call(this, this.config.selectors.buttons.forward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n };\n\n // Seek tooltip\n if (utils.is.htmlElement(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.console.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus() {\n const tabbables = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = tabbables[0];\n const last = tabbables[tabbables.length - 1];\n\n utils.on(\n this.elements.container,\n 'keydown',\n event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9 || !this.fullscreen.active) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n },\n false\n );\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle, passive, capture) {\n // Bail if no elements\n if (elements === null || utils.is.undefined(elements)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just capture boolean\n let options = utils.is.boolean(capture) ? capture : false;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive: utils.is.boolean(passive) ? passive : true,\n // Whether the listener is a capturing listener or not\n capture: utils.is.boolean(capture) ? capture : false,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type, bubbles, properties) {\n // Bail if no element\n if (!element || !type) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles: utils.is.boolean(bubbles) ? bubbles : false,\n detail: Object.assign({}, properties, {\n plyr: this instanceof Plyr ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // Bail if no target\n if (!utils.is.htmlElement(element)) {\n return;\n }\n\n // Get state\n const state = utils.is.boolean(input) ? input : !element.getAttribute('aria-pressed');\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n return (current / max * 100).toFixed(2);\n },\n\n // Deep extend/merge destination object with N more objects\n // http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/\n // Removed call to arguments.callee (used explicit function name instead)\n extend(...objects) {\n const { length } = objects;\n\n // Bail if nothing to merge\n if (!length) {\n return null;\n }\n\n // Return first if specified but nothing to merge\n if (length === 1) {\n return objects[0];\n }\n\n // First object is the destination\n let destination = Array.prototype.shift.call(objects);\n if (!utils.is.object(destination)) {\n destination = {};\n }\n\n // Loop through all objects to merge\n objects.forEach(source => {\n if (!utils.is.object(source)) {\n return;\n }\n\n Object.keys(source).forEach(property => {\n if (source[property] && source[property].constructor && source[property].constructor === Object) {\n destination[property] = destination[property] || {};\n utils.extend(destination[property], source[property]);\n } else {\n destination[property] = source[property];\n }\n });\n });\n\n return destination;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert object to URL parameters\n buildUrlParameters(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n transitionEnd: (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return typeof type === 'string' ? type : false;\n })(),\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, inline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const playsInline = browser.isIPhone && inline && support.inline;\n\n switch (type) {\n case 'video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'vimeo':\n api = true;\n ui = support.rangeInput && !browser.isIPhone;\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Local storage\n // We can't assume if local storage is present that we can use it\n storage: (() => {\n if (!('localStorage' in window)) {\n return false;\n }\n\n // Try to use it (it might be disabled, e.g. user is in private/porn mode)\n // see: https://github.com/sampotts/plyr/issues/131\n const test = '___test';\n try {\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n return true;\n } catch (e) {\n return false;\n }\n })(),\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n inline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Type specific checks\n if (this.type === 'video') {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.type === 'audio') {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // Remember a device can be moust + touch enabled\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEnd !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr fullscreen API\n// ==========================================================================\n\nimport utils from './utils';\n\n// Determine the prefix\nconst prefix = (() => {\n let value = false;\n\n if (utils.is.function(document.cancelFullScreen)) {\n value = '';\n } else {\n // Check for fullscreen support by vendor prefix\n ['webkit', 'o', 'moz', 'ms', 'khtml'].some(pre => {\n if (utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n } else if (utils.is.function(document.msExitFullscreen) && document.msFullscreenEnabled) {\n // Special case for MS (when isn't it?)\n value = 'ms';\n return true;\n }\n\n return false;\n });\n }\n\n return value;\n})();\n\n// Fullscreen API\nconst fullscreen = {\n // Get the prefix\n prefix,\n\n // Check if we can use it\n enabled:\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled,\n\n // Yet again Microsoft awesomeness,\n // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes\n eventType: prefix === 'ms' ? 'MSFullscreenChange' : `${prefix}fullscreenchange`,\n\n // Is an element fullscreen\n isFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n switch (prefix) {\n case '':\n return document.fullscreenElement === target;\n\n case 'moz':\n return document.mozFullScreenElement === target;\n\n default:\n return document[`${prefix}FullscreenElement`] === target;\n }\n },\n\n // Make an element fullscreen\n requestFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n return !prefix.length\n ? target.requestFullScreen()\n : target[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();\n },\n\n // Bail from fullscreen\n cancelFullScreen() {\n if (!fullscreen.enabled) {\n return false;\n }\n\n return !prefix.length\n ? document.cancelFullScreen()\n : document[prefix + (prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')]();\n },\n\n // Get the current element\n element() {\n if (!fullscreen.enabled) {\n return null;\n }\n\n return !prefix.length ? document.fullscreenElement : document[`${prefix}FullscreenElement`];\n },\n\n // Setup fullscreen\n setup() {\n if (!this.supported.ui || this.type === 'audio' || !this.config.fullscreen.enabled) {\n return;\n }\n\n // Check for native support\n const nativeSupport = fullscreen.enabled;\n\n if (nativeSupport || (this.config.fullscreen.fallback && !utils.inFrame())) {\n this.console.log(`${nativeSupport ? 'Native' : 'Fallback'} fullscreen enabled`);\n\n // Add styling hook to show button\n utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.enabled, true);\n } else {\n this.console.log('Fullscreen not supported and fallback disabled');\n }\n\n // Toggle state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, false);\n }\n\n // Trap focus in container\n utils.trapFocus.call(this);\n },\n};\n\nexport default fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport storage from './storage';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst listeners = {\n // Global listeners\n global() {\n let last = null;\n\n // Get the key code for an event\n const getKeyCode = event => (event.keyCode ? event.keyCode : event.which);\n\n // Handle key press\n const handleKey = event => {\n const code = getKeyCode(event);\n const pressed = event.type === 'keydown';\n const held = pressed && code === last;\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.currentTime = this.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.htmlElement(focused) && utils.matches(focused, this.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!held) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!held) {\n this.console.warn('togglePlay', event.type);\n this.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!held) {\n this.muted = 'toggle';\n }\n break;\n\n case 39:\n // Arrow forward\n this.forward();\n break;\n\n case 37:\n // Arrow back\n this.rewind();\n break;\n\n case 70:\n // F key\n this.toggleFullscreen();\n break;\n\n case 67:\n // C key\n if (!held) {\n this.toggleCaptions();\n }\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!fullscreen.enabled && this.fullscreen.active && code === 27) {\n this.toggleFullscreen();\n }\n\n // Store last code for next cycle\n last = code;\n } else {\n last = null;\n }\n };\n\n // Keyboard shortcuts\n if (this.config.keyboard.global) {\n utils.on(window, 'keydown keyup', handleKey, false);\n } else if (this.config.keyboard.focused) {\n utils.on(this.elements.container, 'keydown keyup', handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n window.setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(\n this.elements.container,\n 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen',\n event => {\n this.toggleControls(event);\n }\n );\n }\n\n // Handle user exiting fullscreen by escaping etc\n if (fullscreen.enabled) {\n utils.on(document, fullscreen.eventType, event => {\n this.toggleFullscreen(event);\n });\n }\n },\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event));\n\n // Display duration\n utils.on(this.media, 'durationchange loadedmetadata', event => ui.displayDuration.call(this, event));\n\n // Handle the media finishing\n utils.on(this.media, 'ended', () => {\n // Show poster on end\n if (this.type === 'video' && this.config.showPosterOnEnd) {\n // Restart\n this.restart();\n\n // Re-load media\n this.media.load();\n }\n });\n\n // Check for buffer progress\n utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event));\n\n // Handle native mute\n utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event));\n\n // Handle native play/pause\n utils.on(this.media, 'play pause ended', event => ui.checkPlaying.call(this, event));\n\n // Loading\n utils.on(this.media, 'waiting canplay seeked', event => ui.checkLoading.call(this, event));\n\n // Click video\n if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!wrapper) {\n return;\n }\n\n // Set cursor\n wrapper.style.cursor = 'pointer';\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.config.hideControls && support.touch && !this.media.paused) {\n return;\n }\n\n if (this.media.paused) {\n this.play();\n } else if (this.media.ended) {\n this.restart();\n this.play();\n } else {\n this.pause();\n }\n });\n }\n\n // Disable right click\n if (this.config.disableContextMenu) {\n utils.on(\n this.media,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false\n );\n }\n\n // Speed change\n utils.on(this.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this, 'speed');\n\n // Save to storage\n storage.set.call(this, { speed: this.speed });\n });\n\n // Quality change\n utils.on(this.media, 'qualitychange', () => {\n // Update UI\n controls.updateSetting.call(this, 'quality');\n\n // Save to storage\n storage.set.call(this, { quality: this.quality });\n });\n\n // Caption language change\n utils.on(this.media, 'captionchange', () => {\n // Save to storage\n storage.set.call(this, { language: this.language });\n });\n\n // Volume change\n utils.on(this.media, 'volumechange', () => {\n // Save to storage\n storage.set.call(this, { volume: this.volume, muted: this.muted });\n });\n\n // Captions toggle\n utils.on(this.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this, 'captions');\n\n // Save to storage\n storage.set.call(this, { captions: this.captions.enabled });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.media, this.config.events.concat(['keyup', 'keydown']).join(' '), event => {\n utils.dispatchEvent.call(this, this.elements.container, event.type, true);\n });\n },\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Trigger custom and default handlers\n const proxy = (event, handlerKey, defaultHandler) => {\n const customHandler = this.config.listeners[handlerKey];\n\n // Execute custom handler\n if (utils.is.function(customHandler)) {\n customHandler.call(this, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (!event.defaultPrevented && utils.is.function(defaultHandler)) {\n defaultHandler.call(this, event);\n }\n };\n\n // Click play/pause helper\n const togglePlay = () => {\n const play = this.togglePlay();\n\n // Determine which buttons\n const target = this.elements.buttons[play ? 'pause' : 'play'];\n\n // Transfer focus\n if (utils.is.htmlElement(target)) {\n target.focus();\n }\n };\n\n // Play\n utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.pause, 'click', event => proxy(event, 'pause', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.restart, 'click', event =>\n proxy(event, 'restart', () => {\n this.restart();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.rewind, 'click', event =>\n proxy(event, 'rewind', () => {\n this.rewind();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.forward, 'click', event =>\n proxy(event, 'forward', () => {\n this.forward();\n })\n );\n\n // Mute\n utils.on(this.elements.buttons.mute, 'click', event =>\n proxy(event, 'mute', () => {\n this.muted = !this.muted;\n })\n );\n\n // Captions\n utils.on(this.elements.buttons.captions, 'click', event =>\n proxy(event, 'captions', () => {\n this.toggleCaptions();\n })\n );\n\n // Fullscreen\n utils.on(this.elements.buttons.fullscreen, 'click', event =>\n proxy(event, 'fullscreen', () => {\n this.toggleFullscreen();\n })\n );\n\n // Picture-in-Picture\n utils.on(this.elements.buttons.pip, 'click', event =>\n proxy(event, 'pip', () => {\n this.pip = 'toggle';\n })\n );\n\n // Airplay\n utils.on(this.elements.buttons.airplay, 'click', event =>\n proxy(event, 'airplay', () => {\n this.airPlay();\n })\n );\n\n // Settings menu\n utils.on(this.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Click anywhere closes menu\n utils.on(document.documentElement, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Settings menu\n utils.on(this.elements.settings.form, 'click', event => {\n // Show tab in menu\n controls.showTab.call(this, event);\n\n // Settings menu items - use event delegation as items are added/removed\n // Settings - Language\n if (utils.matches(event.target, this.config.selectors.inputs.language)) {\n proxy(event, 'language', () => {\n this.toggleCaptions(true);\n this.language = event.target.value.toLowerCase();\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.quality)) {\n // Settings - Quality\n proxy(event, 'quality', () => {\n this.quality = event.target.value;\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.speed)) {\n // Settings - Speed\n proxy(event, 'speed', () => {\n this.speed = parseFloat(event.target.value);\n });\n } else if (utils.matches(event.target, this.config.selectors.buttons.loop)) {\n // Settings - Looping\n // TODO: use toggle buttons\n proxy(event, 'loop', () => {\n // TODO: This should be done in the method itself I think\n // var value = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type');\n\n this.console.warn('Set loop');\n });\n }\n });\n\n // Seek\n utils.on(this.elements.inputs.seek, inputEvent, event =>\n proxy(event, 'seek', () => {\n this.currentTime = event.target.value / event.target.max * this.duration;\n })\n );\n\n // Volume\n utils.on(this.elements.inputs.volume, inputEvent, event =>\n proxy(event, 'volume', () => {\n this.volume = event.target.value;\n })\n );\n\n // Polyfill for lower fill in for webkit\n if (browser.isWebkit) {\n utils.on(utils.getElements.call(this, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this, event.target);\n });\n }\n\n // Seek tooltip\n utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(this, event)\n );\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mouseenter mouseleave', event => {\n this.elements.controls.hover = event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Focus in/out on controls\n // TODO: Check we need capture here\n utils.on(\n this.elements.controls,\n 'focus blur',\n event => {\n this.toggleControls(event);\n },\n true\n );\n }\n\n // Mouse wheel for volume\n utils.on(\n this.elements.inputs.volume,\n 'wheel',\n event =>\n proxy(event, 'volume', () => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.decreaseVolume(step);\n direction = -1;\n } else {\n this.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.increaseVolume(step);\n direction = 1;\n } else {\n this.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) {\n event.preventDefault();\n }\n }),\n false\n );\n },\n};\n\nexport default listeners;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport utils from './utils';\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling\n listeners.media.call(this);\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.console.warn(`Basic support only for ${this.type}`);\n\n // Remove controls\n utils.removeElement.call(this, 'controls');\n\n // Remove large play\n utils.removeElement.call(this, 'buttons.play');\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.htmlElement(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n listeners.controls.call(this);\n }\n\n // If there's no controls, bail\n if (!utils.is.htmlElement(this.elements.controls)) {\n return;\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup fullscreen\n fullscreen.setup.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality options\n this.options.quality = [];\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n utils.dispatchEvent.call(this, this.media, 'ready');\n\n // Autoplay\n // TODO: check we still need this?\n /* if (this.isEmbed && this.config.autoplay) {\n this.play();\n } */\n },\n\n // Show the duration on metadataloaded\n displayDuration() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's only one time display, display duration there\n if (!this.elements.display.duration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.currentTime);\n }\n\n // If there's a duration element, update content\n if (this.elements.display.duration) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = this.config.i18n.play;\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (this.supported.ui) {\n if (utils.is.htmlElement(this.elements.buttons.play)) {\n this.elements.buttons.play.setAttribute('aria-label', label);\n }\n if (utils.is.htmlElement(this.elements.buttons.playLarge)) {\n this.elements.buttons.playLarge.setAttribute('aria-label', label);\n }\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.htmlElement(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n\n iframe.setAttribute('title', this.config.i18n.frameTitle.replace('{title}', title));\n }\n },\n\n // Check playing state\n checkPlaying() {\n utils.toggleClass(this.elements.container, this.config.classNames.playing, !this.paused);\n\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);\n\n this.toggleControls(this.paused);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.htmlElement(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update checkbox for mute state\n if (utils.is.htmlElement(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = event.type === 'waiting';\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update seek value and lower fill\n setRange(target, value) {\n if (!utils.is.htmlElement(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set value\n setProgress(target, input) {\n // Default to 0\n const value = !utils.is.undefined(input) ? input : 0;\n const progress = !utils.is.undefined(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.htmlElement(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.htmlElement(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update elements\n updateProgress(event) {\n if (!this.supported.ui) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n value = (() => {\n const { buffered } = this.media;\n\n if (buffered && buffered.length) {\n // HTML5\n return utils.getPercentage(buffered.end(0), this.duration);\n } else if (utils.is.number(buffered)) {\n // YouTube returns between 0 and 1\n return buffered * 100;\n }\n\n return 0;\n })();\n\n ui.setProgress.call(this, this.elements.display.buffer, value);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(value, element) {\n // Bail if there's no duration display\n if (!utils.is.htmlElement(element)) {\n return null;\n }\n\n // Fallback to 0\n const time = !Number.isNaN(value) ? value : 0;\n\n let secs = parseInt(time % 60, 10);\n let mins = parseInt((time / 60) % 60, 10);\n const hours = parseInt((time / 60 / 60) % 60, 10);\n\n // Do we need to display hours?\n const displayHours = parseInt((this.duration / 60 / 60) % 60, 10) > 0;\n\n // Ensure it's two digits. For example, 03 rather than 3.\n secs = `0${secs}`.slice(-2);\n mins = `0${mins}`.slice(-2);\n\n // Generate display\n const display = `${(displayHours ? `${hours}:` : '') + mins}:${secs}`;\n\n // Render\n // eslint-disable-next-line\n element.textContent = display;\n\n // Return for looping\n return display;\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Duration\n ui.updateTimeDisplay.call(this, this.currentTime, this.elements.display.currentTime);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid \n if (!utils.is.htmlElement(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Inject the stylesheet if needed\n if (!utils.is.htmlElement(this.elements.styleSheet)) {\n this.elements.styleSheet = utils.createElement('style');\n this.elements.container.appendChild(this.elements.styleSheet);\n }\n\n const styleSheet = this.elements.styleSheet.sheet;\n const percentage = range.value / range.max * 100;\n const selector = `#${range.id}::-webkit-slider-runnable-track`;\n const styles = `{ background-image: linear-gradient(to right, currentColor ${percentage}%, transparent ${percentage}%) }`;\n\n // Find old rule if it exists\n const index = Array.from(styleSheet.rules).findIndex(rule => rule.selectorText === selector);\n\n // Remove old rule\n if (index !== -1) {\n styleSheet.deleteRule(index);\n }\n\n // Insert new one\n styleSheet.insertRule([selector, styles].join(' '));\n },\n\n // Get icon URL\n getIconUrl() {\n return {\n url: this.config.iconUrl,\n absolute: this.config.iconUrl.indexOf('http') === 0 || (browser.isIE && !window.svg4everybody),\n };\n },\n\n // Create icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.absolute ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create \n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n })\n );\n\n // Create the to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // If the new `href` attribute is supported, use that\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttribute('href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add to \n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type) {\n let text = this.config.i18n[type];\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n return utils.createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n text\n );\n },\n\n // Create a badge\n createBadge(text) {\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text\n )\n );\n\n return badge;\n },\n\n // Create a
to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n const offset = (300 - padding) / 6;\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n this.media.style.transform = `translateY(-${offset}%)`;\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n };\n const params = utils.buildUrlParameters(options);\n const id = utils.parseVimeoId(player.embedId);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = `https://player.vimeo.com/video/${id}?${params}`;\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n player.media.appendChild(iframe);\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe);\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play();\n player.media.paused = false;\n };\n player.media.pause = () => {\n player.embed.pause();\n player.media.paused = true;\n };\n player.media.stop = () => {\n player.embed.stop();\n player.media.paused = true;\n };\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n speed = input;\n player.embed.setPlaybackRate(input);\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n player.embed.setVolume(input);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n muted = toggle;\n player.embed.setVolume(toggle ? 0 : player.config.volume);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n loop = utils.is.boolean(input) ? input : player.config.loop.active;\n player.embed.setLoop(loop);\n },\n });\n\n // Source\n let currentSrc;\n player.embed.getVideoUrl().then(value => {\n currentSrc = value;\n });\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Get available speeds\n if (player.config.controls.includes('settings') && player.config.settings.includes('speed')) {\n controls.setSpeedMenu.call(player);\n }\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.captions.tracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.set.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.htmlElement(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'play');\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n if (parseInt(data.percent, 10) === 1) {\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n // Rebuild UI\n window.setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport youtube from './plugins/youtube';\nimport vimeo from './plugins/vimeo';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.console.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n if (this.supported.ui) {\n // Check for picture-in-picture support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.type === 'video'\n );\n\n // Check for airplay support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.airplay.supported,\n support.airplay && this.isHTML5\n );\n\n // If there's no autoplay attribute, assume the video is stopped and add state class\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.config.autoplay);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch);\n }\n\n // Inject the player wrapper\n if (['video', 'youtube', 'vimeo'].includes(this.type)) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n }\n\n // Embeds\n if (this.isEmbed) {\n switch (this.type) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n }\n\n ui.setTitle.call(this);\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n Array.from(this.media.querySelectorAll('source')).forEach(utils.removeElement);\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.console.log('Cancelled network requests');\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport types from './types';\nimport utils from './utils';\nimport media from './media';\nimport ui from './ui';\nimport support from './support';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.console.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n media.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // TODO: Reset menus here\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.htmlElement(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type\n if ('type' in input) {\n this.type = input.type;\n\n // Get child type for video (it might be an embed)\n if (this.type === 'video') {\n const firstSource = input.sources[0];\n\n if ('type' in firstSource && types.embed.includes(firstSource.type)) {\n this.type = firstSource.type;\n }\n }\n }\n\n // Check for support\n this.supported = support.check(this.type, this.config.inline);\n\n // Create new markup\n switch (this.type) {\n case 'video':\n this.media = utils.createElement('video');\n break;\n\n case 'audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube':\n case 'vimeo':\n this.media = utils.createElement('div');\n this.embedId = input.sources[0].src;\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if ('poster' in input) {\n this.media.setAttribute('poster', input.poster);\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.inline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hooks\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.captions.active,\n this.supported.ui && this.captions.enabled\n );\n\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n },\n true\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.0.0\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport defaults from './defaults';\nimport types from './types';\nimport support from './support';\nimport utils from './utils';\n\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\nimport media from './media';\nimport storage from './storage';\nimport source from './source';\nimport ui from './ui';\n\n// Globals\nlet scrollPosition = {\n x: 0,\n y: 0,\n};\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n this.ready = false;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if (\n (window.jQuery && this.media instanceof jQuery) ||\n utils.is.nodeList(this.media) ||\n utils.is.array(this.media)\n ) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options,\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr'));\n } catch (e) {\n return null;\n }\n })()\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n enabled: null,\n tracks: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n this.console = {\n log() {},\n warn() {},\n error() {},\n };\n if (this.config.debug && 'console' in window) {\n this.console = {\n log: console.log, // eslint-disable-line\n warn: console.warn, // eslint-disable-line\n error: console.error, // eslint-disable-line\n };\n this.console.log('Debugging enabled');\n }\n\n // Log config options and support\n this.console.log('Config', this.config);\n this.console.log('Support', support);\n\n // We need an element to setup\n if (this.media === null || utils.is.undefined(this.media) || !utils.is.htmlElement(this.media)) {\n this.console.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.console.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.console.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n this.elements.original = this.media.cloneNode(true);\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Different setup based on type\n switch (type) {\n // TODO: Handle passing an iframe for true progressive enhancement\n // case 'iframe':\n case 'div':\n this.type = this.media.getAttribute('data-type');\n this.embedId = this.media.getAttribute('data-video-id');\n\n if (utils.is.empty(this.type)) {\n this.console.error('Setup failed: embed type missing');\n return;\n }\n\n if (utils.is.empty(this.embedId)) {\n this.console.error('Setup failed: video id missing');\n return;\n }\n\n // Clean up\n this.media.removeAttribute('data-type');\n this.media.removeAttribute('data-video-id');\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.inline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.console.error('Setup failed: unsupported type');\n return;\n }\n\n // Setup local storage for user settings\n storage.setup.call(this);\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.config.inline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Global listeners\n listeners.global.call(this);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.console.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * If the player is HTML5\n */\n get isHTML5() {\n return types.html5.includes(this.type);\n }\n\n /**\n * If the player is an embed - e.g. YouTube or Vimeo\n */\n get isEmbed() {\n return types.embed.includes(this.type);\n }\n\n /**\n * Play the media\n */\n play() {\n if ('play' in this.media) {\n this.media.play();\n }\n return this;\n }\n\n /**\n * Pause the media\n */\n pause() {\n if ('pause' in this.media) {\n this.media.pause();\n }\n return this;\n }\n\n get paused() {\n return this.media.paused;\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} toggle\n */\n togglePlay(toggle) {\n // True toggle if nothing passed\n if ((!utils.is.boolean(toggle) && this.media.paused) || toggle) {\n return this.play();\n }\n\n return this.pause();\n }\n\n /**\n * Stop playback\n */\n stop() {\n return this.restart().pause();\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n return this;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime.toFixed(4);\n\n // Logging\n this.console.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n get seeking() {\n return this.media.seeking;\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseInt(this.config.duration, 10);\n\n // True duration\n const realDuration = Number(this.media.duration);\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n ({ volume } = storage.get.call(this));\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume, reset muted state\n if (this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return this.media.volume;\n }\n\n // Increase volume\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Decrease volume\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Toggle mute\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = storage.get.call(this).muted;\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n get muted() {\n return this.media.muted;\n }\n\n // Playback speed\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ speed } = storage.get.call(this));\n } else {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.console.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n get speed() {\n return this.media.playbackRate;\n }\n\n // Set playback quality\n set quality(input) {\n let quality = null;\n\n if (utils.is.string(input)) {\n quality = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ quality } = storage.get.call(this));\n } else {\n quality = this.config.quality.selected;\n }\n\n if (!this.options.quality.includes(quality)) {\n this.console.warn(`Unsupported quality option (${quality})`);\n return;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n get quality() {\n return this.media.quality;\n }\n\n // Toggle loop\n // TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n get loop() {\n return this.media.loop;\n }\n\n // Media source\n set source(input) {\n source.change.call(this, input);\n }\n\n get source() {\n return this.media.currentSrc;\n }\n\n // Poster image\n set poster(input) {\n if (this.type !== 'video') {\n this.console.warn('Poster can only be set on HTML5 video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n }\n }\n\n get poster() {\n if (this.type !== 'video') {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n // Autoplay\n get autoplay() {\n return this.config.autoplay;\n }\n\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n // Toggle captions\n toggleCaptions(input) {\n // If there's no full support, or there's no caption toggle\n if (!this.supported.ui || !utils.is.htmlElement(this.elements.buttons.captions)) {\n return this;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input)\n ? input\n : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;\n\n // Nothing to change...\n if (this.captions.enabled === show) {\n return this;\n }\n\n // Set global\n this.captions.enabled = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.enabled);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.enabled);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.enabled ? 'captionsenabled' : 'captionsdisabled');\n\n // Allow chaining\n return this;\n }\n\n // Caption language\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // If nothing to change, bail\n if (this.captions.language === language) {\n return;\n }\n\n // Reset UI\n this.toggleCaptions(true);\n\n // Update config\n this.captions.language = language;\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'captionchange');\n\n // Clear caption\n captions.set.call(this);\n\n // Re-run setup\n captions.setup.call(this);\n }\n\n get language() {\n return this.captions.language;\n }\n\n // Toggle fullscreen\n // Requires user input event\n toggleFullscreen(event) {\n // Check for native support\n if (fullscreen.enabled) {\n // If it's a fullscreen change event, update the UI\n if (utils.is.event(event) && event.type === fullscreen.eventType) {\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n } else {\n // Else it's a user request to enter or exit\n if (!this.fullscreen.active) {\n // Request full screen\n fullscreen.requestFullScreen(this.elements.container);\n } else {\n // Bail from fullscreen\n fullscreen.cancelFullScreen();\n }\n\n // Check if we're actually full screen (it could fail)\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n\n return this;\n }\n } else {\n // Otherwise, it's a simple toggle\n this.fullscreen.active = !this.fullscreen.active;\n\n // Add class hook\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.fullscreen.fallback,\n this.fullscreen.active\n );\n\n // Make sure we don't lose scroll position\n if (this.fullscreen.active) {\n scrollPosition = {\n x: window.pageXOffset || 0,\n y: window.pageYOffset || 0,\n };\n } else {\n window.scrollTo(scrollPosition.x, scrollPosition.y);\n }\n\n // Bind/unbind escape key\n document.body.style.overflow = this.fullscreen.active ? 'hidden' : '';\n }\n\n // Set button state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active);\n }\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.fullscreen.active ? 'enterfullscreen' : 'exitfullscreen');\n\n return this;\n }\n\n // Toggle picture-in-picture\n // TODO: update player with state, support, enabled\n // TODO: detect outside changes\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n // Trigger airplay\n // TODO: update player with state, support, enabled\n airplay() {\n // Bail if no support\n if (!support.airplay) {\n return this;\n }\n\n // Show dialog\n this.media.webkitShowPlaybackTargetPicker();\n\n return this;\n }\n\n // Show the player controls in fullscreen mode\n toggleControls(toggle) {\n const player = this;\n\n // We need controls of course...\n if (!utils.is.htmlElement(this.elements.controls)) {\n return player;\n }\n\n // Don't hide if config says not to, it's audio, or not ready or loading\n if (!this.supported.ui || !this.config.hideControls || this.type === 'audio') {\n return player;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n const loading = utils.hasClass(this.elements.container, this.config.classNames.loading);\n\n // Default to false if no boolean\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Whether to show controls\n show = ['mousemove', 'touchstart', 'mouseenter', 'focus'].includes(toggle.type);\n\n // Delay hiding on move events\n if (['mousemove', 'touchmove'].includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (toggle.type === 'focus') {\n delay = 3000;\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer every movement\n window.clearTimeout(this.timers.hover);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.media.paused || loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.media.paused || loading) {\n return player;\n }\n\n // Delay for hiding on touch\n if (support.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || !this.media.paused) {\n this.timers.hover = window.setTimeout(() => {\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, true);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n\n return this;\n }\n\n // Event listeners\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n return this;\n }\n\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n return this;\n }\n\n // Check for support\n supports(type) {\n return support.mime.call(this, type);\n }\n\n // Destroy an instance\n // Event listeners are removed when elements are removed\n // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n destroy(callback, soft = false) {\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n this.embedId = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove buttons\n if (this.elements.buttons && this.elements.buttons.play) {\n Array.from(this.elements.buttons.play).forEach(button => utils.removeElement(button));\n }\n\n // Remove others\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Replace the container with the original element provided\n const parent = this.elements.container.parentNode;\n\n if (utils.is.htmlElement(parent)) {\n parent.replaceChild(this.elements.original, this.elements.container);\n }\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Clear for GC\n this.elements = null;\n }\n };\n\n // Type specific stuff\n switch (this.type) {\n case 'youtube':\n // Clear timers\n window.clearInterval(this.timers.buffering);\n window.clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n this.embed.destroy();\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n this.embed.unload().then(done);\n\n // Vimeo does not always return\n window.setTimeout(done, 200);\n\n break;\n\n case 'video':\n case 'audio':\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n default:\n break;\n }\n }\n}\n\nexport default Plyr;\n"],"names":["get","store","window","localStorage","getItem","this","config","storage","key","utils","is","empty","JSON","parse","set","object","support","enabled","call","extend","setItem","stringify","defaults","navigator","language","split","types","input","getConstructor","Object","Number","isNaN","String","Boolean","Function","undefined","Array","isArray","NodeList","HTMLElement","Event","instanceOf","TextTrackCue","VTTCue","TextTrack","kind","string","array","nodeList","length","keys","constructor","document","documentMode","documentElement","style","test","userAgent","platform","url","callback","querySelectorAll","element","createElement","src","first","getElementsByTagName","function","addEventListener","event","parentNode","insertBefore","id","updateSprite","data","innerHTML","body","childNodes","hasId","container","setAttribute","cached","content","xhr","XMLHttpRequest","open","onload","responseText","send","prefix","Math","floor","random","self","top","e","elements","wrapper","targets","from","reverse","forEach","index","child","cloneNode","parent","sibling","nextSibling","appendChild","htmlElement","removeChild","target","type","attributes","text","setAttributes","textContent","lastChild","sel","existingAttributes","existing","selector","s","trim","className","replace","parts","value","charAt","class","toggle","contains","classList","prototype","Element","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","includes","querySelector","controls","getElement","selectors","buttons","getElements","play","pause","restart","rewind","forward","mute","pip","airplay","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","currentTime","seekTooltip","classNames","tooltip","error","console","warn","toggleNativeControls","focused","activeElement","tabbables","last","on","keyCode","_this","active","getFocusElement","shiftKey","focus","preventDefault","passive","capture","Node","toggleListener","events","options","boolean","passiveListeners","bubbles","properties","CustomEvent","assign","Plyr","dispatchEvent","state","getAttribute","current","max","toFixed","objects","destination","shift","source","property","match","RegExp","$2","number","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","ratio","getRatio","w","h","find","inline","api","ui","browser","getBrowser","playsInline","isIPhone","video","rangeInput","audio","removeItem","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","canPlayType","supported","defineProperty","range","transitionEnd","matchMedia","cancelFullScreen","some","pre","msExitFullscreen","msFullscreenEnabled","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","fullscreenElement","mozFullScreenElement","requestFullScreen","nativeSupport","fallback","inFrame","log","toggleClass","toggleState","trapFocus","setup","parseFloat","listeners","getKeyCode","which","handleKey","code","pressed","held","editable","stopPropagation","togglePlay","increaseVolume","decreaseVolume","muted","toggleFullscreen","toggleCaptions","keyboard","global","tabFocus","setTimeout","hideControls","toggleControls","eventType","timeUpdate","displayDuration","_this2","showPosterOnEnd","load","updateProgress","updateVolume","checkPlaying","checkLoading","clickToPlay","cursor","touch","paused","ended","disableContextMenu","updateSetting","speed","quality","concat","inputEvent","isIE","proxy","handlerKey","defaultHandler","customHandler","_this3","defaultPrevented","airPlay","toggleMenu","form","showTab","toLowerCase","loop","isWebkit","updateRangeFill","updateSeekTooltip","hover","inverted","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","uiSupported","isHTML5","removeAttribute","removeElement","inject","ready","updateTimeDisplay","label","i18n","title","playLarge","isEmbed","iframe","frameTitle","playing","stopped","setRange","loading","timers","nodeValue","getPercentage","buffered","end","setProgress","time","secs","parseInt","mins","hours","displayHours","slice","seeking","styleSheet","sheet","percentage","styles","rules","findIndex","rule","selectorText","deleteRule","insertRule","iconUrl","indexOf","svg4everybody","getIconUrl","iconPath","absolute","iconPrefix","icon","createElementNS","use","path","setAttributeNS","hidden","badge","menu","buttonType","attr","button","iconDefault","iconToggled","labelKey","control","getAttributesFromSelector","createIcon","createLabel","suffix","played","tooltips","percent","clientRect","getBoundingClientRect","visible","pageX","left","hasClass","setting","tab","tabs","pane","panes","list","filter","toggleTab","emptyElement","getBadge","createBadge","item","radio","createTextNode","getLabel","getLanguage","default","checked","option","textTracks","tracks","none","currentTrack","disabled","track","toUpperCase","unshift","_this4","insertAdjacentHTML","show","isMenuItem","isButton","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","transitions","reducedMotion","size","getTabSize","restore","propertyName","off","createButton","createRange","createProgress","createTime","inner","home","_this5","back","setSpeedMenu","loadSprite","seekTime","create","findElements","labels","_this6","setCaptionsMenu","insertAfter","setCurrentTrack","setCue","mode","activeCues","embed","enableTextTrack","cue","getCueAsHTML","caption","youtube","videoId","parseYouTubeId","embedId","containers","setAspectRatio","generateId","YT","loadScript","urls","onYouTubeReadyCallbacks","push","onYouTubeIframeAPIReady","paddingBottom","player","Player","autoplay","location","hostname","href","instance","getPlaybackQuality","playbackRate","getPlaybackRate","playVideo","pauseVideo","stop","stopVideo","getDuration","getCurrentTime","seekTo","setPlaybackRate","setPlaybackQuality","setVolume","getVideoUrl","getAvailablePlaybackRates","getVideoData","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","build","setQualityMenu","getAvailableQualityLevels","vimeo","Vimeo","padding","offset","transform","params","buildUrlParameters","parseVimeoId","setCurrentTime","selected","setLoop","currentSrc","then","all","getVideoWidth","getVideoHeight","getAspectRatio","dimensions","getVideoTitle","getTextTracks","cues","stripHTML","seconds","isIos","isTouch","wrap","setTitle","blankVideo","insertElement","attribute","sources","cancelRequests","destroy","firstSource","check","crossorigin","poster","addStyleHook","insertElements","scrollPosition","jQuery","debug","plyr","original","tagName","hasAttribute","step","isFullScreen","pageXOffset","pageYOffset","scrollTo","x","y","overflow","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","clearTimeout","mime","soft","done","replaceChild","unload","html5","targetTime","fauxDuration","realDuration","change","states","webkitPresentationMode"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"plyr.js","sources":["src/js/storage.js","src/js/defaults.js","src/js/types.js","src/js/utils.js","src/js/support.js","src/js/fullscreen.js","src/js/listeners.js","src/js/ui.js","src/js/controls.js","src/js/captions.js","src/js/plugins/youtube.js","src/js/plugins/vimeo.js","src/js/media.js","src/js/source.js","src/js/plyr.js"],"sourcesContent":["// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\n// Get contents of local storage\nfunction get() {\n const store = window.localStorage.getItem(this.config.storage.key);\n\n if (utils.is.empty(store)) {\n return {};\n }\n\n return JSON.parse(store);\n}\n\n// Save a value back to local storage\nfunction set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n const storage = get.call(this);\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.config.storage.key, JSON.stringify(storage));\n}\n\n// Setup localStorage\nfunction setup() {\n let value = null;\n let storage = {};\n\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return storage;\n }\n\n // Clean up old volume\n // https://github.com/sampotts/plyr/issues/171\n window.localStorage.removeItem('plyr-volume');\n\n // load value from the current key\n value = window.localStorage.getItem(this.config.storage.key);\n\n if (!value) {\n // Key wasn't set (or had been cleared), move along\n } else if (/^\\d+(\\.\\d+)?$/.test(value)) {\n // If value is a number, it's probably volume from an older\n // version of this. See: https://github.com/sampotts/plyr/pull/313\n // Update the key to be JSON\n set({\n volume: parseFloat(value),\n });\n } else {\n // Assume it's JSON from this or a later version of plyr\n storage = JSON.parse(value);\n }\n\n return storage;\n}\n\nexport default { setup, set, get };\n","// Default config\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration\n displayDuration: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video to play\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Revert to poster on finish (HTML5 - will cause reload)\n showPosterOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/2.0.10/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 'default',\n options: ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'default'],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: window.navigator.language.split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n 'play',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed', 'loop'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime} secs',\n play: 'Play',\n pause: 'Pause',\n forward: 'Forward {seektime} secs',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n toggleMute: 'Toggle Mute',\n toggleCaptions: 'Toggle Captions',\n toggleFullscreen: 'Toggle Fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n none: 'None',\n disabled: 'Disabled',\n },\n\n // URLs\n urls: {\n vimeo: {\n api: 'https://player.vimeo.com/api/player.js',\n },\n youtube: {\n api: 'https://www.youtube.com/iframe_api',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n forward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n forward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n control: 'plyr__control',\n type: 'plyr--{0}',\n stopped: 'plyr--stopped',\n playing: 'plyr--playing',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr supported types\n// ==========================================================================\n\nconst types = {\n embed: ['youtube', 'vimeo'],\n html5: ['video', 'audio'],\n};\n\nexport default types;\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport support from './support';\n\nconst utils = {\n // Check variable types\n is: {\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.undefined(input) && Array.isArray(input);\n },\n nodeList(input) {\n return !this.undefined(input) && input instanceof NodeList;\n },\n htmlElement(input) {\n return !this.undefined(input) && input instanceof HTMLElement;\n },\n event(input) {\n return !this.undefined(input) && input instanceof Event;\n },\n cue(input) {\n return this.instanceOf(input, window.TextTrackCue) || this.instanceOf(input, window.VTTCue);\n },\n track(input) {\n return (\n !this.undefined(input) && (this.instanceOf(input, window.TextTrack) || typeof input.kind === 'string')\n );\n },\n undefined(input) {\n return input !== null && typeof input === 'undefined';\n },\n empty(input) {\n return (\n input === null ||\n typeof input === 'undefined' ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && input.length === 0) ||\n (this.object(input) && Object.keys(input).length === 0)\n );\n },\n getConstructor(input) {\n if (input === null || typeof input === 'undefined') {\n return null;\n }\n\n return input.constructor;\n },\n instanceOf(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Load an external script\n loadScript(url, callback) {\n // Check script is not already referenced\n if (document.querySelectorAll(`script[src=\"${url}\"]`).length) {\n return;\n }\n\n // Build the element\n const element = document.createElement('script');\n element.src = url;\n\n // Find first script\n const first = document.getElementsByTagName('script')[0];\n\n // Bind callback\n if (utils.is.function(callback)) {\n element.addEventListener('load', event => callback.call(null, event), false);\n }\n\n // Inject\n first.parentNode.insertBefore(element, first);\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (typeof url !== 'string') {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = typeof id === 'string';\n let isCached = false;\n\n function updateSprite(data) {\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once\n if (!hasId || !document.querySelectorAll(`#${id}`).length) {\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n updateSprite.call(container, data.content);\n }\n }\n\n // ReSharper disable once InconsistentNaming\n const xhr = new XMLHttpRequest();\n\n // XHR for Chrome/Firefox/Opera/Safari\n if ('withCredentials' in xhr) {\n xhr.open('GET', url, true);\n } else {\n return;\n }\n\n // Once loaded, inject to container and body\n xhr.onload = () => {\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: xhr.responseText,\n })\n );\n }\n\n updateSprite.call(container, xhr.responseText);\n };\n\n xhr.send();\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Determine if we're in an iframe\n inFrame() {\n try {\n return window.self !== window.top;\n } catch (e) {\n return true;\n }\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Remove an element\n removeElement(element) {\n if (!utils.is.htmlElement(element) || !utils.is.htmlElement(element.parentNode)) {\n return null;\n }\n\n element.parentNode.removeChild(element);\n\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new \n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new \n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n Object.keys(attributes).forEach(key => {\n element.setAttribute(key, attributes[key]);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.htmlElement(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.htmlElement(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n forward: utils.getElement.call(this, this.config.selectors.buttons.forward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n };\n\n // Seek tooltip\n if (utils.is.htmlElement(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.console.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus() {\n const tabbables = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = tabbables[0];\n const last = tabbables[tabbables.length - 1];\n\n utils.on(\n this.elements.container,\n 'keydown',\n event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9 || !this.fullscreen.active) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n },\n false\n );\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle, passive, capture) {\n // Bail if no elements\n if (elements === null || utils.is.undefined(elements)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just capture boolean\n let options = utils.is.boolean(capture) ? capture : false;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive: utils.is.boolean(passive) ? passive : true,\n // Whether the listener is a capturing listener or not\n capture: utils.is.boolean(capture) ? capture : false,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type, bubbles, properties) {\n // Bail if no element\n if (!element || !type) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles: utils.is.boolean(bubbles) ? bubbles : false,\n detail: Object.assign({}, properties, {\n plyr: this instanceof Plyr ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // Bail if no target\n if (!utils.is.htmlElement(element)) {\n return;\n }\n\n // Get state\n const state = utils.is.boolean(input) ? input : !element.getAttribute('aria-pressed');\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n return (current / max * 100).toFixed(2);\n },\n\n // Deep extend/merge destination object with N more objects\n // http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/\n // Removed call to arguments.callee (used explicit function name instead)\n extend(...objects) {\n const { length } = objects;\n\n // Bail if nothing to merge\n if (!length) {\n return null;\n }\n\n // Return first if specified but nothing to merge\n if (length === 1) {\n return objects[0];\n }\n\n // First object is the destination\n let destination = Array.prototype.shift.call(objects);\n if (!utils.is.object(destination)) {\n destination = {};\n }\n\n // Loop through all objects to merge\n objects.forEach(source => {\n if (!utils.is.object(source)) {\n return;\n }\n\n Object.keys(source).forEach(property => {\n if (source[property] && source[property].constructor && source[property].constructor === Object) {\n destination[property] = destination[property] || {};\n utils.extend(destination[property], source[property]);\n } else {\n destination[property] = source[property];\n }\n });\n });\n\n return destination;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert object to URL parameters\n buildUrlParameters(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n transitionEnd: (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return typeof type === 'string' ? type : false;\n })(),\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, inline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const playsInline = browser.isIPhone && inline && support.inline;\n\n switch (type) {\n case 'video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'vimeo':\n api = true;\n ui = support.rangeInput && !browser.isIPhone;\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Local storage\n // We can't assume if local storage is present that we can use it\n storage: (() => {\n if (!('localStorage' in window)) {\n return false;\n }\n\n // Try to use it (it might be disabled, e.g. user is in private/porn mode)\n // see: https://github.com/sampotts/plyr/issues/131\n const test = '___test';\n try {\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n return true;\n } catch (e) {\n return false;\n }\n })(),\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n inline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Type specific checks\n if (this.type === 'video') {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.type === 'audio') {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // Remember a device can be moust + touch enabled\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEnd !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr fullscreen API\n// ==========================================================================\n\nimport utils from './utils';\n\n// Determine the prefix\nconst prefix = (() => {\n let value = false;\n\n if (utils.is.function(document.cancelFullScreen)) {\n value = '';\n } else {\n // Check for fullscreen support by vendor prefix\n ['webkit', 'o', 'moz', 'ms', 'khtml'].some(pre => {\n if (utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n } else if (utils.is.function(document.msExitFullscreen) && document.msFullscreenEnabled) {\n // Special case for MS (when isn't it?)\n value = 'ms';\n return true;\n }\n\n return false;\n });\n }\n\n return value;\n})();\n\n// Fullscreen API\nconst fullscreen = {\n // Get the prefix\n prefix,\n\n // Check if we can use it\n enabled:\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled,\n\n // Yet again Microsoft awesomeness,\n // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes\n eventType: prefix === 'ms' ? 'MSFullscreenChange' : `${prefix}fullscreenchange`,\n\n // Is an element fullscreen\n isFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n switch (prefix) {\n case '':\n return document.fullscreenElement === target;\n\n case 'moz':\n return document.mozFullScreenElement === target;\n\n default:\n return document[`${prefix}FullscreenElement`] === target;\n }\n },\n\n // Make an element fullscreen\n requestFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n return !prefix.length\n ? target.requestFullScreen()\n : target[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();\n },\n\n // Bail from fullscreen\n cancelFullScreen() {\n if (!fullscreen.enabled) {\n return false;\n }\n\n return !prefix.length\n ? document.cancelFullScreen()\n : document[prefix + (prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')]();\n },\n\n // Get the current element\n element() {\n if (!fullscreen.enabled) {\n return null;\n }\n\n return !prefix.length ? document.fullscreenElement : document[`${prefix}FullscreenElement`];\n },\n\n // Setup fullscreen\n setup() {\n if (!this.supported.ui || this.type === 'audio' || !this.config.fullscreen.enabled) {\n return;\n }\n\n // Check for native support\n const nativeSupport = fullscreen.enabled;\n\n if (nativeSupport || (this.config.fullscreen.fallback && !utils.inFrame())) {\n this.console.log(`${nativeSupport ? 'Native' : 'Fallback'} fullscreen enabled`);\n\n // Add styling hook to show button\n utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.enabled, true);\n } else {\n this.console.log('Fullscreen not supported and fallback disabled');\n }\n\n // Toggle state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, false);\n }\n\n // Trap focus in container\n utils.trapFocus.call(this);\n },\n};\n\nexport default fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport storage from './storage';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst listeners = {\n // Global listeners\n global() {\n let last = null;\n\n // Get the key code for an event\n const getKeyCode = event => (event.keyCode ? event.keyCode : event.which);\n\n // Handle key press\n const handleKey = event => {\n const code = getKeyCode(event);\n const pressed = event.type === 'keydown';\n const held = pressed && code === last;\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.currentTime = this.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.htmlElement(focused) && utils.matches(focused, this.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!held) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!held) {\n this.console.warn('togglePlay', event.type);\n this.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!held) {\n this.muted = 'toggle';\n }\n break;\n\n case 39:\n // Arrow forward\n this.forward();\n break;\n\n case 37:\n // Arrow back\n this.rewind();\n break;\n\n case 70:\n // F key\n this.toggleFullscreen();\n break;\n\n case 67:\n // C key\n if (!held) {\n this.toggleCaptions();\n }\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!fullscreen.enabled && this.fullscreen.active && code === 27) {\n this.toggleFullscreen();\n }\n\n // Store last code for next cycle\n last = code;\n } else {\n last = null;\n }\n };\n\n // Keyboard shortcuts\n if (this.config.keyboard.global) {\n utils.on(window, 'keydown keyup', handleKey, false);\n } else if (this.config.keyboard.focused) {\n utils.on(this.elements.container, 'keydown keyup', handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n window.setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(\n this.elements.container,\n 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen',\n event => {\n this.toggleControls(event);\n }\n );\n }\n\n // Handle user exiting fullscreen by escaping etc\n if (fullscreen.enabled) {\n utils.on(document, fullscreen.eventType, event => {\n this.toggleFullscreen(event);\n });\n }\n },\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event));\n\n // Display duration\n utils.on(this.media, 'durationchange loadedmetadata', event => ui.displayDuration.call(this, event));\n\n // Handle the media finishing\n utils.on(this.media, 'ended', () => {\n // Show poster on end\n if (this.type === 'video' && this.config.showPosterOnEnd) {\n // Restart\n this.restart();\n\n // Re-load media\n this.media.load();\n }\n });\n\n // Check for buffer progress\n utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event));\n\n // Handle native mute\n utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event));\n\n // Handle native play/pause\n utils.on(this.media, 'play pause ended', event => ui.checkPlaying.call(this, event));\n\n // Loading\n utils.on(this.media, 'waiting canplay seeked', event => ui.checkLoading.call(this, event));\n\n // Click video\n if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!wrapper) {\n return;\n }\n\n // Set cursor\n wrapper.style.cursor = 'pointer';\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.config.hideControls && support.touch && !this.media.paused) {\n return;\n }\n\n if (this.media.paused) {\n this.play();\n } else if (this.media.ended) {\n this.restart();\n this.play();\n } else {\n this.pause();\n }\n });\n }\n\n // Disable right click\n if (this.config.disableContextMenu) {\n utils.on(\n this.media,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false\n );\n }\n\n // Speed change\n utils.on(this.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this, 'speed');\n\n // Save to storage\n storage.set.call(this, { speed: this.speed });\n });\n\n // Quality change\n utils.on(this.media, 'qualitychange', () => {\n // Update UI\n controls.updateSetting.call(this, 'quality');\n\n // Save to storage\n storage.set.call(this, { quality: this.quality });\n });\n\n // Caption language change\n utils.on(this.media, 'languagechange', () => {\n // Save to storage\n storage.set.call(this, { language: this.language });\n });\n\n // Volume change\n utils.on(this.media, 'volumechange', () => {\n // Save to storage\n storage.set.call(this, { volume: this.volume, muted: this.muted });\n });\n\n // Captions toggle\n utils.on(this.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this, 'captions');\n\n // Save to storage\n storage.set.call(this, { captions: this.captions.enabled });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.media, this.config.events.concat(['keyup', 'keydown']).join(' '), event => {\n utils.dispatchEvent.call(this, this.elements.container, event.type, true);\n });\n },\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Trigger custom and default handlers\n const proxy = (event, handlerKey, defaultHandler) => {\n const customHandler = this.config.listeners[handlerKey];\n\n // Execute custom handler\n if (utils.is.function(customHandler)) {\n customHandler.call(this, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (!event.defaultPrevented && utils.is.function(defaultHandler)) {\n defaultHandler.call(this, event);\n }\n };\n\n // Click play/pause helper\n const togglePlay = () => {\n const play = this.togglePlay();\n\n // Determine which buttons\n const target = this.elements.buttons[play ? 'pause' : 'play'];\n\n // Transfer focus\n if (utils.is.htmlElement(target)) {\n target.focus();\n }\n };\n\n // Play\n utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.pause, 'click', event => proxy(event, 'pause', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.restart, 'click', event =>\n proxy(event, 'restart', () => {\n this.restart();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.rewind, 'click', event =>\n proxy(event, 'rewind', () => {\n this.rewind();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.forward, 'click', event =>\n proxy(event, 'forward', () => {\n this.forward();\n })\n );\n\n // Mute\n utils.on(this.elements.buttons.mute, 'click', event =>\n proxy(event, 'mute', () => {\n this.muted = !this.muted;\n })\n );\n\n // Captions\n utils.on(this.elements.buttons.captions, 'click', event =>\n proxy(event, 'captions', () => {\n this.toggleCaptions();\n })\n );\n\n // Fullscreen\n utils.on(this.elements.buttons.fullscreen, 'click', event =>\n proxy(event, 'fullscreen', () => {\n this.toggleFullscreen();\n })\n );\n\n // Picture-in-Picture\n utils.on(this.elements.buttons.pip, 'click', event =>\n proxy(event, 'pip', () => {\n this.pip = 'toggle';\n })\n );\n\n // Airplay\n utils.on(this.elements.buttons.airplay, 'click', event =>\n proxy(event, 'airplay', () => {\n this.airPlay();\n })\n );\n\n // Settings menu\n utils.on(this.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Click anywhere closes menu\n utils.on(document.documentElement, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Settings menu\n utils.on(this.elements.settings.form, 'click', event => {\n // Show tab in menu\n controls.showTab.call(this, event);\n\n // Settings menu items - use event delegation as items are added/removed\n // Settings - Language\n if (utils.matches(event.target, this.config.selectors.inputs.language)) {\n proxy(event, 'language', () => {\n this.toggleCaptions(true);\n this.language = event.target.value.toLowerCase();\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.quality)) {\n // Settings - Quality\n proxy(event, 'quality', () => {\n this.quality = event.target.value;\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.speed)) {\n // Settings - Speed\n proxy(event, 'speed', () => {\n this.speed = parseFloat(event.target.value);\n });\n } else if (utils.matches(event.target, this.config.selectors.buttons.loop)) {\n // Settings - Looping\n // TODO: use toggle buttons\n proxy(event, 'loop', () => {\n // TODO: This should be done in the method itself I think\n // var value = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type');\n\n this.console.warn('Set loop');\n });\n }\n });\n\n // Seek\n utils.on(this.elements.inputs.seek, inputEvent, event =>\n proxy(event, 'seek', () => {\n this.currentTime = event.target.value / event.target.max * this.duration;\n })\n );\n\n // Volume\n utils.on(this.elements.inputs.volume, inputEvent, event =>\n proxy(event, 'volume', () => {\n this.volume = event.target.value;\n })\n );\n\n // Polyfill for lower fill in for webkit\n if (browser.isWebkit) {\n utils.on(utils.getElements.call(this, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this, event.target);\n });\n }\n\n // Seek tooltip\n utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(this, event)\n );\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mouseenter mouseleave', event => {\n this.elements.controls.hover = event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Focus in/out on controls\n // TODO: Check we need capture here\n utils.on(\n this.elements.controls,\n 'focus blur',\n event => {\n this.toggleControls(event);\n },\n true\n );\n }\n\n // Mouse wheel for volume\n utils.on(\n this.elements.inputs.volume,\n 'wheel',\n event =>\n proxy(event, 'volume', () => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.decreaseVolume(step);\n direction = -1;\n } else {\n this.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.increaseVolume(step);\n direction = 1;\n } else {\n this.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) {\n event.preventDefault();\n }\n }),\n false\n );\n },\n};\n\nexport default listeners;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport utils from './utils';\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling\n listeners.media.call(this);\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.console.warn(`Basic support only for ${this.type}`);\n\n // Remove controls\n utils.removeElement.call(this, 'controls');\n\n // Remove large play\n utils.removeElement.call(this, 'buttons.play');\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.htmlElement(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n listeners.controls.call(this);\n }\n\n // If there's no controls, bail\n if (!utils.is.htmlElement(this.elements.controls)) {\n return;\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup fullscreen\n fullscreen.setup.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality options\n this.options.quality = [];\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n utils.dispatchEvent.call(this, this.media, 'ready');\n\n // Autoplay\n // TODO: check we still need this?\n /* if (this.isEmbed && this.config.autoplay) {\n this.play();\n } */\n },\n\n // Show the duration on metadataloaded\n displayDuration() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's only one time display, display duration there\n if (!this.elements.display.duration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.currentTime);\n }\n\n // If there's a duration element, update content\n if (this.elements.display.duration) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = this.config.i18n.play;\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (this.supported.ui) {\n if (utils.is.htmlElement(this.elements.buttons.play)) {\n this.elements.buttons.play.setAttribute('aria-label', label);\n }\n if (utils.is.htmlElement(this.elements.buttons.playLarge)) {\n this.elements.buttons.playLarge.setAttribute('aria-label', label);\n }\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.htmlElement(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n\n iframe.setAttribute('title', this.config.i18n.frameTitle.replace('{title}', title));\n }\n },\n\n // Check playing state\n checkPlaying() {\n utils.toggleClass(this.elements.container, this.config.classNames.playing, !this.paused);\n\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);\n\n this.toggleControls(this.paused);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.htmlElement(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update checkbox for mute state\n if (utils.is.htmlElement(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = event.type === 'waiting';\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update seek value and lower fill\n setRange(target, value) {\n if (!utils.is.htmlElement(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set value\n setProgress(target, input) {\n // Default to 0\n const value = !utils.is.undefined(input) ? input : 0;\n const progress = !utils.is.undefined(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.htmlElement(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.htmlElement(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update elements\n updateProgress(event) {\n if (!this.supported.ui) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n value = (() => {\n const { buffered } = this.media;\n\n if (buffered && buffered.length) {\n // HTML5\n return utils.getPercentage(buffered.end(0), this.duration);\n } else if (utils.is.number(buffered)) {\n // YouTube returns between 0 and 1\n return buffered * 100;\n }\n\n return 0;\n })();\n\n ui.setProgress.call(this, this.elements.display.buffer, value);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(value, element) {\n // Bail if there's no duration display\n if (!utils.is.htmlElement(element)) {\n return null;\n }\n\n // Fallback to 0\n const time = !Number.isNaN(value) ? value : 0;\n\n let secs = parseInt(time % 60, 10);\n let mins = parseInt((time / 60) % 60, 10);\n const hours = parseInt((time / 60 / 60) % 60, 10);\n\n // Do we need to display hours?\n const displayHours = parseInt((this.duration / 60 / 60) % 60, 10) > 0;\n\n // Ensure it's two digits. For example, 03 rather than 3.\n secs = `0${secs}`.slice(-2);\n mins = `0${mins}`.slice(-2);\n\n // Generate display\n const display = `${(displayHours ? `${hours}:` : '') + mins}:${secs}`;\n\n // Render\n // eslint-disable-next-line\n element.textContent = display;\n\n // Return for looping\n return display;\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Duration\n ui.updateTimeDisplay.call(this, this.currentTime, this.elements.display.currentTime);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid \n if (!utils.is.htmlElement(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Inject the stylesheet if needed\n if (!utils.is.htmlElement(this.elements.styleSheet)) {\n this.elements.styleSheet = utils.createElement('style');\n this.elements.container.appendChild(this.elements.styleSheet);\n }\n\n const styleSheet = this.elements.styleSheet.sheet;\n const percentage = range.value / range.max * 100;\n const selector = `#${range.id}::-webkit-slider-runnable-track`;\n const styles = `{ background-image: linear-gradient(to right, currentColor ${percentage}%, transparent ${percentage}%) }`;\n\n // Find old rule if it exists\n const index = Array.from(styleSheet.rules).findIndex(rule => rule.selectorText === selector);\n\n // Remove old rule\n if (index !== -1) {\n styleSheet.deleteRule(index);\n }\n\n // Insert new one\n styleSheet.insertRule([selector, styles].join(' '));\n },\n\n // Get icon URL\n getIconUrl() {\n return {\n url: this.config.iconUrl,\n absolute: this.config.iconUrl.indexOf('http') === 0 || (browser.isIE && !window.svg4everybody),\n };\n },\n\n // Create icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.absolute ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create \n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n })\n );\n\n // Create the to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // If the new `href` attribute is supported, use that\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttribute('href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add to \n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type) {\n let text = this.config.i18n[type];\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n return utils.createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n text\n );\n },\n\n // Create a badge\n createBadge(text) {\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text\n )\n );\n\n return badge;\n },\n\n // Create a
to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n const offset = (300 - padding) / 6;\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n this.media.style.transform = `translateY(-${offset}%)`;\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n };\n const params = utils.buildUrlParameters(options);\n const id = utils.parseVimeoId(player.embedId);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = `https://player.vimeo.com/video/${id}?${params}`;\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n player.media.appendChild(iframe);\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe);\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play();\n player.media.paused = false;\n };\n player.media.pause = () => {\n player.embed.pause();\n player.media.paused = true;\n };\n player.media.stop = () => {\n player.embed.stop();\n player.media.paused = true;\n };\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n speed = input;\n player.embed.setPlaybackRate(input);\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n player.embed.setVolume(input);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n muted = toggle;\n player.embed.setVolume(toggle ? 0 : player.config.volume);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n loop = utils.is.boolean(input) ? input : player.config.loop.active;\n player.embed.setLoop(loop);\n },\n });\n\n // Source\n let currentSrc;\n player.embed.getVideoUrl().then(value => {\n currentSrc = value;\n });\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Get available speeds\n if (player.config.controls.includes('settings') && player.config.settings.includes('speed')) {\n controls.setSpeedMenu.call(player);\n }\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.captions.tracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.set.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.htmlElement(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'play');\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n if (parseInt(data.percent, 10) === 1) {\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n // Rebuild UI\n window.setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport youtube from './plugins/youtube';\nimport vimeo from './plugins/vimeo';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.console.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n if (this.supported.ui) {\n // Check for picture-in-picture support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.type === 'video'\n );\n\n // Check for airplay support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.airplay.supported,\n support.airplay && this.isHTML5\n );\n\n // If there's no autoplay attribute, assume the video is stopped and add state class\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.config.autoplay);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch);\n }\n\n // Inject the player wrapper\n if (['video', 'youtube', 'vimeo'].includes(this.type)) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n }\n\n // Embeds\n if (this.isEmbed) {\n switch (this.type) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n }\n\n ui.setTitle.call(this);\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n Array.from(this.media.querySelectorAll('source')).forEach(utils.removeElement);\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.console.log('Cancelled network requests');\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport types from './types';\nimport utils from './utils';\nimport media from './media';\nimport ui from './ui';\nimport support from './support';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.console.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n media.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // TODO: Reset menus here\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.htmlElement(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type\n if ('type' in input) {\n this.type = input.type;\n\n // Get child type for video (it might be an embed)\n if (this.type === 'video') {\n const firstSource = input.sources[0];\n\n if ('type' in firstSource && types.embed.includes(firstSource.type)) {\n this.type = firstSource.type;\n }\n }\n }\n\n // Check for support\n this.supported = support.check(this.type, this.config.inline);\n\n // Create new markup\n switch (this.type) {\n case 'video':\n this.media = utils.createElement('video');\n break;\n\n case 'audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube':\n case 'vimeo':\n this.media = utils.createElement('div');\n this.embedId = input.sources[0].src;\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if ('poster' in input) {\n this.media.setAttribute('poster', input.poster);\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.inline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hooks\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.captions.active,\n this.supported.ui && this.captions.enabled\n );\n\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n },\n true\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.0.0\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport defaults from './defaults';\nimport types from './types';\nimport support from './support';\nimport utils from './utils';\n\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\nimport media from './media';\nimport storage from './storage';\nimport source from './source';\nimport ui from './ui';\n\n// Globals\nlet scrollPosition = {\n x: 0,\n y: 0,\n};\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n this.ready = false;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if (\n (window.jQuery && this.media instanceof jQuery) ||\n utils.is.nodeList(this.media) ||\n utils.is.array(this.media)\n ) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options,\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr'));\n } catch (e) {\n return null;\n }\n })()\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n enabled: null,\n tracks: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n this.console = {\n log() {},\n warn() {},\n error() {},\n };\n if (this.config.debug && 'console' in window) {\n this.console = {\n log: console.log, // eslint-disable-line\n warn: console.warn, // eslint-disable-line\n error: console.error, // eslint-disable-line\n };\n this.console.log('Debugging enabled');\n }\n\n // Log config options and support\n this.console.log('Config', this.config);\n this.console.log('Support', support);\n\n // We need an element to setup\n if (this.media === null || utils.is.undefined(this.media) || !utils.is.htmlElement(this.media)) {\n this.console.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.console.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.console.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n this.elements.original = this.media.cloneNode(true);\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Different setup based on type\n switch (type) {\n // TODO: Handle passing an iframe for true progressive enhancement\n // case 'iframe':\n case 'div':\n this.type = this.media.getAttribute('data-type');\n this.embedId = this.media.getAttribute('data-video-id');\n\n if (utils.is.empty(this.type)) {\n this.console.error('Setup failed: embed type missing');\n return;\n }\n\n if (utils.is.empty(this.embedId)) {\n this.console.error('Setup failed: video id missing');\n return;\n }\n\n // Clean up\n this.media.removeAttribute('data-type');\n this.media.removeAttribute('data-video-id');\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.inline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.console.error('Setup failed: unsupported type');\n return;\n }\n\n // Setup local storage for user settings\n storage.setup.call(this);\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.config.inline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Global listeners\n listeners.global.call(this);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.console.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * If the player is HTML5\n */\n get isHTML5() {\n return types.html5.includes(this.type);\n }\n\n /**\n * If the player is an embed - e.g. YouTube or Vimeo\n */\n get isEmbed() {\n return types.embed.includes(this.type);\n }\n\n /**\n * Play the media\n */\n play() {\n if ('play' in this.media) {\n this.media.play();\n }\n return this;\n }\n\n /**\n * Pause the media\n */\n pause() {\n if ('pause' in this.media) {\n this.media.pause();\n }\n return this;\n }\n\n get paused() {\n return this.media.paused;\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} toggle\n */\n togglePlay(toggle) {\n // True toggle if nothing passed\n if ((!utils.is.boolean(toggle) && this.media.paused) || toggle) {\n return this.play();\n }\n\n return this.pause();\n }\n\n /**\n * Stop playback\n */\n stop() {\n return this.restart().pause();\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n return this;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime.toFixed(4);\n\n // Logging\n this.console.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n get seeking() {\n return this.media.seeking;\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseInt(this.config.duration, 10);\n\n // True duration\n const realDuration = Number(this.media.duration);\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n ({ volume } = storage.get.call(this));\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume, reset muted state\n if (this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return this.media.volume;\n }\n\n // Increase volume\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Decrease volume\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Toggle mute\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = storage.get.call(this).muted;\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n get muted() {\n return this.media.muted;\n }\n\n // Playback speed\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ speed } = storage.get.call(this));\n } else {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.console.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n get speed() {\n return this.media.playbackRate;\n }\n\n // Set playback quality\n set quality(input) {\n let quality = null;\n\n if (utils.is.string(input)) {\n quality = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ quality } = storage.get.call(this));\n } else {\n quality = this.config.quality.selected;\n }\n\n if (!this.options.quality.includes(quality)) {\n this.console.warn(`Unsupported quality option (${quality})`);\n return;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n get quality() {\n return this.media.quality;\n }\n\n // Toggle loop\n // TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n get loop() {\n return this.media.loop;\n }\n\n // Media source\n set source(input) {\n source.change.call(this, input);\n }\n\n get source() {\n return this.media.currentSrc;\n }\n\n // Poster image\n set poster(input) {\n if (this.type !== 'video') {\n this.console.warn('Poster can only be set on HTML5 video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n }\n }\n\n get poster() {\n if (this.type !== 'video') {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n // Autoplay\n get autoplay() {\n return this.config.autoplay;\n }\n\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n // Toggle captions\n toggleCaptions(input) {\n // If there's no full support, or there's no caption toggle\n if (!this.supported.ui || !utils.is.htmlElement(this.elements.buttons.captions)) {\n return this;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input)\n ? input\n : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;\n\n // Nothing to change...\n if (this.captions.enabled === show) {\n return this;\n }\n\n // Set global\n this.captions.enabled = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.enabled);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.enabled);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.enabled ? 'captionsenabled' : 'captionsdisabled');\n\n // Allow chaining\n return this;\n }\n\n // Caption language\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // If nothing to change, bail\n if (this.captions.language === language) {\n return;\n }\n\n // Reset UI\n this.toggleCaptions(true);\n\n // Update config\n this.captions.language = language;\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n\n // Clear caption\n captions.set.call(this);\n\n // Re-run setup\n captions.setup.call(this);\n }\n\n get language() {\n return this.captions.language;\n }\n\n // Toggle fullscreen\n // Requires user input event\n toggleFullscreen(event) {\n // Check for native support\n if (fullscreen.enabled) {\n // If it's a fullscreen change event, update the UI\n if (utils.is.event(event) && event.type === fullscreen.eventType) {\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n } else {\n // Else it's a user request to enter or exit\n if (!this.fullscreen.active) {\n // Request full screen\n fullscreen.requestFullScreen(this.elements.container);\n } else {\n // Bail from fullscreen\n fullscreen.cancelFullScreen();\n }\n\n // Check if we're actually full screen (it could fail)\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n\n return this;\n }\n } else {\n // Otherwise, it's a simple toggle\n this.fullscreen.active = !this.fullscreen.active;\n\n // Add class hook\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.fullscreen.fallback,\n this.fullscreen.active\n );\n\n // Make sure we don't lose scroll position\n if (this.fullscreen.active) {\n scrollPosition = {\n x: window.pageXOffset || 0,\n y: window.pageYOffset || 0,\n };\n } else {\n window.scrollTo(scrollPosition.x, scrollPosition.y);\n }\n\n // Bind/unbind escape key\n document.body.style.overflow = this.fullscreen.active ? 'hidden' : '';\n }\n\n // Set button state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active);\n }\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.fullscreen.active ? 'enterfullscreen' : 'exitfullscreen');\n\n return this;\n }\n\n // Toggle picture-in-picture\n // TODO: update player with state, support, enabled\n // TODO: detect outside changes\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n // Trigger airplay\n // TODO: update player with state, support, enabled\n airplay() {\n // Bail if no support\n if (!support.airplay) {\n return this;\n }\n\n // Show dialog\n this.media.webkitShowPlaybackTargetPicker();\n\n return this;\n }\n\n // Show the player controls in fullscreen mode\n toggleControls(toggle) {\n const player = this;\n\n // We need controls of course...\n if (!utils.is.htmlElement(this.elements.controls)) {\n return player;\n }\n\n // Don't hide if config says not to, it's audio, or not ready or loading\n if (!this.supported.ui || !this.config.hideControls || this.type === 'audio') {\n return player;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n const loading = utils.hasClass(this.elements.container, this.config.classNames.loading);\n\n // Default to false if no boolean\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Whether to show controls\n show = ['mousemove', 'touchstart', 'mouseenter', 'focus'].includes(toggle.type);\n\n // Delay hiding on move events\n if (['mousemove', 'touchmove'].includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (toggle.type === 'focus') {\n delay = 3000;\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer every movement\n window.clearTimeout(this.timers.hover);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.media.paused || loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.media.paused || loading) {\n return player;\n }\n\n // Delay for hiding on touch\n if (support.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || !this.media.paused) {\n this.timers.hover = window.setTimeout(() => {\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, true);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n\n return this;\n }\n\n // Event listeners\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n return this;\n }\n\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n return this;\n }\n\n // Check for support\n supports(type) {\n return support.mime.call(this, type);\n }\n\n // Destroy an instance\n // Event listeners are removed when elements are removed\n // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n destroy(callback, soft = false) {\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n this.embedId = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove buttons\n if (this.elements.buttons && this.elements.buttons.play) {\n Array.from(this.elements.buttons.play).forEach(button => utils.removeElement(button));\n }\n\n // Remove others\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Replace the container with the original element provided\n const parent = this.elements.container.parentNode;\n\n if (utils.is.htmlElement(parent)) {\n parent.replaceChild(this.elements.original, this.elements.container);\n }\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Clear for GC\n this.elements = null;\n }\n };\n\n // Type specific stuff\n switch (this.type) {\n case 'youtube':\n // Clear timers\n window.clearInterval(this.timers.buffering);\n window.clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n this.embed.destroy();\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n this.embed.unload().then(done);\n\n // Vimeo does not always return\n window.setTimeout(done, 200);\n\n break;\n\n case 'video':\n case 'audio':\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n default:\n break;\n }\n }\n}\n\nexport default Plyr;\n"],"names":["get","store","window","localStorage","getItem","this","config","storage","key","utils","is","empty","JSON","parse","set","object","support","enabled","call","extend","setItem","stringify","defaults","navigator","language","split","types","input","getConstructor","Object","Number","isNaN","String","Boolean","Function","undefined","Array","isArray","NodeList","HTMLElement","Event","instanceOf","TextTrackCue","VTTCue","TextTrack","kind","string","array","nodeList","length","keys","constructor","document","documentMode","documentElement","style","test","userAgent","platform","url","callback","querySelectorAll","element","createElement","src","first","getElementsByTagName","function","addEventListener","event","parentNode","insertBefore","id","updateSprite","data","innerHTML","body","childNodes","hasId","container","setAttribute","cached","content","xhr","XMLHttpRequest","open","onload","responseText","send","prefix","Math","floor","random","self","top","e","elements","wrapper","targets","from","reverse","forEach","index","child","cloneNode","parent","sibling","nextSibling","appendChild","htmlElement","removeChild","target","type","attributes","text","setAttributes","textContent","lastChild","sel","existingAttributes","existing","selector","s","trim","className","replace","parts","value","charAt","class","toggle","contains","classList","prototype","Element","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","includes","querySelector","controls","getElement","selectors","buttons","getElements","play","pause","restart","rewind","forward","mute","pip","airplay","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","currentTime","seekTooltip","classNames","tooltip","error","console","warn","toggleNativeControls","focused","activeElement","tabbables","last","on","keyCode","_this","active","getFocusElement","shiftKey","focus","preventDefault","passive","capture","Node","toggleListener","events","options","boolean","passiveListeners","bubbles","properties","CustomEvent","assign","Plyr","dispatchEvent","state","getAttribute","current","max","toFixed","objects","destination","shift","source","property","match","RegExp","$2","number","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","ratio","getRatio","w","h","find","inline","api","ui","browser","getBrowser","playsInline","isIPhone","video","rangeInput","audio","removeItem","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","canPlayType","supported","defineProperty","range","transitionEnd","matchMedia","cancelFullScreen","some","pre","msExitFullscreen","msFullscreenEnabled","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","fullscreenElement","mozFullScreenElement","requestFullScreen","nativeSupport","fallback","inFrame","log","toggleClass","toggleState","trapFocus","setup","parseFloat","listeners","getKeyCode","which","handleKey","code","pressed","held","editable","stopPropagation","togglePlay","increaseVolume","decreaseVolume","muted","toggleFullscreen","toggleCaptions","keyboard","global","tabFocus","setTimeout","hideControls","toggleControls","eventType","timeUpdate","displayDuration","_this2","showPosterOnEnd","load","updateProgress","updateVolume","checkPlaying","checkLoading","clickToPlay","cursor","touch","paused","ended","disableContextMenu","updateSetting","speed","quality","concat","inputEvent","isIE","proxy","handlerKey","defaultHandler","customHandler","_this3","defaultPrevented","airPlay","toggleMenu","form","showTab","toLowerCase","loop","isWebkit","updateRangeFill","updateSeekTooltip","hover","inverted","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","uiSupported","isHTML5","removeAttribute","removeElement","inject","ready","updateTimeDisplay","label","i18n","title","playLarge","isEmbed","iframe","frameTitle","playing","stopped","setRange","loading","timers","nodeValue","getPercentage","buffered","end","setProgress","time","secs","parseInt","mins","hours","displayHours","slice","seeking","styleSheet","sheet","percentage","styles","rules","findIndex","rule","selectorText","deleteRule","insertRule","iconUrl","indexOf","svg4everybody","getIconUrl","iconPath","absolute","iconPrefix","icon","createElementNS","use","path","setAttributeNS","hidden","badge","menu","buttonType","attr","button","iconDefault","iconToggled","labelKey","control","getAttributesFromSelector","createIcon","createLabel","suffix","played","tooltips","percent","clientRect","getBoundingClientRect","visible","pageX","left","hasClass","setting","tab","tabs","pane","panes","list","filter","toggleTab","emptyElement","getBadge","createBadge","item","radio","createTextNode","getLabel","getLanguage","default","checked","option","textTracks","tracks","none","currentTrack","disabled","track","toUpperCase","unshift","_this4","insertAdjacentHTML","show","isMenuItem","isButton","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","transitions","reducedMotion","size","getTabSize","restore","propertyName","off","createButton","createRange","createProgress","createTime","inner","home","_this5","back","setSpeedMenu","loadSprite","seekTime","create","findElements","labels","_this6","setCaptionsMenu","insertAfter","setCurrentTrack","setCue","mode","activeCues","embed","enableTextTrack","cue","getCueAsHTML","caption","youtube","videoId","parseYouTubeId","embedId","containers","setAspectRatio","generateId","YT","loadScript","urls","onYouTubeReadyCallbacks","push","onYouTubeIframeAPIReady","paddingBottom","player","Player","autoplay","location","hostname","href","instance","getPlaybackQuality","playbackRate","getPlaybackRate","playVideo","pauseVideo","stop","stopVideo","getDuration","getCurrentTime","seekTo","setPlaybackRate","setPlaybackQuality","setVolume","getVideoUrl","getAvailablePlaybackRates","getVideoData","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","build","setQualityMenu","getAvailableQualityLevels","vimeo","Vimeo","padding","offset","transform","params","buildUrlParameters","parseVimeoId","setCurrentTime","selected","setLoop","currentSrc","then","all","getVideoWidth","getVideoHeight","getAspectRatio","dimensions","getVideoTitle","getTextTracks","cues","stripHTML","seconds","isIos","isTouch","wrap","setTitle","blankVideo","insertElement","attribute","sources","cancelRequests","destroy","firstSource","check","crossorigin","poster","addStyleHook","insertElements","scrollPosition","jQuery","debug","plyr","original","tagName","hasAttribute","step","isFullScreen","pageXOffset","pageYOffset","scrollTo","x","y","overflow","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","clearTimeout","mime","soft","done","replaceChild","unload","html5","targetTime","fauxDuration","realDuration","change","states","webkitPresentationMode"],"mappings":"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"} \ No newline at end of file diff --git a/readme.md b/readme.md index 58a3d389..c3fa09ac 100644 --- a/readme.md +++ b/readme.md @@ -331,7 +331,7 @@ Property | Getter | Setter | Description 1. YouTube only. HTML5 will follow. 2. HTML5 only -#### .source setter +#### The `.source` setter This allows changing the player source and type on the fly. @@ -421,207 +421,87 @@ player.source = { }; ``` -Note: `src` can be the video ID or URL +*Note:* `src` property for YouTube and Vimeo can either be the video ID or the whole URL. -More details on the object parameters +Property | Type | Description +-------- | ---- | ----------- +`type` | String | Either `video` or `audio`. *Note:* YouTube and Vimeo are currently not supported as audio sources. +`title` | String | *Optional.* Title of the new media. Used for the `aria-label` attribute on the play button, and outer container. YouTube and Vimeo can be populated automatically. +`sources` | Array | This is an array of sources. For HTML5 media, the properties of this object are mapped directly to HTML attributes so more can be added to the object if required. +`poster`¹ | String | The URL for the poster image (HTML5 video only). +`tracks`¹ | String | An array of track objects. Each element in the array is mapped directly to a track element and any keys mapped directly to HTML attributes so as in the example above, it will render as `` and similar for the French version. Booleans are converted to HTML5 value-less attributes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
typeStringOptions are video, audio, youtube and vimeo
titleStringTitle of the new media. Used for the `aria-label` attribute on the play button, and outer container.
sourcesArrayThis is an array of sources. type is optional for YouTube and Vimeo when specifying an array. For YouTube and Vimeo media, the video ID or URL must be passed as the source as shown above. The keys of this object are mapped directly to HTML attributes so more can be added to the object if required.
posterStringURL for the poster image (video only).
tracksArrayAn array of track objects. Each element in the array is mapped directly to a track element and any keys mapped directly to HTML attributes so as in the example above, it will render as ``. Booleans are converted to HTML5 value-less attributes.
+1. HTML5 only ## Events + You can listen for events on the target element you setup Plyr on (see example under the table). Some events only apply to HTML5 audio and video. Using your reference to the instance, you can use the `on()` API method or `addEventListener()`. Access to the API can be obtained this way through the `event.detail.plyr` property. Here's an example: ```javascript -instance.on('ready', function(event) { - var instance = event.detail.plyr; +player.on('ready', event => { + const instance = event.detail.plyr; }); ``` -These events also bubble up the DOM. The event target will be the container element. +### Standard Media Events - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event nameHTML5 onlyDescription
readyTriggered when the instance is ready for API calls.
canplay✔Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the HAVE_ENOUGH_DATA readyState.
canplaythroughSent when the ready state changes to CAN_PLAY_THROUGH, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. Note: Manually setting the currentTime will eventually fire a canplaythrough event in firefox. Other browsers might not fire this event.
emptied✔The media has become empty; for example, this event is sent if the media has already been loaded (or partially loaded), and the load() method is called to reload it.
endedSent when playback completes. Note: with Vimeo this does not occur if `loop` is enabled.
error✔Sent when an error occurs.  The element's error attribute contains more information.
loadeddata✔The first frame of the media has finished loading.
loadedmetadata✔The media's metadata has finished loading; all attributes now contain as much useful information as they're going to.
loadstart✔Sent when loading of the media begins.
pauseSent when playback is paused.
playSent when playback of the media starts after having been paused; that is, when playback is resumed after a prior pause event.
playingSent when the media begins to play (either for the first time, after having been paused, or after ending and then restarting).
progressSent periodically to inform interested parties of progress downloading the media. Information about the current amount of the media that has been downloaded is available in the media element's buffered attribute.
seekedSent when a seek operation completes.
seekingSent when a seek operation begins.
stalled✔Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming.
timeupdateThe time indicated by the element's currentTime attribute has changed.
volumechangeSent when the audio volume changes (both when the volume is set and when the muted attribute is changed).
waiting✔Sent when the requested operation (such as playback) is delayed pending the completion of another operation (such as a seek).
enterfullscreenUser enters fullscreen (either the proper fullscreen or full-window fallback for older browsers)
exitfullscreenUser exits fullscreen
captionsenabledCaptions toggled on
captionsdisabledCaptions toggled off
destroyedWhen an instance is destroyed. The original element that replaced the container will be returned to your handler as the event target.
+Event Type | Description +---------- | ----------- +`progress` | Sent periodically to inform interested parties of progress downloading the media. Information about the current amount of the media that has been downloaded is available in the media element's `buffered` attribute. +`playing` | Sent when the media begins to play (either for the first time, after having been paused, or after ending and then restarting). +`play` | Sent when playback of the media starts after having been paused; that is, when playback is resumed after a prior `pause` event. +`pause` | Sent when playback is paused. +`timeupdate` | The time indicated by the element's `currentTime` attribute has changed. +`volumechange` | Sent when the audio volume changes (both when the volume is set and when the `muted` state is changed). +`seeking` | Sent when a seek operation begins. +`seeked` | Sent when a seek operation completes. +`ratechange` | Sent when the playback speed changes. +`ended` | Sent when playback completes. +`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. +`captionsenabled` | Sent when captions are enabled. +`captionsdisabled` | Sent when captions are disabled. +`languagechange` | Sent when the caption language is changed. +`controlshidden` | Sent when the controls are hidden. +`controlsshown` | Sent when the controls are shown. +`ready` | Triggered when the instance is ready for API calls. -Details borrowed from: [https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events) +#### HTML5 only +Event Type | Description +---------- | ----------- +`loadstart` | Sent when loading of the media begins. +`loadeddata` | The first frame of the media has finished loading. +`loadedmetadata` | The media's metadata has finished loading; all attributes now contain as much useful information as they're going to. +`canplay` | Sent when enough data is available that the media can be played, at least for a couple of frames. This corresponds to the `HAVE_ENOUGH_DATA` `readyState`. +`canplaythrough` | Sent when the ready state changes to `CAN_PLAY_THROUGH`, indicating that the entire media can be played without interruption, assuming the download rate remains at least at the current level. *Note:* Manually setting the `currentTime` will eventually fire a `canplaythrough` event in firefox. Other browsers might not fire this event. +`stalled` | Sent when the user agent is trying to fetch media data, but data is unexpectedly not forthcoming. +`waiting` | Sent when the requested operation (such as playback) is delayed pending the completion of another operation (such as a seek). +`emptied` | he media has become empty; for example, this event is sent if the media has already been loaded (or partially loaded), and the `load()` method is called to reload it. +`cuechange` | Sent when a `TextTrack` has changed the currently displaying cues. +`error` | Sent when an error occurs. The element's `error` attribute contains more information. + +#### YouTube only +Event Type | Description +---------- | ----------- +`statechange` | The state of the player has changed. The code can be accessed via `event.detail.code`. Possible values are `-1`: Unstarted, `0`: Ended, `1`: Playing, `2`: Paused, `3`: Buffering, `5`: Video cued. See the [YouTube Docs](https://developers.google.com/youtube/iframe_api_reference#onStateChange) for more information. +`qualitychange` | The quality of playback has changed. +`qualityrequested` | A change to playback quality has been requested. *Note:* A change to quality can only be *requested* via the API. There is no guarantee the quality will change to the level requested. You should listen to the `qualitychange` event for true changes. + +*Note:* These events also bubble up the DOM. The event target will be the container element. + +Some event details borrowed from [MDN](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events). ## Embeds -YouTube and Vimeo are currently supported and function much like a HTML5 video. Check the relevant documentation sections for any differences. -Plyr references a custom version of the Vimeo Froogaloop API as Vimeo have neglected to maintain the library and there were bugs with their version. You don't need to worry about including your own versions of the Vimeo or YouTube JavaScript APIs. +YouTube and Vimeo are currently supported and function much like a HTML5 video. Similar events and API methods are available for all types. However if you wish to access the API's directly. You can do so via the `embed` property of your player object - e.g. `player.embed`. You can then use the relevant methods from the third party APIs. More info on the respective API's here: -The embed third party API's can be accessed through the `getEmbed()` API method. +- [YouTube iframe API Reference](https://developers.google.com/youtube/iframe_api_reference) +- [Vimeo player.js Reference](https://github.com/vimeo/player.js) -More info on the respective API's here: - -- [YouTube API Reference](https://developers.google.com/youtube/js_api_reference) -- [Vimeo API Reference](https://developer.vimeo.com/player/js-api#reference) - -*Please note*: not all API methods may work 100%. Your mileage may vary. It's better to use the universal plyr API where possible. +*Note*: Not all API methods may work 100%. Your mileage may vary. It's better to use the Plyr API where possible. ## Shortcuts + By default, a player will bind the following keyboard shortcuts when it has focus. If you have the `global` option to `true` and there's only one player in the document then the shortcuts will work when any element has focus, apart from an element that requires input. diff --git a/src/js/defaults.js b/src/js/defaults.js index cf6bc344..14c7204d 100644 --- a/src/js/defaults.js +++ b/src/js/defaults.js @@ -203,7 +203,7 @@ const defaults = { 'exitfullscreen', 'captionsenabled', 'captionsdisabled', - 'captionchange', + 'languagechange', 'controlshidden', 'controlsshown', 'ready', diff --git a/src/js/listeners.js b/src/js/listeners.js index 71f381f7..40014dab 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -314,7 +314,7 @@ const listeners = { }); // Caption language change - utils.on(this.media, 'captionchange', () => { + utils.on(this.media, 'languagechange', () => { // Save to storage storage.set.call(this, { language: this.language }); }); diff --git a/src/js/plyr.js b/src/js/plyr.js index aed3da44..df751efe 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -680,7 +680,7 @@ class Plyr { this.captions.language = language; // Trigger an event - utils.dispatchEvent.call(this, this.media, 'captionchange'); + utils.dispatchEvent.call(this, this.media, 'languagechange'); // Clear caption captions.set.call(this); From 3ade86537d09c145f9ba3ceeafba4f8c8063c3f7 Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Sun, 12 Nov 2017 08:14:14 +0000 Subject: [PATCH 2/7] Docs, keyboard shortcut fixes --- dist/plyr.js | 2 +- dist/plyr.js.map | 2 +- readme.md | 179 ++++++++++++++------------------------------ src/js/listeners.js | 8 +- 4 files changed, 65 insertions(+), 126 deletions(-) diff --git a/dist/plyr.js b/dist/plyr.js index 62a63c0d..037273be 100644 --- a/dist/plyr.js +++ b/dist/plyr.js @@ -1,3 +1,3 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";function e(){var e=window.localStorage.getItem(this.config.storage.key);return s.is.empty(e)?{}:JSON.parse(e)}function t(t){if(a.storage&&this.config.storage.enabled&&s.is.object(t)){var i=e.call(this);s.extend(i,t),window.localStorage.setItem(this.config.storage.key,JSON.stringify(i))}}var i={enabled:!0,title:"",debug:!1,autoplay:!1,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,showPosterOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/2.0.10/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:"default",options:["hd2160","hd1440","hd1080","hd720","large","medium","small","tiny","default"]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:window.navigator.language.split("-")[0]},fullscreen:{enabled:!0,fallback:!0},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed","loop"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",seek:"Seek",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",toggleMute:"Toggle Mute",toggleCaptions:"Toggle Captions",toggleFullscreen:"Toggle Fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",speed:"Speed",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",none:"None",disabled:"Disabled"},urls:{vimeo:{api:"https://player.vimeo.com/api/player.js"},youtube:{api:"https://www.youtube.com/iframe_api"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,forward:null,mute:null,volume:null,captions:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","qualityrequested"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',forward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress--buffer",played:".plyr__progress--played",loop:".plyr__progress--loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{video:"plyr__video-wrapper",embed:"plyr__video-embed",control:"plyr__control",type:"plyr--{0}",stopped:"plyr--stopped",playing:"plyr--playing",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",menu:{value:"plyr__menu__value",badge:"plyr__badge"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus"}},n={embed:["youtube","vimeo"],html5:["video","audio"]},s={is:{object:function(e){return this.getConstructor(e)===Object},number:function(e){return this.getConstructor(e)===Number&&!Number.isNaN(e)},string:function(e){return this.getConstructor(e)===String},boolean:function(e){return this.getConstructor(e)===Boolean},function:function(e){return this.getConstructor(e)===Function},array:function(e){return!this.undefined(e)&&Array.isArray(e)},nodeList:function(e){return!this.undefined(e)&&e instanceof NodeList},htmlElement:function(e){return!this.undefined(e)&&e instanceof HTMLElement},event:function(e){return!this.undefined(e)&&e instanceof Event},cue:function(e){return this.instanceOf(e,window.TextTrackCue)||this.instanceOf(e,window.VTTCue)},track:function(e){return!this.undefined(e)&&(this.instanceOf(e,window.TextTrack)||"string"==typeof e.kind)},undefined:function(e){return null!==e&&void 0===e},empty:function(e){return null===e||void 0===e||(this.string(e)||this.array(e)||this.nodeList(e))&&0===e.length||this.object(e)&&0===Object.keys(e).length},getConstructor:function(e){return null===e||void 0===e?null:e.constructor},instanceOf:function(e,t){return Boolean(e&&t&&e instanceof t)}},getBrowser:function(){return{isIE:!!document.documentMode,isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)}},loadScript:function(e,t){if(!document.querySelectorAll('script[src="'+e+'"]').length){var i=document.createElement("script");i.src=e;var n=document.getElementsByTagName("script")[0];s.is.function(t)&&i.addEventListener("load",function(e){return t.call(null,e)},!1),n.parentNode.insertBefore(i,n)}},loadSprite:function(e,t){function i(e){this.innerHTML=e,document.body.insertBefore(this,document.body.childNodes[0])}if("string"==typeof e){var n="string"==typeof t;if(!n||!document.querySelectorAll("#"+t).length){var s=document.createElement("div");if(s.setAttribute("hidden",""),n&&s.setAttribute("id",t),a.storage){var l=window.localStorage.getItem("cache-"+t);if(null!==l){var o=JSON.parse(l);i.call(s,o.content)}}var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.open("GET",e,!0),r.onload=function(){a.storage&&window.localStorage.setItem("cache-"+t,JSON.stringify({content:r.responseText})),i.call(s,r.responseText)},r.send()}}},generateId:function(e){return e+"-"+Math.floor(1e4*Math.random())},inFrame:function(){try{return window.self!==window.top}catch(e){return!0}},wrap:function(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,s=e.parentNode,a=e.nextSibling;n.appendChild(e),a?s.insertBefore(n,a):s.appendChild(n)})},removeElement:function(e){return s.is.htmlElement(e)&&s.is.htmlElement(e.parentNode)?(e.parentNode.removeChild(e),e):null},insertAfter:function(e,t){t.parentNode.insertBefore(e,t.nextSibling)},createElement:function(e,t,i){var n=document.createElement(e);return s.is.object(t)&&s.setAttributes(n,t),s.is.string(i)&&(n.textContent=i),n},insertElement:function(e,t,i,n){t.appendChild(s.createElement(e,i,n))},emptyElement:function(e){for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1},setAttributes:function(e,t){Object.keys(t).forEach(function(i){e.setAttribute(i,t[i])})},getAttributesFromSelector:function(e,t){if(!s.is.string(e)||s.is.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),a=t.replace(".",""),l=t.replace(/[[\]]/g,"").split("="),o=l[0],r=l.length>1?l[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":s.is.object(n)&&s.is.string(n.class)&&(n.class+=" "+a),i.class=a;break;case"#":i.id=t.replace("#","");break;case"[":i[o]=r}}),i},toggleClass:function(e,t,i){if(s.is.htmlElement(e)){var n=e.classList.contains(t);return e.classList[i?"add":"remove"](t),i&&!n||!i&&n}return null},hasClass:function(e,t){return s.is.htmlElement(e)&&e.classList.contains(t)},matches:function(e,t){var i={Element:Element},n=i.matches||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||function(){return Array.from(document.querySelectorAll(t)).includes(this)};return n.call(e,t)},getElements:function(e){return this.elements.container.querySelectorAll(e)},getElement:function(e){return this.elements.container.querySelector(e)},findElements:function(){try{return this.elements.controls=s.getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:s.getElements.call(this,this.config.selectors.buttons.play),pause:s.getElement.call(this,this.config.selectors.buttons.pause),restart:s.getElement.call(this,this.config.selectors.buttons.restart),rewind:s.getElement.call(this,this.config.selectors.buttons.rewind),forward:s.getElement.call(this,this.config.selectors.buttons.forward),mute:s.getElement.call(this,this.config.selectors.buttons.mute),pip:s.getElement.call(this,this.config.selectors.buttons.pip),airplay:s.getElement.call(this,this.config.selectors.buttons.airplay),settings:s.getElement.call(this,this.config.selectors.buttons.settings),captions:s.getElement.call(this,this.config.selectors.buttons.captions),fullscreen:s.getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=s.getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:s.getElement.call(this,this.config.selectors.inputs.seek),volume:s.getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:s.getElement.call(this,this.config.selectors.display.buffer),duration:s.getElement.call(this,this.config.selectors.display.duration),currentTime:s.getElement.call(this,this.config.selectors.display.currentTime)},s.is.htmlElement(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector("."+this.config.classNames.tooltip)),!0}catch(e){return this.console.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},getFocusElement:function(){var e=document.activeElement;return e=e&&e!==document.body?document.querySelector(":focus"):null},trapFocus:function(){var e=this,t=s.getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=t[0],n=t[t.length-1];s.on(this.elements.container,"keydown",function(t){if("Tab"===t.key&&9===t.keyCode&&e.fullscreen.active){var a=s.getFocusElement();a!==n||t.shiftKey?a===i&&t.shiftKey&&(n.focus(),t.preventDefault()):(i.focus(),t.preventDefault())}},!1)},toggleListener:function(e,t,i,n,l,o){if(null!==e&&!s.is.undefined(e))if(s.is.nodeList(e))Array.from(e).forEach(function(e){e instanceof Node&&s.toggleListener.call(null,e,t,i,n,l,o)});else{var r=t.split(" "),c=!!s.is.boolean(o)&&o;a.passiveListeners&&(c={passive:!s.is.boolean(l)||l,capture:!!s.is.boolean(o)&&o}),r.forEach(function(t){e[n?"addEventListener":"removeEventListener"](t,i,c)})}},on:function(e,t,i,n,a){s.toggleListener(e,t,i,!0,n,a)},off:function(e,t,i,n,a){s.toggleListener(e,t,i,!1,n,a)},dispatchEvent:function(e,t,i,n){if(e&&t){var a=new CustomEvent(t,{bubbles:!!s.is.boolean(i)&&i,detail:Object.assign({},n,{plyr:this instanceof Plyr?this:null})});e.dispatchEvent(a)}},toggleState:function(e,t){if(s.is.htmlElement(e)){var i=s.is.boolean(t)?t:!e.getAttribute("aria-pressed");e.setAttribute("aria-pressed",i)}},getPercentage:function(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)},extend:function(){for(var e=arguments.length,t=Array(e),i=0;i0)&&(i?(e.decreaseVolume(.02),n=-1):(e.increaseVolume(.02),n=1)),(t.deltaY>0||t.deltaX<0)&&(i?(e.increaseVolume(.02),n=1):(e.decreaseVolume(.02),n=-1)),(1===n&&e.media.volume<1||-1===n&&e.media.volume>0)&&t.preventDefault()})},!1)}},d={addStyleHook:function(){s.toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),s.toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(e){e&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){if(u.media.call(this),!this.supported.ui)return this.console.warn("Basic support only for "+this.type),s.removeElement.call(this,"controls"),s.removeElement.call(this,"buttons.play"),void d.toggleNativeControls.call(this,!0);s.is.htmlElement(this.elements.controls)||(h.inject.call(this),u.controls.call(this)),s.is.htmlElement(this.elements.controls)&&(d.toggleNativeControls.call(this),o.setup.call(this),m.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.options.quality=[],d.timeUpdate.call(this),d.checkPlaying.call(this),this.ready=!0,s.dispatchEvent.call(this,this.media,"ready"))},displayDuration:function(){this.supported.ui&&(!this.elements.display.duration&&this.config.displayDuration&&this.paused&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.currentTime),this.elements.display.duration&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.duration),h.updateSeekTooltip.call(this))},setTitle:function(){var e=this.config.i18n.play;if(s.is.string(this.config.title)&&!s.is.empty(this.config.title)&&(e+=", "+this.config.title,this.elements.container.setAttribute("aria-label",this.config.title)),this.supported.ui&&(s.is.htmlElement(this.elements.buttons.play)&&this.elements.buttons.play.setAttribute("aria-label",e),s.is.htmlElement(this.elements.buttons.playLarge)&&this.elements.buttons.playLarge.setAttribute("aria-label",e)),this.isEmbed){var t=s.getElement.call(this,"iframe");if(!s.is.htmlElement(t))return;var i=s.is.empty(this.config.title)?"video":this.config.title;t.setAttribute("title",this.config.i18n.frameTitle.replace("{title}",i))}},checkPlaying:function(){s.toggleClass(this.elements.container,this.config.classNames.playing,!this.paused),s.toggleClass(this.elements.container,this.config.classNames.stopped,this.paused),this.toggleControls(this.paused)},updateVolume:function(){this.supported.ui&&(s.is.htmlElement(this.elements.inputs.volume)&&d.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),s.is.htmlElement(this.elements.buttons.mute)&&s.toggleState(this.elements.buttons.mute,this.muted||0===this.volume))},checkLoading:function(e){var t=this;this.loading="waiting"===e.type,clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){s.toggleClass(t.elements.container,t.config.classNames.loading,t.loading),t.toggleControls(t.loading)},this.loading?250:0)},setRange:function(e,t){s.is.htmlElement(e)&&(e.value=t,h.updateRangeFill.call(this,e))},setProgress:function(e,t){var i=s.is.undefined(t)?0:t,n=s.is.undefined(e)?this.elements.display.buffer:e;if(s.is.htmlElement(n)){n.value=i;var a=n.getElementsByTagName("span")[0];s.is.htmlElement(a)&&(a.childNodes[0].nodeValue=i)}},updateProgress:function(e){var t=this;if(this.supported.ui){var i=0;if(e)switch(e.type){case"timeupdate":case"seeking":i=s.getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&d.setRange.call(this,this.elements.inputs.seek,i);break;case"playing":case"progress":i=function(){var e=t.media.buffered;return e&&e.length?s.getPercentage(e.end(0),t.duration):s.is.number(e)?100*e:0}(),d.setProgress.call(this,this.elements.display.buffer,i)}}},updateTimeDisplay:function(e,t){if(!s.is.htmlElement(t))return null;var i=Number.isNaN(e)?0:e,n=parseInt(i%60,10),a=parseInt(i/60%60,10),l=parseInt(i/60/60%60,10),o=parseInt(this.duration/60/60%60,10)>0;n=("0"+n).slice(-2),a=("0"+a).slice(-2);var r=(o?l+":":"")+a+":"+n;return t.textContent=r,r},timeUpdate:function(e){d.updateTimeDisplay.call(this,this.currentTime,this.elements.display.currentTime),e&&"timeupdate"===e.type&&this.media.seeking||d.updateProgress.call(this,e)}},p=s.getBrowser(),h={updateRangeFill:function(e){if(p.isWebkit){var t=s.is.event(e)?e.target:e;if(s.is.htmlElement(t)&&"range"===t.getAttribute("type")){s.is.htmlElement(this.elements.styleSheet)||(this.elements.styleSheet=s.createElement("style"),this.elements.container.appendChild(this.elements.styleSheet));var i=this.elements.styleSheet.sheet,n=t.value/t.max*100,a="#"+t.id+"::-webkit-slider-runnable-track",l="{ background-image: linear-gradient(to right, currentColor "+n+"%, transparent "+n+"%) }",o=Array.from(i.rules).findIndex(function(e){return e.selectorText===a});-1!==o&&i.deleteRule(o),i.insertRule([a,l].join(" "))}}},getIconUrl:function(){return{url:this.config.iconUrl,absolute:0===this.config.iconUrl.indexOf("http")||p.isIE&&!window.svg4everybody}},createIcon:function(e,t){var i=h.getIconUrl.call(this),n=(i.absolute?"":i.url)+"#"+this.config.iconPrefix,a=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttributes(a,s.extend(t,{role:"presentation"}));var l=document.createElementNS("http://www.w3.org/2000/svg","use"),o=n+"-"+e;return"href"in l?l.setAttribute("href",o):l.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),a.appendChild(l),a},createLabel:function(e){var t=this.config.i18n[e];switch(e){case"pip":t="PIP";break;case"airplay":t="AirPlay"}return s.createElement("span",{class:this.config.classNames.hidden},t)},createBadge:function(e){var t=s.createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(s.createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=s.createElement("button"),n=Object.assign({},t),a=e,l=void 0,o=void 0,r=void 0;switch("type"in n||(n.type="button"),"class"in n?-1===n.class.indexOf(this.config.classNames.control)&&(n.class+=" "+this.config.classNames.control):n.class=this.config.classNames.control,a){case"mute":r="toggleMute",l="volume",o="muted";break;case"captions":r="toggleCaptions",l="captions-off",o="captions-on";break;case"fullscreen":r="toggleFullscreen",l="enter-fullscreen",o="exit-fullscreen";break;case"play-large":n.class="plyr__play-large",a="play",r="play",l="play";break;default:r=a,l=a}return s.extend(n,s.getAttributesFromSelector(this.config.selectors.buttons[a],n)),s.is.string(o)?(i.appendChild(h.createIcon.call(this,o,{class:"icon--pressed"})),i.appendChild(h.createIcon.call(this,l,{class:"icon--not-pressed"}))):i.appendChild(h.createIcon.call(this,l)),i.appendChild(h.createLabel.call(this,r)),s.setAttributes(i,n),this.elements.buttons[a]=i,i},createRange:function(e,t){var i=s.createElement("label",{for:t.id,class:this.config.classNames.hidden},this.config.i18n[e]),n=s.createElement("input",s.extend(s.getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off"},t));return this.elements.inputs[e]=n,h.updateRangeFill.call(this,n),{label:i,input:n}},createProgress:function(e,t){var i=s.createElement("progress",s.extend(s.getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0},t));if("volume"!==e){i.appendChild(s.createElement("span",null,"0"));var n="";switch(e){case"played":n=this.config.i18n.played;break;case"buffer":n=this.config.i18n.buffered}i.textContent="% "+n.toLowerCase()}return this.elements.display[e]=i,i},createTime:function(e){var t=s.createElement("span",{class:"plyr__time"});return t.appendChild(s.createElement("span",{class:this.config.classNames.hidden},this.config.i18n[e])),t.appendChild(s.createElement("span",s.getAttributesFromSelector(this.config.selectors.display[e]),"00:00")),this.elements.display[e]=t,t},updateSeekTooltip:function(e){if(this.config.tooltips.seek&&s.is.htmlElement(this.elements.inputs.seek)&&s.is.htmlElement(this.elements.display.seekTooltip)&&0!==this.duration){var t=0,i=this.elements.inputs.seek.getBoundingClientRect(),n=this.config.classNames.tooltip+"--visible";if(s.is.event(e))t=100/i.width*(e.pageX-i.left);else{if(!s.hasClass(this.elements.display.seekTooltip,n))return;t=this.elements.display.seekTooltip.style.left.replace("%","")}t<0?t=0:t>100&&(t=100),d.updateTimeDisplay.call(this,this.duration/100*t,this.elements.display.seekTooltip),this.elements.display.seekTooltip.style.left=t+"%",s.is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&s.toggleClass(this.elements.display.seekTooltip,n,"mouseenter"===e.type)}},toggleTab:function(e,t){var i=this.elements.settings.tabs[e],n=this.elements.settings.panes[e];s.is.htmlElement(i)&&(t?i.removeAttribute("hidden"):i.setAttribute("hidden","")),s.is.htmlElement(n)&&(t?n.removeAttribute("hidden"):n.setAttribute("hidden",""))},setQualityMenu:function(e){var t=this,i=this.elements.settings.panes.quality.querySelector("ul");s.is.array(e)?this.options.quality=e.filter(function(e){return t.config.quality.options.includes(e)}):this.options.quality=this.config.quality.options;var n=!s.is.empty(this.options.quality)&&"youtube"===this.type;if(h.toggleTab.call(this,"quality",n),n){s.emptyElement(i);var a=function(e){var i="";switch(e){case"hd2160":i="4K";break;case"hd1440":i="WQHD";break;case"hd1080":case"hd720":i="HD"}return i.length?h.createBadge.call(t,i):null};this.options.quality.forEach(function(e){var n=s.createElement("li"),l=s.createElement("label",{class:t.config.classNames.control}),o=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.quality),{type:"radio",name:"plyr-quality",value:e}));l.appendChild(o),l.appendChild(document.createTextNode(h.getLabel.call(t,"quality",e)));var r=a(e);s.is.htmlElement(r)&&l.appendChild(r),n.appendChild(l),i.appendChild(n)}),h.updateSetting.call(this,"quality",i)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?"Normal":t+"×";case"quality":switch(t){case"hd2160":return"2160P";case"hd1440":return"1440P";case"hd1080":return"1080P";case"hd720":return"720P";case"large":return"480P";case"medium":return"360P";case"small":return"240P";case"tiny":return"Tiny";case"default":return"Auto";default:return t}case"captions":return h.getLanguage.call(this);default:return null}},updateSetting:function(e,t){var i=this.elements.settings.panes[e],n=null,a=t;switch(e){case"captions":n=this.captions.language,this.captions.enabled||(n="");break;default:if(n=this[e],s.is.empty(n)&&(n=this.config[e].default),!this.options[e].includes(n))return void this.console.warn("Unsupported value of '"+n+"' for "+e);if(!this.config[e].options.includes(n))return void this.console.warn("Disabled value of '"+n+"' for "+e)}s.is.htmlElement(a)||(a=i&&i.querySelector("ul"));var l=a&&a.querySelector('input[value="'+n+'"]');s.is.htmlElement(l)&&(l.checked=!0,this.elements.settings.tabs[e].querySelector("."+this.config.classNames.menu.value).innerHTML=h.getLabel.call(this,e,n))},setLoopMenu:function(){var e=this,t=this.elements.settings.panes.loop.querySelector("ul");this.elements.settings.tabs.loop.removeAttribute("hidden"),this.elements.settings.panes.loop.removeAttribute("hidden");var i=!s.is.empty(this.loop.options);h.toggleTab.call(this,"loop",i),s.emptyElement(t),["start","end","all","reset"].forEach(function(i){var n=s.createElement("li"),a=s.createElement("button",s.extend(s.getAttributesFromSelector(e.config.selectors.buttons.loop),{type:"button",class:e.config.classNames.control,"data-plyr-loop-action":i}),e.config.i18n[i]);if(["start","end"].includes(i)){var l=h.createBadge.call(e,"00:00");a.appendChild(l)}n.appendChild(a),t.appendChild(n)})},getLanguage:function(){return this.supported.ui?!a.textTracks||s.is.empty(this.captions.tracks)?this.config.i18n.none:this.captions.enabled?this.captions.currentTrack.label:this.config.i18n.disabled:null},setCaptionsMenu:function(){var e=this,t=this.elements.settings.panes.captions.querySelector("ul"),i=!s.is.empty(this.captions.tracks);if(h.toggleTab.call(this,"captions",i),s.emptyElement(t),!s.is.empty(this.captions.tracks)){var n=Array.from(this.captions.tracks).map(function(e){return{language:e.language,badge:!0,label:s.is.empty(e.label)?e.language.toUpperCase():e.label}});n.unshift({language:"",label:this.config.i18n.none}),n.forEach(function(i){var n=s.createElement("li"),a=s.createElement("label",{class:e.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(e.config.selectors.inputs.language),{type:"radio",name:"plyr-language",value:i.language}));i.language.toLowerCase()===e.captions.language.toLowerCase()&&(l.checked=!0),a.appendChild(l),a.appendChild(document.createTextNode(i.label||i.language)),i.badge&&a.appendChild(h.createBadge.call(e,i.language.toUpperCase())),n.appendChild(a),t.appendChild(n)}),h.updateSetting.call(this,"captions",t)}},setSpeedMenu:function(e){var t=this;s.is.array(e)?this.options.speed=e.filter(function(e){return t.config.speed.options.includes(e)}):this.options.speed=this.config.speed.options;var i=!s.is.empty(this.options.speed);if(h.toggleTab.call(this,"speed",i),i){var n=this.elements.settings.panes.speed.querySelector("ul");this.elements.settings.tabs.speed.removeAttribute("hidden"),this.elements.settings.panes.speed.removeAttribute("hidden"),s.emptyElement(n),this.options.speed.forEach(function(e){var i=s.createElement("li"),a=s.createElement("label",{class:t.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.speed),{type:"radio",name:"plyr-speed",value:e}));a.appendChild(l),a.insertAdjacentHTML("beforeend",h.getLabel.call(t,"speed",e)),i.appendChild(a),n.appendChild(i)}),h.updateSetting.call(this,"speed",n)}},toggleMenu:function(e){var t=this.elements.settings.form,i=this.elements.buttons.settings,n=s.is.boolean(e)?e:t&&"true"===t.getAttribute("aria-hidden");if(s.is.event(e)){var a=t&&t.contains(e.target),l=e.target===this.elements.buttons.settings;if(a||!a&&!l&&n)return;l&&e.stopPropagation()}i&&i.setAttribute("aria-expanded",n),t&&(t.setAttribute("aria-hidden",!n),n?t.removeAttribute("tabindex"):t.setAttribute("tabindex",-1))},getTabSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.setAttribute("aria-hidden",!1),Array.from(t.querySelectorAll("input[name]")).forEach(function(e){var t=e.getAttribute("name");e.setAttribute("name",t+"-clone")}),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return s.removeElement(t),{width:i,height:n}},showTab:function(e){var t=this.elements.settings.menu,i=e.target,n="false"===i.getAttribute("aria-expanded"),l=document.getElementById(i.getAttribute("aria-controls"));if(s.is.htmlElement(l)&&"tabpanel"===l.getAttribute("role")){var o=t.querySelector('[role="tabpanel"][aria-hidden="false"]'),r=o.parentNode;if(Array.from(t.querySelectorAll('[aria-controls="'+o.getAttribute("id")+'"]')).forEach(function(e){e.setAttribute("aria-expanded",!1)}),a.transitions&&!a.reducedMotion){r.style.width=o.scrollWidth+"px",r.style.height=o.scrollHeight+"px";var c=h.getTabSize.call(this,l),u=function e(t){t.target===r&&["width","height"].includes(t.propertyName)&&(r.style.width="",r.style.height="",s.off(r,s.transitionEnd,e))};s.on(r,s.transitionEnd,u),r.style.width=c.width+"px",r.style.height=c.height+"px"}o.setAttribute("aria-hidden",!0),o.setAttribute("tabindex",-1),l.setAttribute("aria-hidden",!n),i.setAttribute("aria-expanded",n),l.removeAttribute("tabindex")}},create:function(e){var t=this;if(s.is.empty(this.config.controls))return null;var i=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(h.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(h.createButton.call(this,"rewind")),this.config.controls.includes("play")&&(i.appendChild(h.createButton.call(this,"play")),i.appendChild(h.createButton.call(this,"pause"))),this.config.controls.includes("fast-forward")&&i.appendChild(h.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=s.createElement("span",s.getAttributesFromSelector(this.config.selectors.progress)),l=h.createRange.call(this,"seek",{id:"plyr-seek-"+e.id});if(n.appendChild(l.label),n.appendChild(l.input),n.appendChild(h.createProgress.call(this,"buffer")),this.config.tooltips.seek){var o=s.createElement("span",{role:"tooltip",class:this.config.classNames.tooltip},"00:00");n.appendChild(o),this.elements.display.seekTooltip=o}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(h.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(h.createTime.call(this,"duration")),this.config.controls.includes("mute")&&i.appendChild(h.createButton.call(this,"mute")),this.config.controls.includes("volume")){var r=s.createElement("span",{class:"plyr__volume"}),c={max:1,step:.05,value:this.config.volume},u=h.createRange.call(this,"volume",s.extend(c,{id:"plyr-volume-"+e.id}));r.appendChild(u.label),r.appendChild(u.input),i.appendChild(r)}if(this.config.controls.includes("captions")&&i.appendChild(h.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!s.is.empty(this.config.settings)){var d=s.createElement("div",{class:"plyr__menu"});d.appendChild(h.createButton.call(this,"settings",{id:"plyr-settings-toggle-"+e.id,"aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id,"aria-expanded":!1}));var p=s.createElement("form",{class:"plyr__menu__container",id:"plyr-settings-"+e.id,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tablist",tabindex:-1}),m=s.createElement("div"),g=s.createElement("div",{id:"plyr-settings-"+e.id+"-home","aria-hidden":!1,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tabpanel"}),f=s.createElement("ul",{role:"tablist"});this.config.settings.forEach(function(i){var n=s.createElement("li",{role:"tab",hidden:""}),a=s.createElement("button",s.extend(s.getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--forward",id:"plyr-settings-"+e.id+"-"+i+"-tab","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-"+i,"aria-expanded":!1}),t.config.i18n[i]),l=s.createElement("span",{class:t.config.classNames.menu.value});l.innerHTML=e[i],a.appendChild(l),n.appendChild(a),f.appendChild(n),t.elements.settings.tabs[i]=n}),g.appendChild(f),m.appendChild(g),this.config.settings.forEach(function(i){var n=s.createElement("div",{id:"plyr-settings-"+e.id+"-"+i,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-"+e.id+"-"+i+"-tab",role:"tabpanel",tabindex:-1,hidden:""}),a=s.createElement("button",{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--back","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-home","aria-expanded":!1},t.config.i18n[i]);n.appendChild(a);var l=s.createElement("ul");n.appendChild(l),m.appendChild(n),t.elements.settings.panes[i]=n}),p.appendChild(m),d.appendChild(p),i.appendChild(d),this.elements.settings.form=p,this.elements.settings.menu=d}return this.config.controls.includes("pip")&&a.pip&&i.appendChild(h.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&a.airplay&&i.appendChild(h.createButton.call(this,"airplay")),this.config.controls.includes("fullscreen")&&i.appendChild(h.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(h.createButton.call(this,"play-large")),this.elements.controls=i,this.config.controls.includes("settings")&&this.config.settings.includes("speed")&&h.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=h.getIconUrl.call(this);t.absolute&&s.loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;i=s.is.string(this.config.controls)?this.config.controls:s.is.function(this.config.controls)?this.config.controls({id:this.id,seektime:this.config.seekTime,title:this.config.title}):h.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:h.getLanguage.call(this)});var n=void 0;if(s.is.string(this.config.selectors.controls.container)&&(n=document.querySelector(this.config.selectors.controls.container)),s.is.htmlElement(n)||(n=this.elements.container),s.is.htmlElement(i)?n.appendChild(i):n.insertAdjacentHTML("beforeend",i),s.is.htmlElement(this.elements.controls)&&s.findElements.call(this),this.config.tooltips.controls){var a=s.getElements.call(this,[this.config.selectors.controls.wrapper," ",this.config.selectors.labels," .",this.config.classNames.hidden].join(""));Array.from(a).forEach(function(t){s.toggleClass(t,e.config.classNames.hidden,!1),s.toggleClass(t,e.config.classNames.tooltip,!0)})}}},m={setup:function(){var e=this;if(this.supported.ui){if(s.is.empty(r.get.call(this).language)?s.is.empty(this.captions.language)&&(this.captions.language=this.config.captions.language.toLowerCase()):this.captions.language=r.get.call(this).language,s.is.boolean(this.captions.enabled)||(s.is.empty(r.get.call(this).language)?this.captions.enabled=this.config.captions.active:this.captions.enabled=r.get.call(this).captions),!["video","vimeo"].includes(this.type)||"video"===this.type&&!a.textTracks)return this.captions.tracks=null,void(this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this));if(s.is.htmlElement(this.elements.captions)||(this.elements.captions=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.captions)),s.insertAfter(this.elements.captions,this.elements.wrapper)),"video"===this.type&&(this.captions.tracks=this.media.textTracks),s.toggleClass(this.elements.container,this.config.classNames.captions.enabled,!s.is.empty(this.captions.tracks)),!s.is.empty(this.captions.tracks)){m.show.call(this);var t=function(){e.captions.currentTrack=null,Array.from(e.captions.tracks).forEach(function(t){t.language===e.captions.language.toLowerCase()&&(e.captions.currentTrack=t)})};if(t(),!s.is.track(this.captions.currentTrack)){var i=this.config.captions.language;this.captions.language=i,t(),s.is.track(this.captions.currentTrack)||this.toggleCaptions(!1),h.updateSetting.call(this,"captions")}if("video"===this.type){Array.from(this.captions.tracks).forEach(function(t){s.off(t,"cuechange",function(t){return m.setCue.call(e,t)}),t.mode="hidden"});var n=this.captions.currentTrack&&["captions","subtitles"].includes(this.captions.currentTrack.kind);s.is.track(this.captions.currentTrack)&&n&&(s.on(this.captions.currentTrack,"cuechange",function(t){return m.setCue.call(e,t)}),this.captions.currentTrack.activeCues&&this.captions.currentTrack.activeCues.length>0&&m.setCue.call(this,this.captions.currentTrack))}else"vimeo"===this.type&&this.captions.active&&this.embed.enableTextTrack(this.captions.language);this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this)}}},setCue:function(e){var t=(s.is.event(e)?e.target:e).activeCues[0];s.is.cue(t)?m.set.call(this,t.getCueAsHTML()):m.set.call(this),s.dispatchEvent.call(this,this.media,"cuechange")},set:function(e){if(this.supported.ui)if(s.is.htmlElement(this.elements.captions)){var t=s.createElement("span");s.emptyElement(this.elements.captions);var i=s.is.undefined(e)?"":e;s.is.string(i)?t.textContent=i.trim():t.appendChild(i),this.elements.captions.appendChild(t)}else this.console.warn("No captions element to render to")},show:function(){if(s.is.htmlElement(this.elements.buttons.captions)){var e=r.get.call(this).captions;s.is.boolean(e)?this.captions.active=e:e=this.config.captions.active,e&&(s.toggleClass(this.elements.container,this.config.classNames.captions.active,!0),s.toggleState(this.elements.buttons.captions,!0))}}},g={setup:function(){var e=this,t=s.parseYouTubeId(this.embedId),i=s.getElements.call(this,'[id^="'+this.type+'-"]');Array.from(i).forEach(s.removeElement),s.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),g.setAspectRatio.call(this),this.media.setAttribute("id",s.generateId(this.type)),s.is.object(window.YT)?g.ready.call(this,t):(s.loadScript(this.config.urls.youtube.api),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){g.ready.call(e,t)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},setAspectRatio:function(){var e=this.config.ratio.split(":");this.elements.wrapper.style.paddingBottom=100/e[0]*e[1]+"%"},ready:function(e){var t=this;t.embed=new window.YT.Player(t.media.id,{videoId:e,playerVars:{autoplay:t.config.autoplay?1:0,controls:t.supported.ui?0:1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1,disablekb:1,playsinline:1,origin:window&&window.location.hostname,widget_referrer:window&&window.location.href,cc_load_policy:this.captions.active?1:0,cc_lang_pref:this.config.captions.language},events:{onError:function(e){s.dispatchEvent.call(t,t.media,"error",!0,{code:e.data,embed:e.target})},onPlaybackQualityChange:function(e){var i=e.target;t.media.quality=i.getPlaybackQuality(),s.dispatchEvent.call(t,t.media,"qualitychange")},onPlaybackRateChange:function(e){var i=e.target;t.media.playbackRate=i.getPlaybackRate(),s.dispatchEvent.call(t,t.media,"ratechange")},onReady:function(e){var i=e.target;t.media.play=function(){i.playVideo(),t.media.paused=!1},t.media.pause=function(){i.pauseVideo(),t.media.paused=!0},t.media.stop=function(){i.stopVideo(),t.media.paused=!0},t.media.duration=i.getDuration(),t.media.paused=!0,t.media.currentTime=0,Object.defineProperty(t.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(e){t.media.seeking=!0,s.dispatchEvent.call(t,t.media,"seeking"),i.seekTo(e)}}),Object.defineProperty(t.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}}),Object.defineProperty(t.media,"quality",{get:function(){return i.getPlaybackQuality()},set:function(e){s.dispatchEvent.call(t,t.media,"qualityrequested",!1,{quality:e}),i.setPlaybackQuality(e)}});var n=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return n},set:function(e){n=e,i.setVolume(100*n),s.dispatchEvent.call(t,t.media,"volumechange")}});var a=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return a},set:function(e){var n=s.is.boolean(e)?e:a;a=n,i[n?"mute":"unMute"](),s.dispatchEvent.call(t,t.media,"volumechange")}}),Object.defineProperty(t.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),t.config.controls.includes("settings")&&t.config.settings.includes("speed")&&h.setSpeedMenu.call(t,i.getAvailablePlaybackRates()),t.config.title=i.getVideoData().title,t.supported.ui&&t.media.setAttribute("tabindex",-1),s.dispatchEvent.call(t,t.media,"timeupdate"),s.dispatchEvent.call(t,t.media,"durationchange"),window.clearInterval(t.timers.buffering),t.timers.buffering=window.setInterval(function(){t.media.buffered=i.getVideoLoadedFraction(),(null===t.media.lastBuffered||t.media.lastBuffered1&&void 0!==arguments[1]&&arguments[1],n=function(){if(document.body.style.overflow="",t.embed=null,t.embedId=null,i)Object.keys(t.elements).length&&(t.elements.buttons&&t.elements.buttons.play&&Array.from(t.elements.buttons.play).forEach(function(e){return s.removeElement(e)}),s.removeElement(t.elements.captions),s.removeElement(t.elements.controls),s.removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),s.is.function(e)&&e();else{var n=t.elements.container.parentNode;s.is.htmlElement(n)&&n.replaceChild(t.elements.original,t.elements.container),s.dispatchEvent.call(t,t.elements.original,"destroyed",!0),s.is.function(e)&&e.call(t.elements.original),t.elements=null}};switch(this.type){case"youtube":window.clearInterval(this.timers.buffering),window.clearInterval(this.timers.playing),this.embed.destroy(),n();break;case"vimeo":this.embed.unload().then(n),window.setTimeout(n,200);break;case"video":case"audio":d.toggleNativeControls.call(this,!0),n()}}},{key:"isHTML5",get:function(){return n.html5.includes(this.type)}},{key:"isEmbed",get:function(){return n.embed.includes(this.type)}},{key:"paused",get:function(){return this.media.paused}},{key:"currentTime",set:function(e){var t=0;s.is.number(e)&&(t=e),t<0?t=0:t>this.duration&&(t=this.duration),this.media.currentTime=t.toFixed(4),this.console.log("Seeking to "+this.currentTime+" seconds")},get:function(){return Number(this.media.currentTime)}},{key:"seeking",get:function(){return this.media.seeking}},{key:"duration",get:function(){var e=parseInt(this.config.duration,10),t=Number(this.media.duration);return Number.isNaN(e)?t:e}},{key:"volume",set:function(e){var t=e;s.is.string(t)&&(t=Number(t)),s.is.number(t)||(t=r.get.call(this).volume),s.is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,this.muted&&t>0&&(this.muted=!1)},get:function(){return this.media.volume}},{key:"muted",set:function(e){var t=e;s.is.boolean(t)||(t=r.get.call(this).muted),s.is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return this.media.muted}},{key:"speed",set:function(e){var t=null;(t=s.is.number(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).speed:this.config.speed.selected)<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.console.warn("Unsupported speed ("+t+")")},get:function(){return this.media.playbackRate}},{key:"quality",set:function(e){var t=null;t=s.is.string(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).quality:this.config.quality.selected,this.options.quality.includes(t)?(this.config.quality.selected=t,this.media.quality=t):this.console.warn("Unsupported quality option ("+t+")")},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=s.is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return this.media.loop}},{key:"source",set:function(e){v.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"poster",set:function(e){"video"===this.type?s.is.string(e)&&this.media.setAttribute("poster",e):this.console.warn("Poster can only be set on HTML5 video")},get:function(){return"video"!==this.type?null:this.media.getAttribute("poster")}},{key:"autoplay",get:function(){return this.config.autoplay},set:function(e){var t=s.is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t}},{key:"language",set:function(e){if(s.is.string(e)){var t=e.toLowerCase();this.captions.language!==t&&(this.toggleCaptions(!0),this.captions.language=t,s.dispatchEvent.call(this,this.media,"languagechange"),m.set.call(this),m.setup.call(this))}},get:function(){return this.captions.language}},{key:"pip",set:function(e){var t={pip:"picture-in-picture",inline:"inline"};if(a.pip){var i=s.is.boolean(e)?e:this.pip===t.inline;this.media.webkitSetPresentationMode(i?t.pip:t.inline)}},get:function(){return a.pip?this.media.webkitPresentationMode:null}}]),e}()}); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Plyr",t):e.Plyr=t()}(this,function(){"use strict";function e(){var e=window.localStorage.getItem(this.config.storage.key);return s.is.empty(e)?{}:JSON.parse(e)}function t(t){if(a.storage&&this.config.storage.enabled&&s.is.object(t)){var i=e.call(this);s.extend(i,t),window.localStorage.setItem(this.config.storage.key,JSON.stringify(i))}}var i={enabled:!0,title:"",debug:!1,autoplay:!1,seekTime:10,volume:1,muted:!1,duration:null,displayDuration:!0,ratio:"16:9",clickToPlay:!0,hideControls:!0,showPosterOnEnd:!1,disableContextMenu:!0,loadSprite:!0,iconPrefix:"plyr",iconUrl:"https://cdn.plyr.io/2.0.10/plyr.svg",blankVideo:"https://cdn.plyr.io/static/blank.mp4",quality:{default:"default",options:["hd2160","hd1440","hd1080","hd720","large","medium","small","tiny","default"]},loop:{active:!1},speed:{selected:1,options:[.5,.75,1,1.25,1.5,1.75,2]},keyboard:{focused:!0,global:!1},tooltips:{controls:!1,seek:!0},captions:{active:!1,language:window.navigator.language.split("-")[0]},fullscreen:{enabled:!0,fallback:!0},storage:{enabled:!0,key:"plyr"},controls:["play-large","play","progress","current-time","mute","volume","captions","settings","pip","airplay","fullscreen"],settings:["captions","quality","speed","loop"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",seek:"Seek",played:"Played",buffered:"Buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",toggleMute:"Toggle Mute",toggleCaptions:"Toggle Captions",toggleFullscreen:"Toggle Fullscreen",frameTitle:"Player for {title}",captions:"Captions",settings:"Settings",speed:"Speed",quality:"Quality",loop:"Loop",start:"Start",end:"End",all:"All",reset:"Reset",none:"None",disabled:"Disabled"},urls:{vimeo:{api:"https://player.vimeo.com/api/player.js"},youtube:{api:"https://www.youtube.com/iframe_api"}},listeners:{seek:null,play:null,pause:null,restart:null,rewind:null,forward:null,mute:null,volume:null,captions:null,fullscreen:null,pip:null,airplay:null,speed:null,quality:null,loop:null,language:null},events:["ended","progress","stalled","playing","waiting","canplay","canplaythrough","loadstart","loadeddata","loadedmetadata","timeupdate","volumechange","play","pause","error","seeking","seeked","emptied","ratechange","cuechange","enterfullscreen","exitfullscreen","captionsenabled","captionsdisabled","languagechange","controlshidden","controlsshown","ready","statechange","qualitychange","qualityrequested"],selectors:{editable:"input, textarea, select, [contenteditable]",container:".plyr",controls:{container:null,wrapper:".plyr__controls"},labels:"[data-plyr]",buttons:{play:'[data-plyr="play"]',pause:'[data-plyr="pause"]',restart:'[data-plyr="restart"]',rewind:'[data-plyr="rewind"]',forward:'[data-plyr="fast-forward"]',mute:'[data-plyr="mute"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]',pip:'[data-plyr="pip"]',airplay:'[data-plyr="airplay"]',settings:'[data-plyr="settings"]',loop:'[data-plyr="loop"]'},inputs:{seek:'[data-plyr="seek"]',volume:'[data-plyr="volume"]',speed:'[data-plyr="speed"]',language:'[data-plyr="language"]',quality:'[data-plyr="quality"]'},display:{currentTime:".plyr__time--current",duration:".plyr__time--duration",buffer:".plyr__progress--buffer",played:".plyr__progress--played",loop:".plyr__progress--loop",volume:".plyr__volume--display"},progress:".plyr__progress",captions:".plyr__captions",menu:{quality:".js-plyr__menu__list--quality"}},classNames:{video:"plyr__video-wrapper",embed:"plyr__video-embed",control:"plyr__control",type:"plyr--{0}",stopped:"plyr--stopped",playing:"plyr--playing",loading:"plyr--loading",hover:"plyr--hover",tooltip:"plyr__tooltip",hidden:"plyr__sr-only",hideControls:"plyr--hide-controls",isIos:"plyr--is-ios",isTouch:"plyr--is-touch",uiSupported:"plyr--full-ui",menu:{value:"plyr__menu__value",badge:"plyr__badge"},captions:{enabled:"plyr--captions-enabled",active:"plyr--captions-active"},fullscreen:{enabled:"plyr--fullscreen-enabled",fallback:"plyr--fullscreen-fallback"},pip:{supported:"plyr--pip-supported",active:"plyr--pip-active"},airplay:{supported:"plyr--airplay-supported",active:"plyr--airplay-active"},tabFocus:"plyr__tab-focus"}},n={embed:["youtube","vimeo"],html5:["video","audio"]},s={is:{object:function(e){return this.getConstructor(e)===Object},number:function(e){return this.getConstructor(e)===Number&&!Number.isNaN(e)},string:function(e){return this.getConstructor(e)===String},boolean:function(e){return this.getConstructor(e)===Boolean},function:function(e){return this.getConstructor(e)===Function},array:function(e){return!this.undefined(e)&&Array.isArray(e)},nodeList:function(e){return!this.undefined(e)&&e instanceof NodeList},htmlElement:function(e){return!this.undefined(e)&&e instanceof HTMLElement},event:function(e){return!this.undefined(e)&&e instanceof Event},cue:function(e){return this.instanceOf(e,window.TextTrackCue)||this.instanceOf(e,window.VTTCue)},track:function(e){return!this.undefined(e)&&(this.instanceOf(e,window.TextTrack)||"string"==typeof e.kind)},undefined:function(e){return null!==e&&void 0===e},empty:function(e){return null===e||void 0===e||(this.string(e)||this.array(e)||this.nodeList(e))&&0===e.length||this.object(e)&&0===Object.keys(e).length},getConstructor:function(e){return null===e||void 0===e?null:e.constructor},instanceOf:function(e,t){return Boolean(e&&t&&e instanceof t)}},getBrowser:function(){return{isIE:!!document.documentMode,isWebkit:"WebkitAppearance"in document.documentElement.style&&!/Edge/.test(navigator.userAgent),isIPhone:/(iPhone|iPod)/gi.test(navigator.platform),isIos:/(iPad|iPhone|iPod)/gi.test(navigator.platform)}},loadScript:function(e,t){if(!document.querySelectorAll('script[src="'+e+'"]').length){var i=document.createElement("script");i.src=e;var n=document.getElementsByTagName("script")[0];s.is.function(t)&&i.addEventListener("load",function(e){return t.call(null,e)},!1),n.parentNode.insertBefore(i,n)}},loadSprite:function(e,t){function i(e){this.innerHTML=e,document.body.insertBefore(this,document.body.childNodes[0])}if("string"==typeof e){var n="string"==typeof t;if(!n||!document.querySelectorAll("#"+t).length){var s=document.createElement("div");if(s.setAttribute("hidden",""),n&&s.setAttribute("id",t),a.storage){var l=window.localStorage.getItem("cache-"+t);if(null!==l){var o=JSON.parse(l);i.call(s,o.content)}}var r=new XMLHttpRequest;if(!("withCredentials"in r))return;r.open("GET",e,!0),r.onload=function(){a.storage&&window.localStorage.setItem("cache-"+t,JSON.stringify({content:r.responseText})),i.call(s,r.responseText)},r.send()}}},generateId:function(e){return e+"-"+Math.floor(1e4*Math.random())},inFrame:function(){try{return window.self!==window.top}catch(e){return!0}},wrap:function(e,t){var i=e.length?e:[e];Array.from(i).reverse().forEach(function(e,i){var n=i>0?t.cloneNode(!0):t,s=e.parentNode,a=e.nextSibling;n.appendChild(e),a?s.insertBefore(n,a):s.appendChild(n)})},removeElement:function(e){return s.is.htmlElement(e)&&s.is.htmlElement(e.parentNode)?(e.parentNode.removeChild(e),e):null},insertAfter:function(e,t){t.parentNode.insertBefore(e,t.nextSibling)},createElement:function(e,t,i){var n=document.createElement(e);return s.is.object(t)&&s.setAttributes(n,t),s.is.string(i)&&(n.textContent=i),n},insertElement:function(e,t,i,n){t.appendChild(s.createElement(e,i,n))},emptyElement:function(e){for(var t=e.childNodes.length;t>0;)e.removeChild(e.lastChild),t-=1},setAttributes:function(e,t){Object.keys(t).forEach(function(i){e.setAttribute(i,t[i])})},getAttributesFromSelector:function(e,t){if(!s.is.string(e)||s.is.empty(e))return{};var i={},n=t;return e.split(",").forEach(function(e){var t=e.trim(),a=t.replace(".",""),l=t.replace(/[[\]]/g,"").split("="),o=l[0],r=l.length>1?l[1].replace(/["']/g,""):"";switch(t.charAt(0)){case".":s.is.object(n)&&s.is.string(n.class)&&(n.class+=" "+a),i.class=a;break;case"#":i.id=t.replace("#","");break;case"[":i[o]=r}}),i},toggleClass:function(e,t,i){if(s.is.htmlElement(e)){var n=e.classList.contains(t);return e.classList[i?"add":"remove"](t),i&&!n||!i&&n}return null},hasClass:function(e,t){return s.is.htmlElement(e)&&e.classList.contains(t)},matches:function(e,t){var i={Element:Element},n=i.matches||i.webkitMatchesSelector||i.mozMatchesSelector||i.msMatchesSelector||function(){return Array.from(document.querySelectorAll(t)).includes(this)};return n.call(e,t)},getElements:function(e){return this.elements.container.querySelectorAll(e)},getElement:function(e){return this.elements.container.querySelector(e)},findElements:function(){try{return this.elements.controls=s.getElement.call(this,this.config.selectors.controls.wrapper),this.elements.buttons={play:s.getElements.call(this,this.config.selectors.buttons.play),pause:s.getElement.call(this,this.config.selectors.buttons.pause),restart:s.getElement.call(this,this.config.selectors.buttons.restart),rewind:s.getElement.call(this,this.config.selectors.buttons.rewind),forward:s.getElement.call(this,this.config.selectors.buttons.forward),mute:s.getElement.call(this,this.config.selectors.buttons.mute),pip:s.getElement.call(this,this.config.selectors.buttons.pip),airplay:s.getElement.call(this,this.config.selectors.buttons.airplay),settings:s.getElement.call(this,this.config.selectors.buttons.settings),captions:s.getElement.call(this,this.config.selectors.buttons.captions),fullscreen:s.getElement.call(this,this.config.selectors.buttons.fullscreen)},this.elements.progress=s.getElement.call(this,this.config.selectors.progress),this.elements.inputs={seek:s.getElement.call(this,this.config.selectors.inputs.seek),volume:s.getElement.call(this,this.config.selectors.inputs.volume)},this.elements.display={buffer:s.getElement.call(this,this.config.selectors.display.buffer),duration:s.getElement.call(this,this.config.selectors.display.duration),currentTime:s.getElement.call(this,this.config.selectors.display.currentTime)},s.is.htmlElement(this.elements.progress)&&(this.elements.display.seekTooltip=this.elements.progress.querySelector("."+this.config.classNames.tooltip)),!0}catch(e){return this.console.warn("It looks like there is a problem with your custom controls HTML",e),this.toggleNativeControls(!0),!1}},getFocusElement:function(){var e=document.activeElement;return e=e&&e!==document.body?document.querySelector(":focus"):null},trapFocus:function(){var e=this,t=s.getElements.call(this,"button:not(:disabled), input:not(:disabled), [tabindex]"),i=t[0],n=t[t.length-1];s.on(this.elements.container,"keydown",function(t){if("Tab"===t.key&&9===t.keyCode&&e.fullscreen.active){var a=s.getFocusElement();a!==n||t.shiftKey?a===i&&t.shiftKey&&(n.focus(),t.preventDefault()):(i.focus(),t.preventDefault())}},!1)},toggleListener:function(e,t,i,n,l,o){if(null!==e&&!s.is.undefined(e))if(s.is.nodeList(e))Array.from(e).forEach(function(e){e instanceof Node&&s.toggleListener.call(null,e,t,i,n,l,o)});else{var r=t.split(" "),c=!!s.is.boolean(o)&&o;a.passiveListeners&&(c={passive:!s.is.boolean(l)||l,capture:!!s.is.boolean(o)&&o}),r.forEach(function(t){e[n?"addEventListener":"removeEventListener"](t,i,c)})}},on:function(e,t,i,n,a){s.toggleListener(e,t,i,!0,n,a)},off:function(e,t,i,n,a){s.toggleListener(e,t,i,!1,n,a)},dispatchEvent:function(e,t,i,n){if(e&&t){var a=new CustomEvent(t,{bubbles:!!s.is.boolean(i)&&i,detail:Object.assign({},n,{plyr:this instanceof Plyr?this:null})});e.dispatchEvent(a)}},toggleState:function(e,t){if(s.is.htmlElement(e)){var i=s.is.boolean(t)?t:!e.getAttribute("aria-pressed");e.setAttribute("aria-pressed",i)}},getPercentage:function(e,t){return 0===e||0===t||Number.isNaN(e)||Number.isNaN(t)?0:(e/t*100).toFixed(2)},extend:function(){for(var e=arguments.length,t=Array(e),i=0;i0)&&(i?(e.decreaseVolume(.02),n=-1):(e.increaseVolume(.02),n=1)),(t.deltaY>0||t.deltaX<0)&&(i?(e.increaseVolume(.02),n=1):(e.decreaseVolume(.02),n=-1)),(1===n&&e.media.volume<1||-1===n&&e.media.volume>0)&&t.preventDefault()})},!1)}},d={addStyleHook:function(){s.toggleClass(this.elements.container,this.config.selectors.container.replace(".",""),!0),s.toggleClass(this.elements.container,this.config.classNames.uiSupported,this.supported.ui)},toggleNativeControls:function(e){e&&this.isHTML5?this.media.setAttribute("controls",""):this.media.removeAttribute("controls")},build:function(){if(u.media.call(this),!this.supported.ui)return this.console.warn("Basic support only for "+this.type),s.removeElement.call(this,"controls"),s.removeElement.call(this,"buttons.play"),void d.toggleNativeControls.call(this,!0);s.is.htmlElement(this.elements.controls)||(h.inject.call(this),u.controls.call(this)),s.is.htmlElement(this.elements.controls)&&(d.toggleNativeControls.call(this),o.setup.call(this),m.setup.call(this),this.volume=null,this.muted=null,this.speed=null,this.loop=null,this.options.quality=[],d.timeUpdate.call(this),d.checkPlaying.call(this),this.ready=!0,s.dispatchEvent.call(this,this.media,"ready"))},displayDuration:function(){this.supported.ui&&(!this.elements.display.duration&&this.config.displayDuration&&this.paused&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.currentTime),this.elements.display.duration&&d.updateTimeDisplay.call(this,this.duration,this.elements.display.duration),h.updateSeekTooltip.call(this))},setTitle:function(){var e=this.config.i18n.play;if(s.is.string(this.config.title)&&!s.is.empty(this.config.title)&&(e+=", "+this.config.title,this.elements.container.setAttribute("aria-label",this.config.title)),this.supported.ui&&(s.is.htmlElement(this.elements.buttons.play)&&this.elements.buttons.play.setAttribute("aria-label",e),s.is.htmlElement(this.elements.buttons.playLarge)&&this.elements.buttons.playLarge.setAttribute("aria-label",e)),this.isEmbed){var t=s.getElement.call(this,"iframe");if(!s.is.htmlElement(t))return;var i=s.is.empty(this.config.title)?"video":this.config.title;t.setAttribute("title",this.config.i18n.frameTitle.replace("{title}",i))}},checkPlaying:function(){s.toggleClass(this.elements.container,this.config.classNames.playing,!this.paused),s.toggleClass(this.elements.container,this.config.classNames.stopped,this.paused),this.toggleControls(this.paused)},updateVolume:function(){this.supported.ui&&(s.is.htmlElement(this.elements.inputs.volume)&&d.setRange.call(this,this.elements.inputs.volume,this.muted?0:this.volume),s.is.htmlElement(this.elements.buttons.mute)&&s.toggleState(this.elements.buttons.mute,this.muted||0===this.volume))},checkLoading:function(e){var t=this;this.loading="waiting"===e.type,clearTimeout(this.timers.loading),this.timers.loading=setTimeout(function(){s.toggleClass(t.elements.container,t.config.classNames.loading,t.loading),t.toggleControls(t.loading)},this.loading?250:0)},setRange:function(e,t){s.is.htmlElement(e)&&(e.value=t,h.updateRangeFill.call(this,e))},setProgress:function(e,t){var i=s.is.undefined(t)?0:t,n=s.is.undefined(e)?this.elements.display.buffer:e;if(s.is.htmlElement(n)){n.value=i;var a=n.getElementsByTagName("span")[0];s.is.htmlElement(a)&&(a.childNodes[0].nodeValue=i)}},updateProgress:function(e){var t=this;if(this.supported.ui){var i=0;if(e)switch(e.type){case"timeupdate":case"seeking":i=s.getPercentage(this.currentTime,this.duration),"timeupdate"===e.type&&d.setRange.call(this,this.elements.inputs.seek,i);break;case"playing":case"progress":i=function(){var e=t.media.buffered;return e&&e.length?s.getPercentage(e.end(0),t.duration):s.is.number(e)?100*e:0}(),d.setProgress.call(this,this.elements.display.buffer,i)}}},updateTimeDisplay:function(e,t){if(!s.is.htmlElement(t))return null;var i=Number.isNaN(e)?0:e,n=parseInt(i%60,10),a=parseInt(i/60%60,10),l=parseInt(i/60/60%60,10),o=parseInt(this.duration/60/60%60,10)>0;n=("0"+n).slice(-2),a=("0"+a).slice(-2);var r=(o?l+":":"")+a+":"+n;return t.textContent=r,r},timeUpdate:function(e){d.updateTimeDisplay.call(this,this.currentTime,this.elements.display.currentTime),e&&"timeupdate"===e.type&&this.media.seeking||d.updateProgress.call(this,e)}},p=s.getBrowser(),h={updateRangeFill:function(e){if(p.isWebkit){var t=s.is.event(e)?e.target:e;if(s.is.htmlElement(t)&&"range"===t.getAttribute("type")){s.is.htmlElement(this.elements.styleSheet)||(this.elements.styleSheet=s.createElement("style"),this.elements.container.appendChild(this.elements.styleSheet));var i=this.elements.styleSheet.sheet,n=t.value/t.max*100,a="#"+t.id+"::-webkit-slider-runnable-track",l="{ background-image: linear-gradient(to right, currentColor "+n+"%, transparent "+n+"%) }",o=Array.from(i.rules).findIndex(function(e){return e.selectorText===a});-1!==o&&i.deleteRule(o),i.insertRule([a,l].join(" "))}}},getIconUrl:function(){return{url:this.config.iconUrl,absolute:0===this.config.iconUrl.indexOf("http")||p.isIE&&!window.svg4everybody}},createIcon:function(e,t){var i=h.getIconUrl.call(this),n=(i.absolute?"":i.url)+"#"+this.config.iconPrefix,a=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttributes(a,s.extend(t,{role:"presentation"}));var l=document.createElementNS("http://www.w3.org/2000/svg","use"),o=n+"-"+e;return"href"in l?l.setAttribute("href",o):l.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",o),a.appendChild(l),a},createLabel:function(e){var t=this.config.i18n[e];switch(e){case"pip":t="PIP";break;case"airplay":t="AirPlay"}return s.createElement("span",{class:this.config.classNames.hidden},t)},createBadge:function(e){var t=s.createElement("span",{class:this.config.classNames.menu.value});return t.appendChild(s.createElement("span",{class:this.config.classNames.menu.badge},e)),t},createButton:function(e,t){var i=s.createElement("button"),n=Object.assign({},t),a=e,l=void 0,o=void 0,r=void 0;switch("type"in n||(n.type="button"),"class"in n?-1===n.class.indexOf(this.config.classNames.control)&&(n.class+=" "+this.config.classNames.control):n.class=this.config.classNames.control,a){case"mute":r="toggleMute",l="volume",o="muted";break;case"captions":r="toggleCaptions",l="captions-off",o="captions-on";break;case"fullscreen":r="toggleFullscreen",l="enter-fullscreen",o="exit-fullscreen";break;case"play-large":n.class="plyr__play-large",a="play",r="play",l="play";break;default:r=a,l=a}return s.extend(n,s.getAttributesFromSelector(this.config.selectors.buttons[a],n)),s.is.string(o)?(i.appendChild(h.createIcon.call(this,o,{class:"icon--pressed"})),i.appendChild(h.createIcon.call(this,l,{class:"icon--not-pressed"}))):i.appendChild(h.createIcon.call(this,l)),i.appendChild(h.createLabel.call(this,r)),s.setAttributes(i,n),this.elements.buttons[a]=i,i},createRange:function(e,t){var i=s.createElement("label",{for:t.id,class:this.config.classNames.hidden},this.config.i18n[e]),n=s.createElement("input",s.extend(s.getAttributesFromSelector(this.config.selectors.inputs[e]),{type:"range",min:0,max:100,step:.01,value:0,autocomplete:"off"},t));return this.elements.inputs[e]=n,h.updateRangeFill.call(this,n),{label:i,input:n}},createProgress:function(e,t){var i=s.createElement("progress",s.extend(s.getAttributesFromSelector(this.config.selectors.display[e]),{min:0,max:100,value:0},t));if("volume"!==e){i.appendChild(s.createElement("span",null,"0"));var n="";switch(e){case"played":n=this.config.i18n.played;break;case"buffer":n=this.config.i18n.buffered}i.textContent="% "+n.toLowerCase()}return this.elements.display[e]=i,i},createTime:function(e){var t=s.createElement("span",{class:"plyr__time"});return t.appendChild(s.createElement("span",{class:this.config.classNames.hidden},this.config.i18n[e])),t.appendChild(s.createElement("span",s.getAttributesFromSelector(this.config.selectors.display[e]),"00:00")),this.elements.display[e]=t,t},updateSeekTooltip:function(e){if(this.config.tooltips.seek&&s.is.htmlElement(this.elements.inputs.seek)&&s.is.htmlElement(this.elements.display.seekTooltip)&&0!==this.duration){var t=0,i=this.elements.inputs.seek.getBoundingClientRect(),n=this.config.classNames.tooltip+"--visible";if(s.is.event(e))t=100/i.width*(e.pageX-i.left);else{if(!s.hasClass(this.elements.display.seekTooltip,n))return;t=this.elements.display.seekTooltip.style.left.replace("%","")}t<0?t=0:t>100&&(t=100),d.updateTimeDisplay.call(this,this.duration/100*t,this.elements.display.seekTooltip),this.elements.display.seekTooltip.style.left=t+"%",s.is.event(e)&&["mouseenter","mouseleave"].includes(e.type)&&s.toggleClass(this.elements.display.seekTooltip,n,"mouseenter"===e.type)}},toggleTab:function(e,t){var i=this.elements.settings.tabs[e],n=this.elements.settings.panes[e];s.is.htmlElement(i)&&(t?i.removeAttribute("hidden"):i.setAttribute("hidden","")),s.is.htmlElement(n)&&(t?n.removeAttribute("hidden"):n.setAttribute("hidden",""))},setQualityMenu:function(e){var t=this,i=this.elements.settings.panes.quality.querySelector("ul");s.is.array(e)?this.options.quality=e.filter(function(e){return t.config.quality.options.includes(e)}):this.options.quality=this.config.quality.options;var n=!s.is.empty(this.options.quality)&&"youtube"===this.type;if(h.toggleTab.call(this,"quality",n),n){s.emptyElement(i);var a=function(e){var i="";switch(e){case"hd2160":i="4K";break;case"hd1440":i="WQHD";break;case"hd1080":case"hd720":i="HD"}return i.length?h.createBadge.call(t,i):null};this.options.quality.forEach(function(e){var n=s.createElement("li"),l=s.createElement("label",{class:t.config.classNames.control}),o=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.quality),{type:"radio",name:"plyr-quality",value:e}));l.appendChild(o),l.appendChild(document.createTextNode(h.getLabel.call(t,"quality",e)));var r=a(e);s.is.htmlElement(r)&&l.appendChild(r),n.appendChild(l),i.appendChild(n)}),h.updateSetting.call(this,"quality",i)}},getLabel:function(e,t){switch(e){case"speed":return 1===t?"Normal":t+"×";case"quality":switch(t){case"hd2160":return"2160P";case"hd1440":return"1440P";case"hd1080":return"1080P";case"hd720":return"720P";case"large":return"480P";case"medium":return"360P";case"small":return"240P";case"tiny":return"Tiny";case"default":return"Auto";default:return t}case"captions":return h.getLanguage.call(this);default:return null}},updateSetting:function(e,t){var i=this.elements.settings.panes[e],n=null,a=t;switch(e){case"captions":n=this.captions.language,this.captions.enabled||(n="");break;default:if(n=this[e],s.is.empty(n)&&(n=this.config[e].default),!this.options[e].includes(n))return void this.console.warn("Unsupported value of '"+n+"' for "+e);if(!this.config[e].options.includes(n))return void this.console.warn("Disabled value of '"+n+"' for "+e)}s.is.htmlElement(a)||(a=i&&i.querySelector("ul"));var l=a&&a.querySelector('input[value="'+n+'"]');s.is.htmlElement(l)&&(l.checked=!0,this.elements.settings.tabs[e].querySelector("."+this.config.classNames.menu.value).innerHTML=h.getLabel.call(this,e,n))},setLoopMenu:function(){var e=this,t=this.elements.settings.panes.loop.querySelector("ul");this.elements.settings.tabs.loop.removeAttribute("hidden"),this.elements.settings.panes.loop.removeAttribute("hidden");var i=!s.is.empty(this.loop.options);h.toggleTab.call(this,"loop",i),s.emptyElement(t),["start","end","all","reset"].forEach(function(i){var n=s.createElement("li"),a=s.createElement("button",s.extend(s.getAttributesFromSelector(e.config.selectors.buttons.loop),{type:"button",class:e.config.classNames.control,"data-plyr-loop-action":i}),e.config.i18n[i]);if(["start","end"].includes(i)){var l=h.createBadge.call(e,"00:00");a.appendChild(l)}n.appendChild(a),t.appendChild(n)})},getLanguage:function(){return this.supported.ui?!a.textTracks||s.is.empty(this.captions.tracks)?this.config.i18n.none:this.captions.enabled?this.captions.currentTrack.label:this.config.i18n.disabled:null},setCaptionsMenu:function(){var e=this,t=this.elements.settings.panes.captions.querySelector("ul"),i=!s.is.empty(this.captions.tracks);if(h.toggleTab.call(this,"captions",i),s.emptyElement(t),!s.is.empty(this.captions.tracks)){var n=Array.from(this.captions.tracks).map(function(e){return{language:e.language,badge:!0,label:s.is.empty(e.label)?e.language.toUpperCase():e.label}});n.unshift({language:"",label:this.config.i18n.none}),n.forEach(function(i){var n=s.createElement("li"),a=s.createElement("label",{class:e.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(e.config.selectors.inputs.language),{type:"radio",name:"plyr-language",value:i.language}));i.language.toLowerCase()===e.captions.language.toLowerCase()&&(l.checked=!0),a.appendChild(l),a.appendChild(document.createTextNode(i.label||i.language)),i.badge&&a.appendChild(h.createBadge.call(e,i.language.toUpperCase())),n.appendChild(a),t.appendChild(n)}),h.updateSetting.call(this,"captions",t)}},setSpeedMenu:function(e){var t=this;s.is.array(e)?this.options.speed=e.filter(function(e){return t.config.speed.options.includes(e)}):this.options.speed=this.config.speed.options;var i=!s.is.empty(this.options.speed);if(h.toggleTab.call(this,"speed",i),i){var n=this.elements.settings.panes.speed.querySelector("ul");this.elements.settings.tabs.speed.removeAttribute("hidden"),this.elements.settings.panes.speed.removeAttribute("hidden"),s.emptyElement(n),this.options.speed.forEach(function(e){var i=s.createElement("li"),a=s.createElement("label",{class:t.config.classNames.control}),l=s.createElement("input",s.extend(s.getAttributesFromSelector(t.config.selectors.inputs.speed),{type:"radio",name:"plyr-speed",value:e}));a.appendChild(l),a.insertAdjacentHTML("beforeend",h.getLabel.call(t,"speed",e)),i.appendChild(a),n.appendChild(i)}),h.updateSetting.call(this,"speed",n)}},toggleMenu:function(e){var t=this.elements.settings.form,i=this.elements.buttons.settings,n=s.is.boolean(e)?e:t&&"true"===t.getAttribute("aria-hidden");if(s.is.event(e)){var a=t&&t.contains(e.target),l=e.target===this.elements.buttons.settings;if(a||!a&&!l&&n)return;l&&e.stopPropagation()}i&&i.setAttribute("aria-expanded",n),t&&(t.setAttribute("aria-hidden",!n),n?t.removeAttribute("tabindex"):t.setAttribute("tabindex",-1))},getTabSize:function(e){var t=e.cloneNode(!0);t.style.position="absolute",t.style.opacity=0,t.setAttribute("aria-hidden",!1),Array.from(t.querySelectorAll("input[name]")).forEach(function(e){var t=e.getAttribute("name");e.setAttribute("name",t+"-clone")}),e.parentNode.appendChild(t);var i=t.scrollWidth,n=t.scrollHeight;return s.removeElement(t),{width:i,height:n}},showTab:function(e){var t=this.elements.settings.menu,i=e.target,n="false"===i.getAttribute("aria-expanded"),l=document.getElementById(i.getAttribute("aria-controls"));if(s.is.htmlElement(l)&&"tabpanel"===l.getAttribute("role")){var o=t.querySelector('[role="tabpanel"][aria-hidden="false"]'),r=o.parentNode;if(Array.from(t.querySelectorAll('[aria-controls="'+o.getAttribute("id")+'"]')).forEach(function(e){e.setAttribute("aria-expanded",!1)}),a.transitions&&!a.reducedMotion){r.style.width=o.scrollWidth+"px",r.style.height=o.scrollHeight+"px";var c=h.getTabSize.call(this,l),u=function e(t){t.target===r&&["width","height"].includes(t.propertyName)&&(r.style.width="",r.style.height="",s.off(r,s.transitionEnd,e))};s.on(r,s.transitionEnd,u),r.style.width=c.width+"px",r.style.height=c.height+"px"}o.setAttribute("aria-hidden",!0),o.setAttribute("tabindex",-1),l.setAttribute("aria-hidden",!n),i.setAttribute("aria-expanded",n),l.removeAttribute("tabindex")}},create:function(e){var t=this;if(s.is.empty(this.config.controls))return null;var i=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.controls.wrapper));if(this.config.controls.includes("restart")&&i.appendChild(h.createButton.call(this,"restart")),this.config.controls.includes("rewind")&&i.appendChild(h.createButton.call(this,"rewind")),this.config.controls.includes("play")&&(i.appendChild(h.createButton.call(this,"play")),i.appendChild(h.createButton.call(this,"pause"))),this.config.controls.includes("fast-forward")&&i.appendChild(h.createButton.call(this,"fast-forward")),this.config.controls.includes("progress")){var n=s.createElement("span",s.getAttributesFromSelector(this.config.selectors.progress)),l=h.createRange.call(this,"seek",{id:"plyr-seek-"+e.id});if(n.appendChild(l.label),n.appendChild(l.input),n.appendChild(h.createProgress.call(this,"buffer")),this.config.tooltips.seek){var o=s.createElement("span",{role:"tooltip",class:this.config.classNames.tooltip},"00:00");n.appendChild(o),this.elements.display.seekTooltip=o}this.elements.progress=n,i.appendChild(this.elements.progress)}if(this.config.controls.includes("current-time")&&i.appendChild(h.createTime.call(this,"currentTime")),this.config.controls.includes("duration")&&i.appendChild(h.createTime.call(this,"duration")),this.config.controls.includes("mute")&&i.appendChild(h.createButton.call(this,"mute")),this.config.controls.includes("volume")){var r=s.createElement("span",{class:"plyr__volume"}),c={max:1,step:.05,value:this.config.volume},u=h.createRange.call(this,"volume",s.extend(c,{id:"plyr-volume-"+e.id}));r.appendChild(u.label),r.appendChild(u.input),i.appendChild(r)}if(this.config.controls.includes("captions")&&i.appendChild(h.createButton.call(this,"captions")),this.config.controls.includes("settings")&&!s.is.empty(this.config.settings)){var d=s.createElement("div",{class:"plyr__menu"});d.appendChild(h.createButton.call(this,"settings",{id:"plyr-settings-toggle-"+e.id,"aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id,"aria-expanded":!1}));var p=s.createElement("form",{class:"plyr__menu__container",id:"plyr-settings-"+e.id,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tablist",tabindex:-1}),m=s.createElement("div"),g=s.createElement("div",{id:"plyr-settings-"+e.id+"-home","aria-hidden":!1,"aria-labelled-by":"plyr-settings-toggle-"+e.id,role:"tabpanel"}),f=s.createElement("ul",{role:"tablist"});this.config.settings.forEach(function(i){var n=s.createElement("li",{role:"tab",hidden:""}),a=s.createElement("button",s.extend(s.getAttributesFromSelector(t.config.selectors.buttons.settings),{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--forward",id:"plyr-settings-"+e.id+"-"+i+"-tab","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-"+i,"aria-expanded":!1}),t.config.i18n[i]),l=s.createElement("span",{class:t.config.classNames.menu.value});l.innerHTML=e[i],a.appendChild(l),n.appendChild(a),f.appendChild(n),t.elements.settings.tabs[i]=n}),g.appendChild(f),m.appendChild(g),this.config.settings.forEach(function(i){var n=s.createElement("div",{id:"plyr-settings-"+e.id+"-"+i,"aria-hidden":!0,"aria-labelled-by":"plyr-settings-"+e.id+"-"+i+"-tab",role:"tabpanel",tabindex:-1,hidden:""}),a=s.createElement("button",{type:"button",class:t.config.classNames.control+" "+t.config.classNames.control+"--back","aria-haspopup":!0,"aria-controls":"plyr-settings-"+e.id+"-home","aria-expanded":!1},t.config.i18n[i]);n.appendChild(a);var l=s.createElement("ul");n.appendChild(l),m.appendChild(n),t.elements.settings.panes[i]=n}),p.appendChild(m),d.appendChild(p),i.appendChild(d),this.elements.settings.form=p,this.elements.settings.menu=d}return this.config.controls.includes("pip")&&a.pip&&i.appendChild(h.createButton.call(this,"pip")),this.config.controls.includes("airplay")&&a.airplay&&i.appendChild(h.createButton.call(this,"airplay")),this.config.controls.includes("fullscreen")&&i.appendChild(h.createButton.call(this,"fullscreen")),this.config.controls.includes("play-large")&&this.elements.container.appendChild(h.createButton.call(this,"play-large")),this.elements.controls=i,this.config.controls.includes("settings")&&this.config.settings.includes("speed")&&h.setSpeedMenu.call(this),i},inject:function(){var e=this;if(this.config.loadSprite){var t=h.getIconUrl.call(this);t.absolute&&s.loadSprite(t.url,"sprite-plyr")}this.id=Math.floor(1e4*Math.random());var i=null;i=s.is.string(this.config.controls)?this.config.controls:s.is.function(this.config.controls)?this.config.controls({id:this.id,seektime:this.config.seekTime,title:this.config.title}):h.create.call(this,{id:this.id,seektime:this.config.seekTime,speed:this.speed,quality:this.quality,captions:h.getLanguage.call(this)});var n=void 0;if(s.is.string(this.config.selectors.controls.container)&&(n=document.querySelector(this.config.selectors.controls.container)),s.is.htmlElement(n)||(n=this.elements.container),s.is.htmlElement(i)?n.appendChild(i):n.insertAdjacentHTML("beforeend",i),s.is.htmlElement(this.elements.controls)&&s.findElements.call(this),this.config.tooltips.controls){var a=s.getElements.call(this,[this.config.selectors.controls.wrapper," ",this.config.selectors.labels," .",this.config.classNames.hidden].join(""));Array.from(a).forEach(function(t){s.toggleClass(t,e.config.classNames.hidden,!1),s.toggleClass(t,e.config.classNames.tooltip,!0)})}}},m={setup:function(){var e=this;if(this.supported.ui){if(s.is.empty(r.get.call(this).language)?s.is.empty(this.captions.language)&&(this.captions.language=this.config.captions.language.toLowerCase()):this.captions.language=r.get.call(this).language,s.is.boolean(this.captions.enabled)||(s.is.empty(r.get.call(this).language)?this.captions.enabled=this.config.captions.active:this.captions.enabled=r.get.call(this).captions),!["video","vimeo"].includes(this.type)||"video"===this.type&&!a.textTracks)return this.captions.tracks=null,void(this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this));if(s.is.htmlElement(this.elements.captions)||(this.elements.captions=s.createElement("div",s.getAttributesFromSelector(this.config.selectors.captions)),s.insertAfter(this.elements.captions,this.elements.wrapper)),"video"===this.type&&(this.captions.tracks=this.media.textTracks),s.toggleClass(this.elements.container,this.config.classNames.captions.enabled,!s.is.empty(this.captions.tracks)),!s.is.empty(this.captions.tracks)){m.show.call(this);var t=function(){e.captions.currentTrack=null,Array.from(e.captions.tracks).forEach(function(t){t.language===e.captions.language.toLowerCase()&&(e.captions.currentTrack=t)})};if(t(),!s.is.track(this.captions.currentTrack)){var i=this.config.captions.language;this.captions.language=i,t(),s.is.track(this.captions.currentTrack)||this.toggleCaptions(!1),h.updateSetting.call(this,"captions")}if("video"===this.type){Array.from(this.captions.tracks).forEach(function(t){s.off(t,"cuechange",function(t){return m.setCue.call(e,t)}),t.mode="hidden"});var n=this.captions.currentTrack&&["captions","subtitles"].includes(this.captions.currentTrack.kind);s.is.track(this.captions.currentTrack)&&n&&(s.on(this.captions.currentTrack,"cuechange",function(t){return m.setCue.call(e,t)}),this.captions.currentTrack.activeCues&&this.captions.currentTrack.activeCues.length>0&&m.setCue.call(this,this.captions.currentTrack))}else"vimeo"===this.type&&this.captions.active&&this.embed.enableTextTrack(this.captions.language);this.config.controls.includes("settings")&&this.config.settings.includes("captions")&&h.setCaptionsMenu.call(this)}}},setCue:function(e){var t=(s.is.event(e)?e.target:e).activeCues[0];s.is.cue(t)?m.set.call(this,t.getCueAsHTML()):m.set.call(this),s.dispatchEvent.call(this,this.media,"cuechange")},set:function(e){if(this.supported.ui)if(s.is.htmlElement(this.elements.captions)){var t=s.createElement("span");s.emptyElement(this.elements.captions);var i=s.is.undefined(e)?"":e;s.is.string(i)?t.textContent=i.trim():t.appendChild(i),this.elements.captions.appendChild(t)}else this.console.warn("No captions element to render to")},show:function(){if(s.is.htmlElement(this.elements.buttons.captions)){var e=r.get.call(this).captions;s.is.boolean(e)?this.captions.active=e:e=this.config.captions.active,e&&(s.toggleClass(this.elements.container,this.config.classNames.captions.active,!0),s.toggleState(this.elements.buttons.captions,!0))}}},g={setup:function(){var e=this,t=s.parseYouTubeId(this.embedId),i=s.getElements.call(this,'[id^="'+this.type+'-"]');Array.from(i).forEach(s.removeElement),s.toggleClass(this.elements.wrapper,this.config.classNames.embed,!0),g.setAspectRatio.call(this),this.media.setAttribute("id",s.generateId(this.type)),s.is.object(window.YT)?g.ready.call(this,t):(s.loadScript(this.config.urls.youtube.api),window.onYouTubeReadyCallbacks=window.onYouTubeReadyCallbacks||[],window.onYouTubeReadyCallbacks.push(function(){g.ready.call(e,t)}),window.onYouTubeIframeAPIReady=function(){window.onYouTubeReadyCallbacks.forEach(function(e){e()})})},setAspectRatio:function(){var e=this.config.ratio.split(":");this.elements.wrapper.style.paddingBottom=100/e[0]*e[1]+"%"},ready:function(e){var t=this;t.embed=new window.YT.Player(t.media.id,{videoId:e,playerVars:{autoplay:t.config.autoplay?1:0,controls:t.supported.ui?0:1,rel:0,showinfo:0,iv_load_policy:3,modestbranding:1,disablekb:1,playsinline:1,origin:window&&window.location.hostname,widget_referrer:window&&window.location.href,cc_load_policy:this.captions.active?1:0,cc_lang_pref:this.config.captions.language},events:{onError:function(e){s.dispatchEvent.call(t,t.media,"error",!0,{code:e.data,embed:e.target})},onPlaybackQualityChange:function(e){var i=e.target;t.media.quality=i.getPlaybackQuality(),s.dispatchEvent.call(t,t.media,"qualitychange")},onPlaybackRateChange:function(e){var i=e.target;t.media.playbackRate=i.getPlaybackRate(),s.dispatchEvent.call(t,t.media,"ratechange")},onReady:function(e){var i=e.target;t.media.play=function(){i.playVideo(),t.media.paused=!1},t.media.pause=function(){i.pauseVideo(),t.media.paused=!0},t.media.stop=function(){i.stopVideo(),t.media.paused=!0},t.media.duration=i.getDuration(),t.media.paused=!0,t.media.currentTime=0,Object.defineProperty(t.media,"currentTime",{get:function(){return Number(i.getCurrentTime())},set:function(e){t.media.seeking=!0,s.dispatchEvent.call(t,t.media,"seeking"),i.seekTo(e)}}),Object.defineProperty(t.media,"playbackRate",{get:function(){return i.getPlaybackRate()},set:function(e){i.setPlaybackRate(e)}}),Object.defineProperty(t.media,"quality",{get:function(){return i.getPlaybackQuality()},set:function(e){s.dispatchEvent.call(t,t.media,"qualityrequested",!1,{quality:e}),i.setPlaybackQuality(e)}});var n=t.config.volume;Object.defineProperty(t.media,"volume",{get:function(){return n},set:function(e){n=e,i.setVolume(100*n),s.dispatchEvent.call(t,t.media,"volumechange")}});var a=t.config.muted;Object.defineProperty(t.media,"muted",{get:function(){return a},set:function(e){var n=s.is.boolean(e)?e:a;a=n,i[n?"mute":"unMute"](),s.dispatchEvent.call(t,t.media,"volumechange")}}),Object.defineProperty(t.media,"currentSrc",{get:function(){return i.getVideoUrl()}}),t.config.controls.includes("settings")&&t.config.settings.includes("speed")&&h.setSpeedMenu.call(t,i.getAvailablePlaybackRates()),t.config.title=i.getVideoData().title,t.supported.ui&&t.media.setAttribute("tabindex",-1),s.dispatchEvent.call(t,t.media,"timeupdate"),s.dispatchEvent.call(t,t.media,"durationchange"),window.clearInterval(t.timers.buffering),t.timers.buffering=window.setInterval(function(){t.media.buffered=i.getVideoLoadedFraction(),(null===t.media.lastBuffered||t.media.lastBuffered1&&void 0!==arguments[1]&&arguments[1],n=function(){if(document.body.style.overflow="",t.embed=null,t.embedId=null,i)Object.keys(t.elements).length&&(t.elements.buttons&&t.elements.buttons.play&&Array.from(t.elements.buttons.play).forEach(function(e){return s.removeElement(e)}),s.removeElement(t.elements.captions),s.removeElement(t.elements.controls),s.removeElement(t.elements.wrapper),t.elements.buttons.play=null,t.elements.captions=null,t.elements.controls=null,t.elements.wrapper=null),s.is.function(e)&&e();else{var n=t.elements.container.parentNode;s.is.htmlElement(n)&&n.replaceChild(t.elements.original,t.elements.container),s.dispatchEvent.call(t,t.elements.original,"destroyed",!0),s.is.function(e)&&e.call(t.elements.original),t.elements=null}};switch(this.type){case"youtube":window.clearInterval(this.timers.buffering),window.clearInterval(this.timers.playing),this.embed.destroy(),n();break;case"vimeo":this.embed.unload().then(n),window.setTimeout(n,200);break;case"video":case"audio":d.toggleNativeControls.call(this,!0),n()}}},{key:"isHTML5",get:function(){return n.html5.includes(this.type)}},{key:"isEmbed",get:function(){return n.embed.includes(this.type)}},{key:"paused",get:function(){return this.media.paused}},{key:"currentTime",set:function(e){var t=0;s.is.number(e)&&(t=e),t<0?t=0:t>this.duration&&(t=this.duration),this.media.currentTime=t.toFixed(4),this.console.log("Seeking to "+this.currentTime+" seconds")},get:function(){return Number(this.media.currentTime)}},{key:"seeking",get:function(){return this.media.seeking}},{key:"duration",get:function(){var e=parseInt(this.config.duration,10),t=Number(this.media.duration);return Number.isNaN(e)?t:e}},{key:"volume",set:function(e){var t=e;s.is.string(t)&&(t=Number(t)),s.is.number(t)||(t=r.get.call(this).volume),s.is.number(t)||(t=this.config.volume),t>1&&(t=1),t<0&&(t=0),this.config.volume=t,this.media.volume=t,this.muted&&t>0&&(this.muted=!1)},get:function(){return this.media.volume}},{key:"muted",set:function(e){var t=e;s.is.boolean(t)||(t=r.get.call(this).muted),s.is.boolean(t)||(t=this.config.muted),this.config.muted=t,this.media.muted=t},get:function(){return this.media.muted}},{key:"speed",set:function(e){var t=null;(t=s.is.number(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).speed:this.config.speed.selected)<.1&&(t=.1),t>2&&(t=2),this.config.speed.options.includes(t)?(this.config.speed.selected=t,this.media.playbackRate=t):this.console.warn("Unsupported speed ("+t+")")},get:function(){return this.media.playbackRate}},{key:"quality",set:function(e){var t=null;t=s.is.string(e)?e:s.is.number(r.get.call(this).speed)?r.get.call(this).quality:this.config.quality.selected,this.options.quality.includes(t)?(this.config.quality.selected=t,this.media.quality=t):this.console.warn("Unsupported quality option ("+t+")")},get:function(){return this.media.quality}},{key:"loop",set:function(e){var t=s.is.boolean(e)?e:this.config.loop.active;this.config.loop.active=t,this.media.loop=t},get:function(){return this.media.loop}},{key:"source",set:function(e){v.change.call(this,e)},get:function(){return this.media.currentSrc}},{key:"poster",set:function(e){"video"===this.type?s.is.string(e)&&this.media.setAttribute("poster",e):this.console.warn("Poster can only be set on HTML5 video")},get:function(){return"video"!==this.type?null:this.media.getAttribute("poster")}},{key:"autoplay",get:function(){return this.config.autoplay},set:function(e){var t=s.is.boolean(e)?e:this.config.autoplay;this.config.autoplay=t}},{key:"language",set:function(e){if(s.is.string(e)){var t=e.toLowerCase();this.captions.language!==t&&(this.toggleCaptions(!0),this.captions.language=t,s.dispatchEvent.call(this,this.media,"languagechange"),m.set.call(this),m.setup.call(this))}},get:function(){return this.captions.language}},{key:"pip",set:function(e){var t={pip:"picture-in-picture",inline:"inline"};if(a.pip){var i=s.is.boolean(e)?e:this.pip===t.inline;this.media.webkitSetPresentationMode(i?t.pip:t.inline)}},get:function(){return a.pip?this.media.webkitPresentationMode:null}}]),e}()}); //# sourceMappingURL=plyr.js.map diff --git a/dist/plyr.js.map b/dist/plyr.js.map index ab134fe8..9725e034 100644 --- a/dist/plyr.js.map +++ b/dist/plyr.js.map @@ -1 +1 @@ -{"version":3,"file":"plyr.js","sources":["src/js/storage.js","src/js/defaults.js","src/js/types.js","src/js/utils.js","src/js/support.js","src/js/fullscreen.js","src/js/listeners.js","src/js/ui.js","src/js/controls.js","src/js/captions.js","src/js/plugins/youtube.js","src/js/plugins/vimeo.js","src/js/media.js","src/js/source.js","src/js/plyr.js"],"sourcesContent":["// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\n// Get contents of local storage\nfunction get() {\n const store = window.localStorage.getItem(this.config.storage.key);\n\n if (utils.is.empty(store)) {\n return {};\n }\n\n return JSON.parse(store);\n}\n\n// Save a value back to local storage\nfunction set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n const storage = get.call(this);\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.config.storage.key, JSON.stringify(storage));\n}\n\n// Setup localStorage\nfunction setup() {\n let value = null;\n let storage = {};\n\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return storage;\n }\n\n // Clean up old volume\n // https://github.com/sampotts/plyr/issues/171\n window.localStorage.removeItem('plyr-volume');\n\n // load value from the current key\n value = window.localStorage.getItem(this.config.storage.key);\n\n if (!value) {\n // Key wasn't set (or had been cleared), move along\n } else if (/^\\d+(\\.\\d+)?$/.test(value)) {\n // If value is a number, it's probably volume from an older\n // version of this. See: https://github.com/sampotts/plyr/pull/313\n // Update the key to be JSON\n set({\n volume: parseFloat(value),\n });\n } else {\n // Assume it's JSON from this or a later version of plyr\n storage = JSON.parse(value);\n }\n\n return storage;\n}\n\nexport default { setup, set, get };\n","// Default config\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration\n displayDuration: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video to play\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Revert to poster on finish (HTML5 - will cause reload)\n showPosterOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/2.0.10/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 'default',\n options: ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'default'],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: window.navigator.language.split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n 'play',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed', 'loop'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime} secs',\n play: 'Play',\n pause: 'Pause',\n forward: 'Forward {seektime} secs',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n toggleMute: 'Toggle Mute',\n toggleCaptions: 'Toggle Captions',\n toggleFullscreen: 'Toggle Fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n none: 'None',\n disabled: 'Disabled',\n },\n\n // URLs\n urls: {\n vimeo: {\n api: 'https://player.vimeo.com/api/player.js',\n },\n youtube: {\n api: 'https://www.youtube.com/iframe_api',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n forward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n forward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n control: 'plyr__control',\n type: 'plyr--{0}',\n stopped: 'plyr--stopped',\n playing: 'plyr--playing',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr supported types\n// ==========================================================================\n\nconst types = {\n embed: ['youtube', 'vimeo'],\n html5: ['video', 'audio'],\n};\n\nexport default types;\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport support from './support';\n\nconst utils = {\n // Check variable types\n is: {\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.undefined(input) && Array.isArray(input);\n },\n nodeList(input) {\n return !this.undefined(input) && input instanceof NodeList;\n },\n htmlElement(input) {\n return !this.undefined(input) && input instanceof HTMLElement;\n },\n event(input) {\n return !this.undefined(input) && input instanceof Event;\n },\n cue(input) {\n return this.instanceOf(input, window.TextTrackCue) || this.instanceOf(input, window.VTTCue);\n },\n track(input) {\n return (\n !this.undefined(input) && (this.instanceOf(input, window.TextTrack) || typeof input.kind === 'string')\n );\n },\n undefined(input) {\n return input !== null && typeof input === 'undefined';\n },\n empty(input) {\n return (\n input === null ||\n typeof input === 'undefined' ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && input.length === 0) ||\n (this.object(input) && Object.keys(input).length === 0)\n );\n },\n getConstructor(input) {\n if (input === null || typeof input === 'undefined') {\n return null;\n }\n\n return input.constructor;\n },\n instanceOf(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Load an external script\n loadScript(url, callback) {\n // Check script is not already referenced\n if (document.querySelectorAll(`script[src=\"${url}\"]`).length) {\n return;\n }\n\n // Build the element\n const element = document.createElement('script');\n element.src = url;\n\n // Find first script\n const first = document.getElementsByTagName('script')[0];\n\n // Bind callback\n if (utils.is.function(callback)) {\n element.addEventListener('load', event => callback.call(null, event), false);\n }\n\n // Inject\n first.parentNode.insertBefore(element, first);\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (typeof url !== 'string') {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = typeof id === 'string';\n let isCached = false;\n\n function updateSprite(data) {\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once\n if (!hasId || !document.querySelectorAll(`#${id}`).length) {\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n updateSprite.call(container, data.content);\n }\n }\n\n // ReSharper disable once InconsistentNaming\n const xhr = new XMLHttpRequest();\n\n // XHR for Chrome/Firefox/Opera/Safari\n if ('withCredentials' in xhr) {\n xhr.open('GET', url, true);\n } else {\n return;\n }\n\n // Once loaded, inject to container and body\n xhr.onload = () => {\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: xhr.responseText,\n })\n );\n }\n\n updateSprite.call(container, xhr.responseText);\n };\n\n xhr.send();\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Determine if we're in an iframe\n inFrame() {\n try {\n return window.self !== window.top;\n } catch (e) {\n return true;\n }\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Remove an element\n removeElement(element) {\n if (!utils.is.htmlElement(element) || !utils.is.htmlElement(element.parentNode)) {\n return null;\n }\n\n element.parentNode.removeChild(element);\n\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new \n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new \n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n Object.keys(attributes).forEach(key => {\n element.setAttribute(key, attributes[key]);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.htmlElement(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.htmlElement(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n forward: utils.getElement.call(this, this.config.selectors.buttons.forward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n };\n\n // Seek tooltip\n if (utils.is.htmlElement(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.console.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus() {\n const tabbables = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = tabbables[0];\n const last = tabbables[tabbables.length - 1];\n\n utils.on(\n this.elements.container,\n 'keydown',\n event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9 || !this.fullscreen.active) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n },\n false\n );\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle, passive, capture) {\n // Bail if no elements\n if (elements === null || utils.is.undefined(elements)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just capture boolean\n let options = utils.is.boolean(capture) ? capture : false;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive: utils.is.boolean(passive) ? passive : true,\n // Whether the listener is a capturing listener or not\n capture: utils.is.boolean(capture) ? capture : false,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type, bubbles, properties) {\n // Bail if no element\n if (!element || !type) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles: utils.is.boolean(bubbles) ? bubbles : false,\n detail: Object.assign({}, properties, {\n plyr: this instanceof Plyr ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // Bail if no target\n if (!utils.is.htmlElement(element)) {\n return;\n }\n\n // Get state\n const state = utils.is.boolean(input) ? input : !element.getAttribute('aria-pressed');\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n return (current / max * 100).toFixed(2);\n },\n\n // Deep extend/merge destination object with N more objects\n // http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/\n // Removed call to arguments.callee (used explicit function name instead)\n extend(...objects) {\n const { length } = objects;\n\n // Bail if nothing to merge\n if (!length) {\n return null;\n }\n\n // Return first if specified but nothing to merge\n if (length === 1) {\n return objects[0];\n }\n\n // First object is the destination\n let destination = Array.prototype.shift.call(objects);\n if (!utils.is.object(destination)) {\n destination = {};\n }\n\n // Loop through all objects to merge\n objects.forEach(source => {\n if (!utils.is.object(source)) {\n return;\n }\n\n Object.keys(source).forEach(property => {\n if (source[property] && source[property].constructor && source[property].constructor === Object) {\n destination[property] = destination[property] || {};\n utils.extend(destination[property], source[property]);\n } else {\n destination[property] = source[property];\n }\n });\n });\n\n return destination;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert object to URL parameters\n buildUrlParameters(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n transitionEnd: (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return typeof type === 'string' ? type : false;\n })(),\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, inline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const playsInline = browser.isIPhone && inline && support.inline;\n\n switch (type) {\n case 'video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'vimeo':\n api = true;\n ui = support.rangeInput && !browser.isIPhone;\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Local storage\n // We can't assume if local storage is present that we can use it\n storage: (() => {\n if (!('localStorage' in window)) {\n return false;\n }\n\n // Try to use it (it might be disabled, e.g. user is in private/porn mode)\n // see: https://github.com/sampotts/plyr/issues/131\n const test = '___test';\n try {\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n return true;\n } catch (e) {\n return false;\n }\n })(),\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n inline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Type specific checks\n if (this.type === 'video') {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.type === 'audio') {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // Remember a device can be moust + touch enabled\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEnd !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr fullscreen API\n// ==========================================================================\n\nimport utils from './utils';\n\n// Determine the prefix\nconst prefix = (() => {\n let value = false;\n\n if (utils.is.function(document.cancelFullScreen)) {\n value = '';\n } else {\n // Check for fullscreen support by vendor prefix\n ['webkit', 'o', 'moz', 'ms', 'khtml'].some(pre => {\n if (utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n } else if (utils.is.function(document.msExitFullscreen) && document.msFullscreenEnabled) {\n // Special case for MS (when isn't it?)\n value = 'ms';\n return true;\n }\n\n return false;\n });\n }\n\n return value;\n})();\n\n// Fullscreen API\nconst fullscreen = {\n // Get the prefix\n prefix,\n\n // Check if we can use it\n enabled:\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled,\n\n // Yet again Microsoft awesomeness,\n // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes\n eventType: prefix === 'ms' ? 'MSFullscreenChange' : `${prefix}fullscreenchange`,\n\n // Is an element fullscreen\n isFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n switch (prefix) {\n case '':\n return document.fullscreenElement === target;\n\n case 'moz':\n return document.mozFullScreenElement === target;\n\n default:\n return document[`${prefix}FullscreenElement`] === target;\n }\n },\n\n // Make an element fullscreen\n requestFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n return !prefix.length\n ? target.requestFullScreen()\n : target[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();\n },\n\n // Bail from fullscreen\n cancelFullScreen() {\n if (!fullscreen.enabled) {\n return false;\n }\n\n return !prefix.length\n ? document.cancelFullScreen()\n : document[prefix + (prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')]();\n },\n\n // Get the current element\n element() {\n if (!fullscreen.enabled) {\n return null;\n }\n\n return !prefix.length ? document.fullscreenElement : document[`${prefix}FullscreenElement`];\n },\n\n // Setup fullscreen\n setup() {\n if (!this.supported.ui || this.type === 'audio' || !this.config.fullscreen.enabled) {\n return;\n }\n\n // Check for native support\n const nativeSupport = fullscreen.enabled;\n\n if (nativeSupport || (this.config.fullscreen.fallback && !utils.inFrame())) {\n this.console.log(`${nativeSupport ? 'Native' : 'Fallback'} fullscreen enabled`);\n\n // Add styling hook to show button\n utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.enabled, true);\n } else {\n this.console.log('Fullscreen not supported and fallback disabled');\n }\n\n // Toggle state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, false);\n }\n\n // Trap focus in container\n utils.trapFocus.call(this);\n },\n};\n\nexport default fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport storage from './storage';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst listeners = {\n // Global listeners\n global() {\n let last = null;\n\n // Get the key code for an event\n const getKeyCode = event => (event.keyCode ? event.keyCode : event.which);\n\n // Handle key press\n const handleKey = event => {\n const code = getKeyCode(event);\n const pressed = event.type === 'keydown';\n const held = pressed && code === last;\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.currentTime = this.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.htmlElement(focused) && utils.matches(focused, this.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!held) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!held) {\n this.console.warn('togglePlay', event.type);\n this.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!held) {\n this.muted = 'toggle';\n }\n break;\n\n case 39:\n // Arrow forward\n this.forward();\n break;\n\n case 37:\n // Arrow back\n this.rewind();\n break;\n\n case 70:\n // F key\n this.toggleFullscreen();\n break;\n\n case 67:\n // C key\n if (!held) {\n this.toggleCaptions();\n }\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!fullscreen.enabled && this.fullscreen.active && code === 27) {\n this.toggleFullscreen();\n }\n\n // Store last code for next cycle\n last = code;\n } else {\n last = null;\n }\n };\n\n // Keyboard shortcuts\n if (this.config.keyboard.global) {\n utils.on(window, 'keydown keyup', handleKey, false);\n } else if (this.config.keyboard.focused) {\n utils.on(this.elements.container, 'keydown keyup', handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n window.setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(\n this.elements.container,\n 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen',\n event => {\n this.toggleControls(event);\n }\n );\n }\n\n // Handle user exiting fullscreen by escaping etc\n if (fullscreen.enabled) {\n utils.on(document, fullscreen.eventType, event => {\n this.toggleFullscreen(event);\n });\n }\n },\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event));\n\n // Display duration\n utils.on(this.media, 'durationchange loadedmetadata', event => ui.displayDuration.call(this, event));\n\n // Handle the media finishing\n utils.on(this.media, 'ended', () => {\n // Show poster on end\n if (this.type === 'video' && this.config.showPosterOnEnd) {\n // Restart\n this.restart();\n\n // Re-load media\n this.media.load();\n }\n });\n\n // Check for buffer progress\n utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event));\n\n // Handle native mute\n utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event));\n\n // Handle native play/pause\n utils.on(this.media, 'play pause ended', event => ui.checkPlaying.call(this, event));\n\n // Loading\n utils.on(this.media, 'waiting canplay seeked', event => ui.checkLoading.call(this, event));\n\n // Click video\n if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!wrapper) {\n return;\n }\n\n // Set cursor\n wrapper.style.cursor = 'pointer';\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.config.hideControls && support.touch && !this.media.paused) {\n return;\n }\n\n if (this.media.paused) {\n this.play();\n } else if (this.media.ended) {\n this.restart();\n this.play();\n } else {\n this.pause();\n }\n });\n }\n\n // Disable right click\n if (this.config.disableContextMenu) {\n utils.on(\n this.media,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false\n );\n }\n\n // Speed change\n utils.on(this.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this, 'speed');\n\n // Save to storage\n storage.set.call(this, { speed: this.speed });\n });\n\n // Quality change\n utils.on(this.media, 'qualitychange', () => {\n // Update UI\n controls.updateSetting.call(this, 'quality');\n\n // Save to storage\n storage.set.call(this, { quality: this.quality });\n });\n\n // Caption language change\n utils.on(this.media, 'languagechange', () => {\n // Save to storage\n storage.set.call(this, { language: this.language });\n });\n\n // Volume change\n utils.on(this.media, 'volumechange', () => {\n // Save to storage\n storage.set.call(this, { volume: this.volume, muted: this.muted });\n });\n\n // Captions toggle\n utils.on(this.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this, 'captions');\n\n // Save to storage\n storage.set.call(this, { captions: this.captions.enabled });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.media, this.config.events.concat(['keyup', 'keydown']).join(' '), event => {\n utils.dispatchEvent.call(this, this.elements.container, event.type, true);\n });\n },\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Trigger custom and default handlers\n const proxy = (event, handlerKey, defaultHandler) => {\n const customHandler = this.config.listeners[handlerKey];\n\n // Execute custom handler\n if (utils.is.function(customHandler)) {\n customHandler.call(this, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (!event.defaultPrevented && utils.is.function(defaultHandler)) {\n defaultHandler.call(this, event);\n }\n };\n\n // Click play/pause helper\n const togglePlay = () => {\n const play = this.togglePlay();\n\n // Determine which buttons\n const target = this.elements.buttons[play ? 'pause' : 'play'];\n\n // Transfer focus\n if (utils.is.htmlElement(target)) {\n target.focus();\n }\n };\n\n // Play\n utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.pause, 'click', event => proxy(event, 'pause', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.restart, 'click', event =>\n proxy(event, 'restart', () => {\n this.restart();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.rewind, 'click', event =>\n proxy(event, 'rewind', () => {\n this.rewind();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.forward, 'click', event =>\n proxy(event, 'forward', () => {\n this.forward();\n })\n );\n\n // Mute\n utils.on(this.elements.buttons.mute, 'click', event =>\n proxy(event, 'mute', () => {\n this.muted = !this.muted;\n })\n );\n\n // Captions\n utils.on(this.elements.buttons.captions, 'click', event =>\n proxy(event, 'captions', () => {\n this.toggleCaptions();\n })\n );\n\n // Fullscreen\n utils.on(this.elements.buttons.fullscreen, 'click', event =>\n proxy(event, 'fullscreen', () => {\n this.toggleFullscreen();\n })\n );\n\n // Picture-in-Picture\n utils.on(this.elements.buttons.pip, 'click', event =>\n proxy(event, 'pip', () => {\n this.pip = 'toggle';\n })\n );\n\n // Airplay\n utils.on(this.elements.buttons.airplay, 'click', event =>\n proxy(event, 'airplay', () => {\n this.airPlay();\n })\n );\n\n // Settings menu\n utils.on(this.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Click anywhere closes menu\n utils.on(document.documentElement, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Settings menu\n utils.on(this.elements.settings.form, 'click', event => {\n // Show tab in menu\n controls.showTab.call(this, event);\n\n // Settings menu items - use event delegation as items are added/removed\n // Settings - Language\n if (utils.matches(event.target, this.config.selectors.inputs.language)) {\n proxy(event, 'language', () => {\n this.toggleCaptions(true);\n this.language = event.target.value.toLowerCase();\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.quality)) {\n // Settings - Quality\n proxy(event, 'quality', () => {\n this.quality = event.target.value;\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.speed)) {\n // Settings - Speed\n proxy(event, 'speed', () => {\n this.speed = parseFloat(event.target.value);\n });\n } else if (utils.matches(event.target, this.config.selectors.buttons.loop)) {\n // Settings - Looping\n // TODO: use toggle buttons\n proxy(event, 'loop', () => {\n // TODO: This should be done in the method itself I think\n // var value = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type');\n\n this.console.warn('Set loop');\n });\n }\n });\n\n // Seek\n utils.on(this.elements.inputs.seek, inputEvent, event =>\n proxy(event, 'seek', () => {\n this.currentTime = event.target.value / event.target.max * this.duration;\n })\n );\n\n // Volume\n utils.on(this.elements.inputs.volume, inputEvent, event =>\n proxy(event, 'volume', () => {\n this.volume = event.target.value;\n })\n );\n\n // Polyfill for lower fill in for webkit\n if (browser.isWebkit) {\n utils.on(utils.getElements.call(this, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this, event.target);\n });\n }\n\n // Seek tooltip\n utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(this, event)\n );\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mouseenter mouseleave', event => {\n this.elements.controls.hover = event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Focus in/out on controls\n // TODO: Check we need capture here\n utils.on(\n this.elements.controls,\n 'focus blur',\n event => {\n this.toggleControls(event);\n },\n true\n );\n }\n\n // Mouse wheel for volume\n utils.on(\n this.elements.inputs.volume,\n 'wheel',\n event =>\n proxy(event, 'volume', () => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.decreaseVolume(step);\n direction = -1;\n } else {\n this.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.increaseVolume(step);\n direction = 1;\n } else {\n this.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) {\n event.preventDefault();\n }\n }),\n false\n );\n },\n};\n\nexport default listeners;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport utils from './utils';\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling\n listeners.media.call(this);\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.console.warn(`Basic support only for ${this.type}`);\n\n // Remove controls\n utils.removeElement.call(this, 'controls');\n\n // Remove large play\n utils.removeElement.call(this, 'buttons.play');\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.htmlElement(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n listeners.controls.call(this);\n }\n\n // If there's no controls, bail\n if (!utils.is.htmlElement(this.elements.controls)) {\n return;\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup fullscreen\n fullscreen.setup.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality options\n this.options.quality = [];\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n utils.dispatchEvent.call(this, this.media, 'ready');\n\n // Autoplay\n // TODO: check we still need this?\n /* if (this.isEmbed && this.config.autoplay) {\n this.play();\n } */\n },\n\n // Show the duration on metadataloaded\n displayDuration() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's only one time display, display duration there\n if (!this.elements.display.duration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.currentTime);\n }\n\n // If there's a duration element, update content\n if (this.elements.display.duration) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = this.config.i18n.play;\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (this.supported.ui) {\n if (utils.is.htmlElement(this.elements.buttons.play)) {\n this.elements.buttons.play.setAttribute('aria-label', label);\n }\n if (utils.is.htmlElement(this.elements.buttons.playLarge)) {\n this.elements.buttons.playLarge.setAttribute('aria-label', label);\n }\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.htmlElement(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n\n iframe.setAttribute('title', this.config.i18n.frameTitle.replace('{title}', title));\n }\n },\n\n // Check playing state\n checkPlaying() {\n utils.toggleClass(this.elements.container, this.config.classNames.playing, !this.paused);\n\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);\n\n this.toggleControls(this.paused);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.htmlElement(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update checkbox for mute state\n if (utils.is.htmlElement(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = event.type === 'waiting';\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update seek value and lower fill\n setRange(target, value) {\n if (!utils.is.htmlElement(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set value\n setProgress(target, input) {\n // Default to 0\n const value = !utils.is.undefined(input) ? input : 0;\n const progress = !utils.is.undefined(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.htmlElement(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.htmlElement(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update elements\n updateProgress(event) {\n if (!this.supported.ui) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n value = (() => {\n const { buffered } = this.media;\n\n if (buffered && buffered.length) {\n // HTML5\n return utils.getPercentage(buffered.end(0), this.duration);\n } else if (utils.is.number(buffered)) {\n // YouTube returns between 0 and 1\n return buffered * 100;\n }\n\n return 0;\n })();\n\n ui.setProgress.call(this, this.elements.display.buffer, value);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(value, element) {\n // Bail if there's no duration display\n if (!utils.is.htmlElement(element)) {\n return null;\n }\n\n // Fallback to 0\n const time = !Number.isNaN(value) ? value : 0;\n\n let secs = parseInt(time % 60, 10);\n let mins = parseInt((time / 60) % 60, 10);\n const hours = parseInt((time / 60 / 60) % 60, 10);\n\n // Do we need to display hours?\n const displayHours = parseInt((this.duration / 60 / 60) % 60, 10) > 0;\n\n // Ensure it's two digits. For example, 03 rather than 3.\n secs = `0${secs}`.slice(-2);\n mins = `0${mins}`.slice(-2);\n\n // Generate display\n const display = `${(displayHours ? `${hours}:` : '') + mins}:${secs}`;\n\n // Render\n // eslint-disable-next-line\n element.textContent = display;\n\n // Return for looping\n return display;\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Duration\n ui.updateTimeDisplay.call(this, this.currentTime, this.elements.display.currentTime);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid \n if (!utils.is.htmlElement(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Inject the stylesheet if needed\n if (!utils.is.htmlElement(this.elements.styleSheet)) {\n this.elements.styleSheet = utils.createElement('style');\n this.elements.container.appendChild(this.elements.styleSheet);\n }\n\n const styleSheet = this.elements.styleSheet.sheet;\n const percentage = range.value / range.max * 100;\n const selector = `#${range.id}::-webkit-slider-runnable-track`;\n const styles = `{ background-image: linear-gradient(to right, currentColor ${percentage}%, transparent ${percentage}%) }`;\n\n // Find old rule if it exists\n const index = Array.from(styleSheet.rules).findIndex(rule => rule.selectorText === selector);\n\n // Remove old rule\n if (index !== -1) {\n styleSheet.deleteRule(index);\n }\n\n // Insert new one\n styleSheet.insertRule([selector, styles].join(' '));\n },\n\n // Get icon URL\n getIconUrl() {\n return {\n url: this.config.iconUrl,\n absolute: this.config.iconUrl.indexOf('http') === 0 || (browser.isIE && !window.svg4everybody),\n };\n },\n\n // Create icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.absolute ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create \n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n })\n );\n\n // Create the to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // If the new `href` attribute is supported, use that\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttribute('href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add to \n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type) {\n let text = this.config.i18n[type];\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n return utils.createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n text\n );\n },\n\n // Create a badge\n createBadge(text) {\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text\n )\n );\n\n return badge;\n },\n\n // Create a
to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n const offset = (300 - padding) / 6;\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n this.media.style.transform = `translateY(-${offset}%)`;\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n };\n const params = utils.buildUrlParameters(options);\n const id = utils.parseVimeoId(player.embedId);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = `https://player.vimeo.com/video/${id}?${params}`;\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n player.media.appendChild(iframe);\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe);\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play();\n player.media.paused = false;\n };\n player.media.pause = () => {\n player.embed.pause();\n player.media.paused = true;\n };\n player.media.stop = () => {\n player.embed.stop();\n player.media.paused = true;\n };\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n speed = input;\n player.embed.setPlaybackRate(input);\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n player.embed.setVolume(input);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n muted = toggle;\n player.embed.setVolume(toggle ? 0 : player.config.volume);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n loop = utils.is.boolean(input) ? input : player.config.loop.active;\n player.embed.setLoop(loop);\n },\n });\n\n // Source\n let currentSrc;\n player.embed.getVideoUrl().then(value => {\n currentSrc = value;\n });\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Get available speeds\n if (player.config.controls.includes('settings') && player.config.settings.includes('speed')) {\n controls.setSpeedMenu.call(player);\n }\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.captions.tracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.set.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.htmlElement(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'play');\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n if (parseInt(data.percent, 10) === 1) {\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n // Rebuild UI\n window.setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport youtube from './plugins/youtube';\nimport vimeo from './plugins/vimeo';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.console.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n if (this.supported.ui) {\n // Check for picture-in-picture support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.type === 'video'\n );\n\n // Check for airplay support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.airplay.supported,\n support.airplay && this.isHTML5\n );\n\n // If there's no autoplay attribute, assume the video is stopped and add state class\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.config.autoplay);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch);\n }\n\n // Inject the player wrapper\n if (['video', 'youtube', 'vimeo'].includes(this.type)) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n }\n\n // Embeds\n if (this.isEmbed) {\n switch (this.type) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n }\n\n ui.setTitle.call(this);\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n Array.from(this.media.querySelectorAll('source')).forEach(utils.removeElement);\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.console.log('Cancelled network requests');\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport types from './types';\nimport utils from './utils';\nimport media from './media';\nimport ui from './ui';\nimport support from './support';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.console.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n media.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // TODO: Reset menus here\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.htmlElement(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type\n if ('type' in input) {\n this.type = input.type;\n\n // Get child type for video (it might be an embed)\n if (this.type === 'video') {\n const firstSource = input.sources[0];\n\n if ('type' in firstSource && types.embed.includes(firstSource.type)) {\n this.type = firstSource.type;\n }\n }\n }\n\n // Check for support\n this.supported = support.check(this.type, this.config.inline);\n\n // Create new markup\n switch (this.type) {\n case 'video':\n this.media = utils.createElement('video');\n break;\n\n case 'audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube':\n case 'vimeo':\n this.media = utils.createElement('div');\n this.embedId = input.sources[0].src;\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if ('poster' in input) {\n this.media.setAttribute('poster', input.poster);\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.inline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hooks\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.captions.active,\n this.supported.ui && this.captions.enabled\n );\n\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n },\n true\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.0.0\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport defaults from './defaults';\nimport types from './types';\nimport support from './support';\nimport utils from './utils';\n\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\nimport media from './media';\nimport storage from './storage';\nimport source from './source';\nimport ui from './ui';\n\n// Globals\nlet scrollPosition = {\n x: 0,\n y: 0,\n};\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n this.ready = false;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if (\n (window.jQuery && this.media instanceof jQuery) ||\n utils.is.nodeList(this.media) ||\n utils.is.array(this.media)\n ) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options,\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr'));\n } catch (e) {\n return null;\n }\n })()\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n enabled: null,\n tracks: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n this.console = {\n log() {},\n warn() {},\n error() {},\n };\n if (this.config.debug && 'console' in window) {\n this.console = {\n log: console.log, // eslint-disable-line\n warn: console.warn, // eslint-disable-line\n error: console.error, // eslint-disable-line\n };\n this.console.log('Debugging enabled');\n }\n\n // Log config options and support\n this.console.log('Config', this.config);\n this.console.log('Support', support);\n\n // We need an element to setup\n if (this.media === null || utils.is.undefined(this.media) || !utils.is.htmlElement(this.media)) {\n this.console.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.console.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.console.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n this.elements.original = this.media.cloneNode(true);\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Different setup based on type\n switch (type) {\n // TODO: Handle passing an iframe for true progressive enhancement\n // case 'iframe':\n case 'div':\n this.type = this.media.getAttribute('data-type');\n this.embedId = this.media.getAttribute('data-video-id');\n\n if (utils.is.empty(this.type)) {\n this.console.error('Setup failed: embed type missing');\n return;\n }\n\n if (utils.is.empty(this.embedId)) {\n this.console.error('Setup failed: video id missing');\n return;\n }\n\n // Clean up\n this.media.removeAttribute('data-type');\n this.media.removeAttribute('data-video-id');\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.inline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.console.error('Setup failed: unsupported type');\n return;\n }\n\n // Setup local storage for user settings\n storage.setup.call(this);\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.config.inline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Global listeners\n listeners.global.call(this);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.console.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * If the player is HTML5\n */\n get isHTML5() {\n return types.html5.includes(this.type);\n }\n\n /**\n * If the player is an embed - e.g. YouTube or Vimeo\n */\n get isEmbed() {\n return types.embed.includes(this.type);\n }\n\n /**\n * Play the media\n */\n play() {\n if ('play' in this.media) {\n this.media.play();\n }\n return this;\n }\n\n /**\n * Pause the media\n */\n pause() {\n if ('pause' in this.media) {\n this.media.pause();\n }\n return this;\n }\n\n get paused() {\n return this.media.paused;\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} toggle\n */\n togglePlay(toggle) {\n // True toggle if nothing passed\n if ((!utils.is.boolean(toggle) && this.media.paused) || toggle) {\n return this.play();\n }\n\n return this.pause();\n }\n\n /**\n * Stop playback\n */\n stop() {\n return this.restart().pause();\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n return this;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime.toFixed(4);\n\n // Logging\n this.console.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n get seeking() {\n return this.media.seeking;\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseInt(this.config.duration, 10);\n\n // True duration\n const realDuration = Number(this.media.duration);\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n ({ volume } = storage.get.call(this));\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume, reset muted state\n if (this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return this.media.volume;\n }\n\n // Increase volume\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Decrease volume\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Toggle mute\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = storage.get.call(this).muted;\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n get muted() {\n return this.media.muted;\n }\n\n // Playback speed\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ speed } = storage.get.call(this));\n } else {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.console.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n get speed() {\n return this.media.playbackRate;\n }\n\n // Set playback quality\n set quality(input) {\n let quality = null;\n\n if (utils.is.string(input)) {\n quality = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ quality } = storage.get.call(this));\n } else {\n quality = this.config.quality.selected;\n }\n\n if (!this.options.quality.includes(quality)) {\n this.console.warn(`Unsupported quality option (${quality})`);\n return;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n get quality() {\n return this.media.quality;\n }\n\n // Toggle loop\n // TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n get loop() {\n return this.media.loop;\n }\n\n // Media source\n set source(input) {\n source.change.call(this, input);\n }\n\n get source() {\n return this.media.currentSrc;\n }\n\n // Poster image\n set poster(input) {\n if (this.type !== 'video') {\n this.console.warn('Poster can only be set on HTML5 video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n }\n }\n\n get poster() {\n if (this.type !== 'video') {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n // Autoplay\n get autoplay() {\n return this.config.autoplay;\n }\n\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n // Toggle captions\n toggleCaptions(input) {\n // If there's no full support, or there's no caption toggle\n if (!this.supported.ui || !utils.is.htmlElement(this.elements.buttons.captions)) {\n return this;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input)\n ? input\n : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;\n\n // Nothing to change...\n if (this.captions.enabled === show) {\n return this;\n }\n\n // Set global\n this.captions.enabled = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.enabled);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.enabled);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.enabled ? 'captionsenabled' : 'captionsdisabled');\n\n // Allow chaining\n return this;\n }\n\n // Caption language\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // If nothing to change, bail\n if (this.captions.language === language) {\n return;\n }\n\n // Reset UI\n this.toggleCaptions(true);\n\n // Update config\n this.captions.language = language;\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n\n // Clear caption\n captions.set.call(this);\n\n // Re-run setup\n captions.setup.call(this);\n }\n\n get language() {\n return this.captions.language;\n }\n\n // Toggle fullscreen\n // Requires user input event\n toggleFullscreen(event) {\n // Check for native support\n if (fullscreen.enabled) {\n // If it's a fullscreen change event, update the UI\n if (utils.is.event(event) && event.type === fullscreen.eventType) {\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n } else {\n // Else it's a user request to enter or exit\n if (!this.fullscreen.active) {\n // Request full screen\n fullscreen.requestFullScreen(this.elements.container);\n } else {\n // Bail from fullscreen\n fullscreen.cancelFullScreen();\n }\n\n // Check if we're actually full screen (it could fail)\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n\n return this;\n }\n } else {\n // Otherwise, it's a simple toggle\n this.fullscreen.active = !this.fullscreen.active;\n\n // Add class hook\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.fullscreen.fallback,\n this.fullscreen.active\n );\n\n // Make sure we don't lose scroll position\n if (this.fullscreen.active) {\n scrollPosition = {\n x: window.pageXOffset || 0,\n y: window.pageYOffset || 0,\n };\n } else {\n window.scrollTo(scrollPosition.x, scrollPosition.y);\n }\n\n // Bind/unbind escape key\n document.body.style.overflow = this.fullscreen.active ? 'hidden' : '';\n }\n\n // Set button state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active);\n }\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.fullscreen.active ? 'enterfullscreen' : 'exitfullscreen');\n\n return this;\n }\n\n // Toggle picture-in-picture\n // TODO: update player with state, support, enabled\n // TODO: detect outside changes\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n // Trigger airplay\n // TODO: update player with state, support, enabled\n airplay() {\n // Bail if no support\n if (!support.airplay) {\n return this;\n }\n\n // Show dialog\n this.media.webkitShowPlaybackTargetPicker();\n\n return this;\n }\n\n // Show the player controls in fullscreen mode\n toggleControls(toggle) {\n const player = this;\n\n // We need controls of course...\n if (!utils.is.htmlElement(this.elements.controls)) {\n return player;\n }\n\n // Don't hide if config says not to, it's audio, or not ready or loading\n if (!this.supported.ui || !this.config.hideControls || this.type === 'audio') {\n return player;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n const loading = utils.hasClass(this.elements.container, this.config.classNames.loading);\n\n // Default to false if no boolean\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Whether to show controls\n show = ['mousemove', 'touchstart', 'mouseenter', 'focus'].includes(toggle.type);\n\n // Delay hiding on move events\n if (['mousemove', 'touchmove'].includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (toggle.type === 'focus') {\n delay = 3000;\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer every movement\n window.clearTimeout(this.timers.hover);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.media.paused || loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.media.paused || loading) {\n return player;\n }\n\n // Delay for hiding on touch\n if (support.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || !this.media.paused) {\n this.timers.hover = window.setTimeout(() => {\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, true);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n\n return this;\n }\n\n // Event listeners\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n return this;\n }\n\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n return this;\n }\n\n // Check for support\n supports(type) {\n return support.mime.call(this, type);\n }\n\n // Destroy an instance\n // Event listeners are removed when elements are removed\n // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n destroy(callback, soft = false) {\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n this.embedId = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove buttons\n if (this.elements.buttons && this.elements.buttons.play) {\n Array.from(this.elements.buttons.play).forEach(button => utils.removeElement(button));\n }\n\n // Remove others\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Replace the container with the original element provided\n const parent = this.elements.container.parentNode;\n\n if (utils.is.htmlElement(parent)) {\n parent.replaceChild(this.elements.original, this.elements.container);\n }\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Clear for GC\n this.elements = null;\n }\n };\n\n // Type specific stuff\n switch (this.type) {\n case 'youtube':\n // Clear timers\n window.clearInterval(this.timers.buffering);\n window.clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n this.embed.destroy();\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n this.embed.unload().then(done);\n\n // Vimeo does not always return\n window.setTimeout(done, 200);\n\n break;\n\n case 'video':\n case 'audio':\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n default:\n break;\n }\n }\n}\n\nexport default Plyr;\n"],"names":["get","store","window","localStorage","getItem","this","config","storage","key","utils","is","empty","JSON","parse","set","object","support","enabled","call","extend","setItem","stringify","defaults","navigator","language","split","types","input","getConstructor","Object","Number","isNaN","String","Boolean","Function","undefined","Array","isArray","NodeList","HTMLElement","Event","instanceOf","TextTrackCue","VTTCue","TextTrack","kind","string","array","nodeList","length","keys","constructor","document","documentMode","documentElement","style","test","userAgent","platform","url","callback","querySelectorAll","element","createElement","src","first","getElementsByTagName","function","addEventListener","event","parentNode","insertBefore","id","updateSprite","data","innerHTML","body","childNodes","hasId","container","setAttribute","cached","content","xhr","XMLHttpRequest","open","onload","responseText","send","prefix","Math","floor","random","self","top","e","elements","wrapper","targets","from","reverse","forEach","index","child","cloneNode","parent","sibling","nextSibling","appendChild","htmlElement","removeChild","target","type","attributes","text","setAttributes","textContent","lastChild","sel","existingAttributes","existing","selector","s","trim","className","replace","parts","value","charAt","class","toggle","contains","classList","prototype","Element","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","includes","querySelector","controls","getElement","selectors","buttons","getElements","play","pause","restart","rewind","forward","mute","pip","airplay","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","currentTime","seekTooltip","classNames","tooltip","error","console","warn","toggleNativeControls","focused","activeElement","tabbables","last","on","keyCode","_this","active","getFocusElement","shiftKey","focus","preventDefault","passive","capture","Node","toggleListener","events","options","boolean","passiveListeners","bubbles","properties","CustomEvent","assign","Plyr","dispatchEvent","state","getAttribute","current","max","toFixed","objects","destination","shift","source","property","match","RegExp","$2","number","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","ratio","getRatio","w","h","find","inline","api","ui","browser","getBrowser","playsInline","isIPhone","video","rangeInput","audio","removeItem","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","canPlayType","supported","defineProperty","range","transitionEnd","matchMedia","cancelFullScreen","some","pre","msExitFullscreen","msFullscreenEnabled","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","fullscreenElement","mozFullScreenElement","requestFullScreen","nativeSupport","fallback","inFrame","log","toggleClass","toggleState","trapFocus","setup","parseFloat","listeners","getKeyCode","which","handleKey","code","pressed","held","editable","stopPropagation","togglePlay","increaseVolume","decreaseVolume","muted","toggleFullscreen","toggleCaptions","keyboard","global","tabFocus","setTimeout","hideControls","toggleControls","eventType","timeUpdate","displayDuration","_this2","showPosterOnEnd","load","updateProgress","updateVolume","checkPlaying","checkLoading","clickToPlay","cursor","touch","paused","ended","disableContextMenu","updateSetting","speed","quality","concat","inputEvent","isIE","proxy","handlerKey","defaultHandler","customHandler","_this3","defaultPrevented","airPlay","toggleMenu","form","showTab","toLowerCase","loop","isWebkit","updateRangeFill","updateSeekTooltip","hover","inverted","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","uiSupported","isHTML5","removeAttribute","removeElement","inject","ready","updateTimeDisplay","label","i18n","title","playLarge","isEmbed","iframe","frameTitle","playing","stopped","setRange","loading","timers","nodeValue","getPercentage","buffered","end","setProgress","time","secs","parseInt","mins","hours","displayHours","slice","seeking","styleSheet","sheet","percentage","styles","rules","findIndex","rule","selectorText","deleteRule","insertRule","iconUrl","indexOf","svg4everybody","getIconUrl","iconPath","absolute","iconPrefix","icon","createElementNS","use","path","setAttributeNS","hidden","badge","menu","buttonType","attr","button","iconDefault","iconToggled","labelKey","control","getAttributesFromSelector","createIcon","createLabel","suffix","played","tooltips","percent","clientRect","getBoundingClientRect","visible","pageX","left","hasClass","setting","tab","tabs","pane","panes","list","filter","toggleTab","emptyElement","getBadge","createBadge","item","radio","createTextNode","getLabel","getLanguage","default","checked","option","textTracks","tracks","none","currentTrack","disabled","track","toUpperCase","unshift","_this4","insertAdjacentHTML","show","isMenuItem","isButton","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","transitions","reducedMotion","size","getTabSize","restore","propertyName","off","createButton","createRange","createProgress","createTime","inner","home","_this5","back","setSpeedMenu","loadSprite","seekTime","create","findElements","labels","_this6","setCaptionsMenu","insertAfter","setCurrentTrack","setCue","mode","activeCues","embed","enableTextTrack","cue","getCueAsHTML","caption","youtube","videoId","parseYouTubeId","embedId","containers","setAspectRatio","generateId","YT","loadScript","urls","onYouTubeReadyCallbacks","push","onYouTubeIframeAPIReady","paddingBottom","player","Player","autoplay","location","hostname","href","instance","getPlaybackQuality","playbackRate","getPlaybackRate","playVideo","pauseVideo","stop","stopVideo","getDuration","getCurrentTime","seekTo","setPlaybackRate","setPlaybackQuality","setVolume","getVideoUrl","getAvailablePlaybackRates","getVideoData","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","build","setQualityMenu","getAvailableQualityLevels","vimeo","Vimeo","padding","offset","transform","params","buildUrlParameters","parseVimeoId","setCurrentTime","selected","setLoop","currentSrc","then","all","getVideoWidth","getVideoHeight","getAspectRatio","dimensions","getVideoTitle","getTextTracks","cues","stripHTML","seconds","isIos","isTouch","wrap","setTitle","blankVideo","insertElement","attribute","sources","cancelRequests","destroy","firstSource","check","crossorigin","poster","addStyleHook","insertElements","scrollPosition","jQuery","debug","plyr","original","tagName","hasAttribute","step","isFullScreen","pageXOffset","pageYOffset","scrollTo","x","y","overflow","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","clearTimeout","mime","soft","done","replaceChild","unload","html5","targetTime","fauxDuration","realDuration","change","states","webkitPresentationMode"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"plyr.js","sources":["src/js/storage.js","src/js/defaults.js","src/js/types.js","src/js/utils.js","src/js/support.js","src/js/fullscreen.js","src/js/listeners.js","src/js/ui.js","src/js/controls.js","src/js/captions.js","src/js/plugins/youtube.js","src/js/plugins/vimeo.js","src/js/media.js","src/js/source.js","src/js/plyr.js"],"sourcesContent":["// ==========================================================================\n// Plyr storage\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\n\n// Get contents of local storage\nfunction get() {\n const store = window.localStorage.getItem(this.config.storage.key);\n\n if (utils.is.empty(store)) {\n return {};\n }\n\n return JSON.parse(store);\n}\n\n// Save a value back to local storage\nfunction set(object) {\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return;\n }\n\n // Can only store objectst\n if (!utils.is.object(object)) {\n return;\n }\n\n // Get current storage\n const storage = get.call(this);\n\n // Update the working copy of the values\n utils.extend(storage, object);\n\n // Update storage\n window.localStorage.setItem(this.config.storage.key, JSON.stringify(storage));\n}\n\n// Setup localStorage\nfunction setup() {\n let value = null;\n let storage = {};\n\n // Bail if we don't have localStorage support or it's disabled\n if (!support.storage || !this.config.storage.enabled) {\n return storage;\n }\n\n // Clean up old volume\n // https://github.com/sampotts/plyr/issues/171\n window.localStorage.removeItem('plyr-volume');\n\n // load value from the current key\n value = window.localStorage.getItem(this.config.storage.key);\n\n if (!value) {\n // Key wasn't set (or had been cleared), move along\n } else if (/^\\d+(\\.\\d+)?$/.test(value)) {\n // If value is a number, it's probably volume from an older\n // version of this. See: https://github.com/sampotts/plyr/pull/313\n // Update the key to be JSON\n set({\n volume: parseFloat(value),\n });\n } else {\n // Assume it's JSON from this or a later version of plyr\n storage = JSON.parse(value);\n }\n\n return storage;\n}\n\nexport default { setup, set, get };\n","// Default config\nconst defaults = {\n // Disable\n enabled: true,\n\n // Custom media title\n title: '',\n\n // Logging to console\n debug: false,\n\n // Auto play (if supported)\n autoplay: false,\n\n // Default time to skip when rewind/fast forward\n seekTime: 10,\n\n // Default volume\n volume: 1,\n muted: false,\n\n // Pass a custom duration\n duration: null,\n\n // Display the media duration\n displayDuration: true,\n\n // Aspect ratio (for embeds)\n ratio: '16:9',\n\n // Click video to play\n clickToPlay: true,\n\n // Auto hide the controls\n hideControls: true,\n\n // Revert to poster on finish (HTML5 - will cause reload)\n showPosterOnEnd: false,\n\n // Disable the standard context menu\n disableContextMenu: true,\n\n // Sprite (for icons)\n loadSprite: true,\n iconPrefix: 'plyr',\n iconUrl: 'https://cdn.plyr.io/2.0.10/plyr.svg',\n\n // Blank video (used to prevent errors on source change)\n blankVideo: 'https://cdn.plyr.io/static/blank.mp4',\n\n // Quality default\n quality: {\n default: 'default',\n options: ['hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'default'],\n },\n\n // Set loops\n loop: {\n active: false,\n // start: null,\n // end: null,\n },\n\n // Speed default and options to display\n speed: {\n selected: 1,\n options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],\n },\n\n // Keyboard shortcut settings\n keyboard: {\n focused: true,\n global: false,\n },\n\n // Display tooltips\n tooltips: {\n controls: false,\n seek: true,\n },\n\n // Captions settings\n captions: {\n active: false,\n language: window.navigator.language.split('-')[0],\n },\n\n // Fullscreen settings\n fullscreen: {\n enabled: true, // Allow fullscreen?\n fallback: true, // Fallback for vintage browsers\n },\n\n // Local storage\n storage: {\n enabled: true,\n key: 'plyr',\n },\n\n // Default controls\n controls: [\n 'play-large',\n 'play',\n 'progress',\n 'current-time',\n 'mute',\n 'volume',\n 'captions',\n 'settings',\n 'pip',\n 'airplay',\n 'fullscreen',\n ],\n settings: ['captions', 'quality', 'speed', 'loop'],\n\n // Localisation\n i18n: {\n restart: 'Restart',\n rewind: 'Rewind {seektime} secs',\n play: 'Play',\n pause: 'Pause',\n forward: 'Forward {seektime} secs',\n seek: 'Seek',\n played: 'Played',\n buffered: 'Buffered',\n currentTime: 'Current time',\n duration: 'Duration',\n volume: 'Volume',\n toggleMute: 'Toggle Mute',\n toggleCaptions: 'Toggle Captions',\n toggleFullscreen: 'Toggle Fullscreen',\n frameTitle: 'Player for {title}',\n captions: 'Captions',\n settings: 'Settings',\n speed: 'Speed',\n quality: 'Quality',\n loop: 'Loop',\n start: 'Start',\n end: 'End',\n all: 'All',\n reset: 'Reset',\n none: 'None',\n disabled: 'Disabled',\n },\n\n // URLs\n urls: {\n vimeo: {\n api: 'https://player.vimeo.com/api/player.js',\n },\n youtube: {\n api: 'https://www.youtube.com/iframe_api',\n },\n },\n\n // Custom control listeners\n listeners: {\n seek: null,\n play: null,\n pause: null,\n restart: null,\n rewind: null,\n forward: null,\n mute: null,\n volume: null,\n captions: null,\n fullscreen: null,\n pip: null,\n airplay: null,\n speed: null,\n quality: null,\n loop: null,\n language: null,\n },\n\n // Events to watch and bubble\n events: [\n // Events to watch on HTML5 media elements and bubble\n // https://developer.mozilla.org/en/docs/Web/Guide/Events/Media_events\n 'ended',\n 'progress',\n 'stalled',\n 'playing',\n 'waiting',\n 'canplay',\n 'canplaythrough',\n 'loadstart',\n 'loadeddata',\n 'loadedmetadata',\n 'timeupdate',\n 'volumechange',\n 'play',\n 'pause',\n 'error',\n 'seeking',\n 'seeked',\n 'emptied',\n 'ratechange',\n 'cuechange',\n\n // Custom events\n 'enterfullscreen',\n 'exitfullscreen',\n 'captionsenabled',\n 'captionsdisabled',\n 'languagechange',\n 'controlshidden',\n 'controlsshown',\n 'ready',\n\n // YouTube\n 'statechange',\n 'qualitychange',\n 'qualityrequested',\n ],\n\n // Selectors\n // Change these to match your template if using custom HTML\n selectors: {\n editable: 'input, textarea, select, [contenteditable]',\n container: '.plyr',\n controls: {\n container: null,\n wrapper: '.plyr__controls',\n },\n labels: '[data-plyr]',\n buttons: {\n play: '[data-plyr=\"play\"]',\n pause: '[data-plyr=\"pause\"]',\n restart: '[data-plyr=\"restart\"]',\n rewind: '[data-plyr=\"rewind\"]',\n forward: '[data-plyr=\"fast-forward\"]',\n mute: '[data-plyr=\"mute\"]',\n captions: '[data-plyr=\"captions\"]',\n fullscreen: '[data-plyr=\"fullscreen\"]',\n pip: '[data-plyr=\"pip\"]',\n airplay: '[data-plyr=\"airplay\"]',\n settings: '[data-plyr=\"settings\"]',\n loop: '[data-plyr=\"loop\"]',\n },\n inputs: {\n seek: '[data-plyr=\"seek\"]',\n volume: '[data-plyr=\"volume\"]',\n speed: '[data-plyr=\"speed\"]',\n language: '[data-plyr=\"language\"]',\n quality: '[data-plyr=\"quality\"]',\n },\n display: {\n currentTime: '.plyr__time--current',\n duration: '.plyr__time--duration',\n buffer: '.plyr__progress--buffer',\n played: '.plyr__progress--played',\n loop: '.plyr__progress--loop',\n volume: '.plyr__volume--display',\n },\n progress: '.plyr__progress',\n captions: '.plyr__captions',\n menu: {\n quality: '.js-plyr__menu__list--quality',\n },\n },\n\n // Class hooks added to the player in different states\n classNames: {\n video: 'plyr__video-wrapper',\n embed: 'plyr__video-embed',\n control: 'plyr__control',\n type: 'plyr--{0}',\n stopped: 'plyr--stopped',\n playing: 'plyr--playing',\n loading: 'plyr--loading',\n hover: 'plyr--hover',\n tooltip: 'plyr__tooltip',\n hidden: 'plyr__sr-only',\n hideControls: 'plyr--hide-controls',\n isIos: 'plyr--is-ios',\n isTouch: 'plyr--is-touch',\n uiSupported: 'plyr--full-ui',\n menu: {\n value: 'plyr__menu__value',\n badge: 'plyr__badge',\n },\n captions: {\n enabled: 'plyr--captions-enabled',\n active: 'plyr--captions-active',\n },\n fullscreen: {\n enabled: 'plyr--fullscreen-enabled',\n fallback: 'plyr--fullscreen-fallback',\n },\n pip: {\n supported: 'plyr--pip-supported',\n active: 'plyr--pip-active',\n },\n airplay: {\n supported: 'plyr--airplay-supported',\n active: 'plyr--airplay-active',\n },\n tabFocus: 'plyr__tab-focus',\n },\n};\n\nexport default defaults;\n","// ==========================================================================\n// Plyr supported types\n// ==========================================================================\n\nconst types = {\n embed: ['youtube', 'vimeo'],\n html5: ['video', 'audio'],\n};\n\nexport default types;\n","// ==========================================================================\n// Plyr utils\n// ==========================================================================\n\nimport support from './support';\n\nconst utils = {\n // Check variable types\n is: {\n object(input) {\n return this.getConstructor(input) === Object;\n },\n number(input) {\n return this.getConstructor(input) === Number && !Number.isNaN(input);\n },\n string(input) {\n return this.getConstructor(input) === String;\n },\n boolean(input) {\n return this.getConstructor(input) === Boolean;\n },\n function(input) {\n return this.getConstructor(input) === Function;\n },\n array(input) {\n return !this.undefined(input) && Array.isArray(input);\n },\n nodeList(input) {\n return !this.undefined(input) && input instanceof NodeList;\n },\n htmlElement(input) {\n return !this.undefined(input) && input instanceof HTMLElement;\n },\n event(input) {\n return !this.undefined(input) && input instanceof Event;\n },\n cue(input) {\n return this.instanceOf(input, window.TextTrackCue) || this.instanceOf(input, window.VTTCue);\n },\n track(input) {\n return (\n !this.undefined(input) && (this.instanceOf(input, window.TextTrack) || typeof input.kind === 'string')\n );\n },\n undefined(input) {\n return input !== null && typeof input === 'undefined';\n },\n empty(input) {\n return (\n input === null ||\n typeof input === 'undefined' ||\n ((this.string(input) || this.array(input) || this.nodeList(input)) && input.length === 0) ||\n (this.object(input) && Object.keys(input).length === 0)\n );\n },\n getConstructor(input) {\n if (input === null || typeof input === 'undefined') {\n return null;\n }\n\n return input.constructor;\n },\n instanceOf(input, constructor) {\n return Boolean(input && constructor && input instanceof constructor);\n },\n },\n\n // Unfortunately, due to mixed support, UA sniffing is required\n getBrowser() {\n return {\n isIE: /* @cc_on!@ */ false || !!document.documentMode,\n isWebkit: 'WebkitAppearance' in document.documentElement.style && !/Edge/.test(navigator.userAgent),\n isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),\n isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),\n };\n },\n\n // Load an external script\n loadScript(url, callback) {\n // Check script is not already referenced\n if (document.querySelectorAll(`script[src=\"${url}\"]`).length) {\n return;\n }\n\n // Build the element\n const element = document.createElement('script');\n element.src = url;\n\n // Find first script\n const first = document.getElementsByTagName('script')[0];\n\n // Bind callback\n if (utils.is.function(callback)) {\n element.addEventListener('load', event => callback.call(null, event), false);\n }\n\n // Inject\n first.parentNode.insertBefore(element, first);\n },\n\n // Load an external SVG sprite\n loadSprite(url, id) {\n if (typeof url !== 'string') {\n return;\n }\n\n const prefix = 'cache-';\n const hasId = typeof id === 'string';\n let isCached = false;\n\n function updateSprite(data) {\n // Inject content\n this.innerHTML = data;\n\n // Inject the SVG to the body\n document.body.insertBefore(this, document.body.childNodes[0]);\n }\n\n // Only load once\n if (!hasId || !document.querySelectorAll(`#${id}`).length) {\n // Create container\n const container = document.createElement('div');\n container.setAttribute('hidden', '');\n\n if (hasId) {\n container.setAttribute('id', id);\n }\n\n // Check in cache\n if (support.storage) {\n const cached = window.localStorage.getItem(prefix + id);\n isCached = cached !== null;\n\n if (isCached) {\n const data = JSON.parse(cached);\n updateSprite.call(container, data.content);\n }\n }\n\n // ReSharper disable once InconsistentNaming\n const xhr = new XMLHttpRequest();\n\n // XHR for Chrome/Firefox/Opera/Safari\n if ('withCredentials' in xhr) {\n xhr.open('GET', url, true);\n } else {\n return;\n }\n\n // Once loaded, inject to container and body\n xhr.onload = () => {\n if (support.storage) {\n window.localStorage.setItem(\n prefix + id,\n JSON.stringify({\n content: xhr.responseText,\n })\n );\n }\n\n updateSprite.call(container, xhr.responseText);\n };\n\n xhr.send();\n }\n },\n\n // Generate a random ID\n generateId(prefix) {\n return `${prefix}-${Math.floor(Math.random() * 10000)}`;\n },\n\n // Determine if we're in an iframe\n inFrame() {\n try {\n return window.self !== window.top;\n } catch (e) {\n return true;\n }\n },\n\n // Wrap an element\n wrap(elements, wrapper) {\n // Convert `elements` to an array, if necessary.\n const targets = elements.length ? elements : [elements];\n\n // Loops backwards to prevent having to clone the wrapper on the\n // first element (see `child` below).\n Array.from(targets)\n .reverse()\n .forEach((element, index) => {\n const child = index > 0 ? wrapper.cloneNode(true) : wrapper;\n\n // Cache the current parent and sibling.\n const parent = element.parentNode;\n const sibling = element.nextSibling;\n\n // Wrap the element (is automatically removed from its current\n // parent).\n child.appendChild(element);\n\n // If the element had a sibling, insert the wrapper before\n // the sibling to maintain the HTML structure; otherwise, just\n // append it to the parent.\n if (sibling) {\n parent.insertBefore(child, sibling);\n } else {\n parent.appendChild(child);\n }\n });\n },\n\n // Remove an element\n removeElement(element) {\n if (!utils.is.htmlElement(element) || !utils.is.htmlElement(element.parentNode)) {\n return null;\n }\n\n element.parentNode.removeChild(element);\n\n return element;\n },\n\n // Inaert an element after another\n insertAfter(element, target) {\n target.parentNode.insertBefore(element, target.nextSibling);\n },\n\n // Create a DocumentFragment\n createElement(type, attributes, text) {\n // Create a new \n const element = document.createElement(type);\n\n // Set all passed attributes\n if (utils.is.object(attributes)) {\n utils.setAttributes(element, attributes);\n }\n\n // Add text node\n if (utils.is.string(text)) {\n element.textContent = text;\n }\n\n // Return built element\n return element;\n },\n\n // Insert a DocumentFragment\n insertElement(type, parent, attributes, text) {\n // Inject the new \n parent.appendChild(utils.createElement(type, attributes, text));\n },\n\n // Remove all child elements\n emptyElement(element) {\n let { length } = element.childNodes;\n\n while (length > 0) {\n element.removeChild(element.lastChild);\n length -= 1;\n }\n },\n\n // Set attributes\n setAttributes(element, attributes) {\n Object.keys(attributes).forEach(key => {\n element.setAttribute(key, attributes[key]);\n });\n },\n\n // Get an attribute object from a string selector\n getAttributesFromSelector(sel, existingAttributes) {\n // For example:\n // '.test' to { class: 'test' }\n // '#test' to { id: 'test' }\n // '[data-test=\"test\"]' to { 'data-test': 'test' }\n\n if (!utils.is.string(sel) || utils.is.empty(sel)) {\n return {};\n }\n\n const attributes = {};\n const existing = existingAttributes;\n\n sel.split(',').forEach(s => {\n // Remove whitespace\n const selector = s.trim();\n const className = selector.replace('.', '');\n const stripped = selector.replace(/[[\\]]/g, '');\n\n // Get the parts and value\n const parts = stripped.split('=');\n const key = parts[0];\n const value = parts.length > 1 ? parts[1].replace(/[\"']/g, '') : '';\n\n // Get the first character\n const start = selector.charAt(0);\n\n switch (start) {\n case '.':\n // Add to existing classname\n if (utils.is.object(existing) && utils.is.string(existing.class)) {\n existing.class += ` ${className}`;\n }\n\n attributes.class = className;\n break;\n\n case '#':\n // ID selector\n attributes.id = selector.replace('#', '');\n break;\n\n case '[':\n // Attribute selector\n attributes[key] = value;\n\n break;\n\n default:\n break;\n }\n });\n\n return attributes;\n },\n\n // Toggle class on an element\n toggleClass(element, className, toggle) {\n if (utils.is.htmlElement(element)) {\n const contains = element.classList.contains(className);\n\n element.classList[toggle ? 'add' : 'remove'](className);\n\n return (toggle && !contains) || (!toggle && contains);\n }\n\n return null;\n },\n\n // Has class name\n hasClass(element, className) {\n return utils.is.htmlElement(element) && element.classList.contains(className);\n },\n\n // Element matches selector\n matches(element, selector) {\n const prototype = { Element };\n\n function match() {\n return Array.from(document.querySelectorAll(selector)).includes(this);\n }\n\n const matches =\n prototype.matches ||\n prototype.webkitMatchesSelector ||\n prototype.mozMatchesSelector ||\n prototype.msMatchesSelector ||\n match;\n\n return matches.call(element, selector);\n },\n\n // Find all elements\n getElements(selector) {\n return this.elements.container.querySelectorAll(selector);\n },\n\n // Find a single element\n getElement(selector) {\n return this.elements.container.querySelector(selector);\n },\n\n // Find the UI controls and store references in custom controls\n // TODO: Allow settings menus with custom controls\n findElements() {\n try {\n this.elements.controls = utils.getElement.call(this, this.config.selectors.controls.wrapper);\n\n // Buttons\n this.elements.buttons = {\n play: utils.getElements.call(this, this.config.selectors.buttons.play),\n pause: utils.getElement.call(this, this.config.selectors.buttons.pause),\n restart: utils.getElement.call(this, this.config.selectors.buttons.restart),\n rewind: utils.getElement.call(this, this.config.selectors.buttons.rewind),\n forward: utils.getElement.call(this, this.config.selectors.buttons.forward),\n mute: utils.getElement.call(this, this.config.selectors.buttons.mute),\n pip: utils.getElement.call(this, this.config.selectors.buttons.pip),\n airplay: utils.getElement.call(this, this.config.selectors.buttons.airplay),\n settings: utils.getElement.call(this, this.config.selectors.buttons.settings),\n captions: utils.getElement.call(this, this.config.selectors.buttons.captions),\n fullscreen: utils.getElement.call(this, this.config.selectors.buttons.fullscreen),\n };\n\n // Progress\n this.elements.progress = utils.getElement.call(this, this.config.selectors.progress);\n\n // Inputs\n this.elements.inputs = {\n seek: utils.getElement.call(this, this.config.selectors.inputs.seek),\n volume: utils.getElement.call(this, this.config.selectors.inputs.volume),\n };\n\n // Display\n this.elements.display = {\n buffer: utils.getElement.call(this, this.config.selectors.display.buffer),\n duration: utils.getElement.call(this, this.config.selectors.display.duration),\n currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),\n };\n\n // Seek tooltip\n if (utils.is.htmlElement(this.elements.progress)) {\n this.elements.display.seekTooltip = this.elements.progress.querySelector(\n `.${this.config.classNames.tooltip}`\n );\n }\n\n return true;\n } catch (error) {\n // Log it\n this.console.warn('It looks like there is a problem with your custom controls HTML', error);\n\n // Restore native video controls\n this.toggleNativeControls(true);\n\n return false;\n }\n },\n\n // Get the focused element\n getFocusElement() {\n let focused = document.activeElement;\n\n if (!focused || focused === document.body) {\n focused = null;\n } else {\n focused = document.querySelector(':focus');\n }\n\n return focused;\n },\n\n // Trap focus inside container\n trapFocus() {\n const tabbables = utils.getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');\n const first = tabbables[0];\n const last = tabbables[tabbables.length - 1];\n\n utils.on(\n this.elements.container,\n 'keydown',\n event => {\n // Bail if not tab key or not fullscreen\n if (event.key !== 'Tab' || event.keyCode !== 9 || !this.fullscreen.active) {\n return;\n }\n\n // Get the current focused element\n const focused = utils.getFocusElement();\n\n if (focused === last && !event.shiftKey) {\n // Move focus to first element that can be tabbed if Shift isn't used\n first.focus();\n event.preventDefault();\n } else if (focused === first && event.shiftKey) {\n // Move focus to last element that can be tabbed if Shift is used\n last.focus();\n event.preventDefault();\n }\n },\n false\n );\n },\n\n // Toggle event listener\n toggleListener(elements, event, callback, toggle, passive, capture) {\n // Bail if no elements\n if (elements === null || utils.is.undefined(elements)) {\n return;\n }\n\n // If a nodelist is passed, call itself on each node\n if (utils.is.nodeList(elements)) {\n // Create listener for each node\n Array.from(elements).forEach(element => {\n if (element instanceof Node) {\n utils.toggleListener.call(null, element, event, callback, toggle, passive, capture);\n }\n });\n\n return;\n }\n\n // Allow multiple events\n const events = event.split(' ');\n\n // Build options\n // Default to just capture boolean\n let options = utils.is.boolean(capture) ? capture : false;\n\n // If passive events listeners are supported\n if (support.passiveListeners) {\n options = {\n // Whether the listener can be passive (i.e. default never prevented)\n passive: utils.is.boolean(passive) ? passive : true,\n // Whether the listener is a capturing listener or not\n capture: utils.is.boolean(capture) ? capture : false,\n };\n }\n\n // If a single node is passed, bind the event listener\n events.forEach(type => {\n elements[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);\n });\n },\n\n // Bind event handler\n on(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, true, passive, capture);\n },\n\n // Unbind event handler\n off(element, events, callback, passive, capture) {\n utils.toggleListener(element, events, callback, false, passive, capture);\n },\n\n // Trigger event\n dispatchEvent(element, type, bubbles, properties) {\n // Bail if no element\n if (!element || !type) {\n return;\n }\n\n // Create and dispatch the event\n const event = new CustomEvent(type, {\n bubbles: utils.is.boolean(bubbles) ? bubbles : false,\n detail: Object.assign({}, properties, {\n plyr: this instanceof Plyr ? this : null,\n }),\n });\n\n // Dispatch the event\n element.dispatchEvent(event);\n },\n\n // Toggle aria-pressed state on a toggle button\n // http://www.ssbbartgroup.com/blog/how-not-to-misuse-aria-states-properties-and-roles\n toggleState(element, input) {\n // Bail if no target\n if (!utils.is.htmlElement(element)) {\n return;\n }\n\n // Get state\n const state = utils.is.boolean(input) ? input : !element.getAttribute('aria-pressed');\n\n // Set the attribute on target\n element.setAttribute('aria-pressed', state);\n },\n\n // Get percentage\n getPercentage(current, max) {\n if (current === 0 || max === 0 || Number.isNaN(current) || Number.isNaN(max)) {\n return 0;\n }\n return (current / max * 100).toFixed(2);\n },\n\n // Deep extend/merge destination object with N more objects\n // http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/\n // Removed call to arguments.callee (used explicit function name instead)\n extend(...objects) {\n const { length } = objects;\n\n // Bail if nothing to merge\n if (!length) {\n return null;\n }\n\n // Return first if specified but nothing to merge\n if (length === 1) {\n return objects[0];\n }\n\n // First object is the destination\n let destination = Array.prototype.shift.call(objects);\n if (!utils.is.object(destination)) {\n destination = {};\n }\n\n // Loop through all objects to merge\n objects.forEach(source => {\n if (!utils.is.object(source)) {\n return;\n }\n\n Object.keys(source).forEach(property => {\n if (source[property] && source[property].constructor && source[property].constructor === Object) {\n destination[property] = destination[property] || {};\n utils.extend(destination[property], source[property]);\n } else {\n destination[property] = source[property];\n }\n });\n });\n\n return destination;\n },\n\n // Parse YouTube ID from URL\n parseYouTubeId(url) {\n const regex = /^.*(youtu.be\\/|v\\/|u\\/\\w\\/|embed\\/|watch\\?v=|&v=)([^#&?]*).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Parse Vimeo ID from URL\n parseVimeoId(url) {\n if (utils.is.number(Number(url))) {\n return url;\n }\n\n const regex = /^.*(vimeo.com\\/|video\\/)(\\d+).*/;\n return url.match(regex) ? RegExp.$2 : url;\n },\n\n // Convert object to URL parameters\n buildUrlParameters(input) {\n if (!utils.is.object(input)) {\n return '';\n }\n\n return Object.keys(input)\n .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(input[key])}`)\n .join('&');\n },\n\n // Remove HTML from a string\n stripHTML(source) {\n const fragment = document.createDocumentFragment();\n const element = document.createElement('div');\n fragment.appendChild(element);\n element.innerHTML = source;\n return fragment.firstChild.innerText;\n },\n\n // Get aspect ratio for dimensions\n getAspectRatio(width, height) {\n const getRatio = (w, h) => (h === 0 ? w : getRatio(h, w % h));\n const ratio = getRatio(width, height);\n return `${width / ratio}:${height / ratio}`;\n },\n\n // Get the transition end event\n transitionEnd: (() => {\n const element = document.createElement('span');\n\n const events = {\n WebkitTransition: 'webkitTransitionEnd',\n MozTransition: 'transitionend',\n OTransition: 'oTransitionEnd otransitionend',\n transition: 'transitionend',\n };\n\n const type = Object.keys(events).find(event => element.style[event] !== undefined);\n\n return typeof type === 'string' ? type : false;\n })(),\n};\n\nexport default utils;\n","// ==========================================================================\n// Plyr support checks\n// ==========================================================================\n\nimport utils from './utils';\n\n// Check for feature support\nconst support = {\n // Basic support\n audio: 'canPlayType' in document.createElement('audio'),\n video: 'canPlayType' in document.createElement('video'),\n\n // Check for support\n // Basic functionality vs full UI\n check(type, inline) {\n let api = false;\n let ui = false;\n const browser = utils.getBrowser();\n const playsInline = browser.isIPhone && inline && support.inline;\n\n switch (type) {\n case 'video':\n api = support.video;\n ui = api && support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'audio':\n api = support.audio;\n ui = api && support.rangeInput;\n break;\n\n case 'youtube':\n api = true;\n ui = support.rangeInput && (!browser.isIPhone || playsInline);\n break;\n\n case 'vimeo':\n api = true;\n ui = support.rangeInput && !browser.isIPhone;\n break;\n\n default:\n api = support.audio && support.video;\n ui = api && support.rangeInput;\n }\n\n return {\n api,\n ui,\n };\n },\n\n // Local storage\n // We can't assume if local storage is present that we can use it\n storage: (() => {\n if (!('localStorage' in window)) {\n return false;\n }\n\n // Try to use it (it might be disabled, e.g. user is in private/porn mode)\n // see: https://github.com/sampotts/plyr/issues/131\n const test = '___test';\n try {\n window.localStorage.setItem(test, test);\n window.localStorage.removeItem(test);\n return true;\n } catch (e) {\n return false;\n }\n })(),\n\n // Picture-in-picture support\n // Safari only currently\n pip: (() => {\n const browser = utils.getBrowser();\n return !browser.isIPhone && utils.is.function(utils.createElement('video').webkitSetPresentationMode);\n })(),\n\n // Airplay support\n // Safari only currently\n airplay: utils.is.function(window.WebKitPlaybackTargetAvailabilityEvent),\n\n // Inline playback support\n // https://webkit.org/blog/6784/new-video-policies-for-ios/\n inline: 'playsInline' in document.createElement('video'),\n\n // Check for mime type support against a player instance\n // Credits: http://diveintohtml5.info/everything.html\n // Related: http://www.leanbackplayer.com/test/h5mt.html\n mime(type) {\n const { media } = this;\n\n try {\n // Bail if no checking function\n if (!utils.is.function(media.canPlayType)) {\n return false;\n }\n\n // Type specific checks\n if (this.type === 'video') {\n switch (type) {\n case 'video/webm':\n return media.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/no/, '');\n\n case 'video/mp4':\n return media.canPlayType('video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"').replace(/no/, '');\n\n case 'video/ogg':\n return media.canPlayType('video/ogg; codecs=\"theora\"').replace(/no/, '');\n\n default:\n return false;\n }\n } else if (this.type === 'audio') {\n switch (type) {\n case 'audio/mpeg':\n return media.canPlayType('audio/mpeg;').replace(/no/, '');\n\n case 'audio/ogg':\n return media.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/no/, '');\n\n case 'audio/wav':\n return media.canPlayType('audio/wav; codecs=\"1\"').replace(/no/, '');\n\n default:\n return false;\n }\n }\n } catch (e) {\n return false;\n }\n\n // If we got this far, we're stuffed\n return false;\n },\n\n // Check for textTracks support\n textTracks: 'textTracks' in document.createElement('video'),\n\n // Check for passive event listener support\n // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n // https://www.youtube.com/watch?v=NPM6172J22g\n passiveListeners: (() => {\n // Test via a getter in the options object to see if the passive property is accessed\n let supported = false;\n try {\n const options = Object.defineProperty({}, 'passive', {\n get() {\n supported = true;\n return null;\n },\n });\n window.addEventListener('test', null, options);\n } catch (e) {\n // Do nothing\n }\n\n return supported;\n })(),\n\n // Sliders\n rangeInput: (() => {\n const range = document.createElement('input');\n range.type = 'range';\n return range.type === 'range';\n })(),\n\n // Touch\n // Remember a device can be moust + touch enabled\n touch: 'ontouchstart' in document.documentElement,\n\n // Detect transitions support\n transitions: utils.transitionEnd !== false,\n\n // Reduced motion iOS & MacOS setting\n // https://webkit.org/blog/7551/responsive-design-for-motion/\n reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches,\n};\n\nexport default support;\n","// ==========================================================================\n// Plyr fullscreen API\n// ==========================================================================\n\nimport utils from './utils';\n\n// Determine the prefix\nconst prefix = (() => {\n let value = false;\n\n if (utils.is.function(document.cancelFullScreen)) {\n value = '';\n } else {\n // Check for fullscreen support by vendor prefix\n ['webkit', 'o', 'moz', 'ms', 'khtml'].some(pre => {\n if (utils.is.function(document[`${pre}CancelFullScreen`])) {\n value = pre;\n return true;\n } else if (utils.is.function(document.msExitFullscreen) && document.msFullscreenEnabled) {\n // Special case for MS (when isn't it?)\n value = 'ms';\n return true;\n }\n\n return false;\n });\n }\n\n return value;\n})();\n\n// Fullscreen API\nconst fullscreen = {\n // Get the prefix\n prefix,\n\n // Check if we can use it\n enabled:\n document.fullscreenEnabled ||\n document.webkitFullscreenEnabled ||\n document.mozFullScreenEnabled ||\n document.msFullscreenEnabled,\n\n // Yet again Microsoft awesomeness,\n // Sometimes the prefix is 'ms', sometimes 'MS' to keep you on your toes\n eventType: prefix === 'ms' ? 'MSFullscreenChange' : `${prefix}fullscreenchange`,\n\n // Is an element fullscreen\n isFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n switch (prefix) {\n case '':\n return document.fullscreenElement === target;\n\n case 'moz':\n return document.mozFullScreenElement === target;\n\n default:\n return document[`${prefix}FullscreenElement`] === target;\n }\n },\n\n // Make an element fullscreen\n requestFullScreen(element) {\n if (!fullscreen.enabled) {\n return false;\n }\n\n const target = utils.is.undefined(element) ? document.body : element;\n\n return !prefix.length\n ? target.requestFullScreen()\n : target[prefix + (prefix === 'ms' ? 'RequestFullscreen' : 'RequestFullScreen')]();\n },\n\n // Bail from fullscreen\n cancelFullScreen() {\n if (!fullscreen.enabled) {\n return false;\n }\n\n return !prefix.length\n ? document.cancelFullScreen()\n : document[prefix + (prefix === 'ms' ? 'ExitFullscreen' : 'CancelFullScreen')]();\n },\n\n // Get the current element\n element() {\n if (!fullscreen.enabled) {\n return null;\n }\n\n return !prefix.length ? document.fullscreenElement : document[`${prefix}FullscreenElement`];\n },\n\n // Setup fullscreen\n setup() {\n if (!this.supported.ui || this.type === 'audio' || !this.config.fullscreen.enabled) {\n return;\n }\n\n // Check for native support\n const nativeSupport = fullscreen.enabled;\n\n if (nativeSupport || (this.config.fullscreen.fallback && !utils.inFrame())) {\n this.console.log(`${nativeSupport ? 'Native' : 'Fallback'} fullscreen enabled`);\n\n // Add styling hook to show button\n utils.toggleClass(this.elements.container, this.config.classNames.fullscreen.enabled, true);\n } else {\n this.console.log('Fullscreen not supported and fallback disabled');\n }\n\n // Toggle state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, false);\n }\n\n // Trap focus in container\n utils.trapFocus.call(this);\n },\n};\n\nexport default fullscreen;\n","// ==========================================================================\n// Plyr Event Listeners\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport storage from './storage';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst listeners = {\n // Global listeners\n global() {\n let last = null;\n\n // Get the key code for an event\n const getKeyCode = event => (event.keyCode ? event.keyCode : event.which);\n\n // Handle key press\n const handleKey = event => {\n const code = getKeyCode(event);\n const pressed = event.type === 'keydown';\n const held = pressed && code === last;\n\n // If the event is bubbled from the media element\n // Firefox doesn't get the keycode for whatever reason\n if (!utils.is.number(code)) {\n return;\n }\n\n // Seek by the number keys\n const seekByKey = () => {\n // Divide the max duration into 10th's and times by the number value\n this.currentTime = this.duration / 10 * (code - 48);\n };\n\n // Handle the key on keydown\n // Reset on keyup\n if (pressed) {\n // Which keycodes should we prevent default\n const preventDefault = [\n 48,\n 49,\n 50,\n 51,\n 52,\n 53,\n 54,\n 56,\n 57,\n 32,\n 75,\n 38,\n 40,\n 77,\n 39,\n 37,\n 70,\n 67,\n 73,\n 76,\n 79,\n ];\n\n // Check focused element\n // and if the focused element is not editable (e.g. text input)\n // and any that accept key input http://webaim.org/techniques/keyboard/\n const focused = utils.getFocusElement();\n if (utils.is.htmlElement(focused) && utils.matches(focused, this.config.selectors.editable)) {\n return;\n }\n\n // If the code is found prevent default (e.g. prevent scrolling for arrows)\n if (preventDefault.includes(code)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (code) {\n case 48:\n case 49:\n case 50:\n case 51:\n case 52:\n case 53:\n case 54:\n case 55:\n case 56:\n case 57:\n // 0-9\n if (!held) {\n seekByKey();\n }\n break;\n\n case 32:\n case 75:\n // Space and K key\n if (!held) {\n this.togglePlay();\n }\n break;\n\n case 38:\n // Arrow up\n this.increaseVolume(0.1);\n break;\n\n case 40:\n // Arrow down\n this.decreaseVolume(0.1);\n break;\n\n case 77:\n // M key\n if (!held) {\n this.muted = !this.muted;\n }\n break;\n\n case 39:\n // Arrow forward\n this.forward();\n break;\n\n case 37:\n // Arrow back\n this.rewind();\n break;\n\n case 70:\n // F key\n this.toggleFullscreen();\n break;\n\n case 67:\n // C key\n if (!held) {\n this.toggleCaptions();\n }\n break;\n\n case 76:\n // L key\n this.loop = !this.loop;\n break;\n\n /* case 73:\n this.setLoop('start');\n break;\n\n case 76:\n this.setLoop();\n break;\n\n case 79:\n this.setLoop('end');\n break; */\n\n default:\n break;\n }\n\n // Escape is handle natively when in full screen\n // So we only need to worry about non native\n if (!fullscreen.enabled && this.fullscreen.active && code === 27) {\n this.toggleFullscreen();\n }\n\n // Store last code for next cycle\n last = code;\n } else {\n last = null;\n }\n };\n\n // Keyboard shortcuts\n if (this.config.keyboard.global) {\n utils.on(window, 'keydown keyup', handleKey, false);\n } else if (this.config.keyboard.focused) {\n utils.on(this.elements.container, 'keydown keyup', handleKey, false);\n }\n\n // Detect tab focus\n // Remove class on blur/focusout\n utils.on(this.elements.container, 'focusout', event => {\n utils.toggleClass(event.target, this.config.classNames.tabFocus, false);\n });\n\n // Add classname to tabbed elements\n utils.on(this.elements.container, 'keydown', event => {\n if (event.keyCode !== 9) {\n return;\n }\n\n // Delay the adding of classname until the focus has changed\n // This event fires before the focusin event\n window.setTimeout(() => {\n utils.toggleClass(utils.getFocusElement(), this.config.classNames.tabFocus, true);\n }, 0);\n });\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Toggle controls on mouse events and entering fullscreen\n utils.on(\n this.elements.container,\n 'mouseenter mouseleave mousemove touchstart touchend touchcancel touchmove enterfullscreen',\n event => {\n this.toggleControls(event);\n }\n );\n }\n\n // Handle user exiting fullscreen by escaping etc\n if (fullscreen.enabled) {\n utils.on(document, fullscreen.eventType, event => {\n this.toggleFullscreen(event);\n });\n }\n },\n\n // Listen for media events\n media() {\n // Time change on media\n utils.on(this.media, 'timeupdate seeking', event => ui.timeUpdate.call(this, event));\n\n // Display duration\n utils.on(this.media, 'durationchange loadedmetadata', event => ui.displayDuration.call(this, event));\n\n // Handle the media finishing\n utils.on(this.media, 'ended', () => {\n // Show poster on end\n if (this.type === 'video' && this.config.showPosterOnEnd) {\n // Restart\n this.restart();\n\n // Re-load media\n this.media.load();\n }\n });\n\n // Check for buffer progress\n utils.on(this.media, 'progress playing', event => ui.updateProgress.call(this, event));\n\n // Handle native mute\n utils.on(this.media, 'volumechange', event => ui.updateVolume.call(this, event));\n\n // Handle native play/pause\n utils.on(this.media, 'play pause ended', event => ui.checkPlaying.call(this, event));\n\n // Loading\n utils.on(this.media, 'waiting canplay seeked', event => ui.checkLoading.call(this, event));\n\n // Click video\n if (this.supported.ui && this.config.clickToPlay && this.type !== 'audio') {\n // Re-fetch the wrapper\n const wrapper = utils.getElement.call(this, `.${this.config.classNames.video}`);\n\n // Bail if there's no wrapper (this should never happen)\n if (!wrapper) {\n return;\n }\n\n // Set cursor\n wrapper.style.cursor = 'pointer';\n\n // On click play, pause ore restart\n utils.on(wrapper, 'click', () => {\n // Touch devices will just show controls (if we're hiding controls)\n if (this.config.hideControls && support.touch && !this.media.paused) {\n return;\n }\n\n if (this.media.paused) {\n this.play();\n } else if (this.media.ended) {\n this.restart();\n this.play();\n } else {\n this.pause();\n }\n });\n }\n\n // Disable right click\n if (this.config.disableContextMenu) {\n utils.on(\n this.media,\n 'contextmenu',\n event => {\n event.preventDefault();\n },\n false\n );\n }\n\n // Speed change\n utils.on(this.media, 'ratechange', () => {\n // Update UI\n controls.updateSetting.call(this, 'speed');\n\n // Save to storage\n storage.set.call(this, { speed: this.speed });\n });\n\n // Quality change\n utils.on(this.media, 'qualitychange', () => {\n // Update UI\n controls.updateSetting.call(this, 'quality');\n\n // Save to storage\n storage.set.call(this, { quality: this.quality });\n });\n\n // Caption language change\n utils.on(this.media, 'languagechange', () => {\n // Save to storage\n storage.set.call(this, { language: this.language });\n });\n\n // Volume change\n utils.on(this.media, 'volumechange', () => {\n // Save to storage\n storage.set.call(this, { volume: this.volume, muted: this.muted });\n });\n\n // Captions toggle\n utils.on(this.media, 'captionsenabled captionsdisabled', () => {\n // Update UI\n controls.updateSetting.call(this, 'captions');\n\n // Save to storage\n storage.set.call(this, { captions: this.captions.enabled });\n });\n\n // Proxy events to container\n // Bubble up key events for Edge\n utils.on(this.media, this.config.events.concat(['keyup', 'keydown']).join(' '), event => {\n utils.dispatchEvent.call(this, this.elements.container, event.type, true);\n });\n },\n\n // Listen for control events\n controls() {\n // IE doesn't support input event, so we fallback to change\n const inputEvent = browser.isIE ? 'change' : 'input';\n\n // Trigger custom and default handlers\n const proxy = (event, handlerKey, defaultHandler) => {\n const customHandler = this.config.listeners[handlerKey];\n\n // Execute custom handler\n if (utils.is.function(customHandler)) {\n customHandler.call(this, event);\n }\n\n // Only call default handler if not prevented in custom handler\n if (!event.defaultPrevented && utils.is.function(defaultHandler)) {\n defaultHandler.call(this, event);\n }\n };\n\n // Click play/pause helper\n const togglePlay = () => {\n const play = this.togglePlay();\n\n // Determine which buttons\n const target = this.elements.buttons[play ? 'pause' : 'play'];\n\n // Transfer focus\n if (utils.is.htmlElement(target)) {\n target.focus();\n }\n };\n\n // Play\n utils.on(this.elements.buttons.play, 'click', event => proxy(event, 'play', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.pause, 'click', event => proxy(event, 'pause', togglePlay));\n\n // Pause\n utils.on(this.elements.buttons.restart, 'click', event =>\n proxy(event, 'restart', () => {\n this.restart();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.rewind, 'click', event =>\n proxy(event, 'rewind', () => {\n this.rewind();\n })\n );\n\n // Rewind\n utils.on(this.elements.buttons.forward, 'click', event =>\n proxy(event, 'forward', () => {\n this.forward();\n })\n );\n\n // Mute\n utils.on(this.elements.buttons.mute, 'click', event =>\n proxy(event, 'mute', () => {\n this.muted = !this.muted;\n })\n );\n\n // Captions\n utils.on(this.elements.buttons.captions, 'click', event =>\n proxy(event, 'captions', () => {\n this.toggleCaptions();\n })\n );\n\n // Fullscreen\n utils.on(this.elements.buttons.fullscreen, 'click', event =>\n proxy(event, 'fullscreen', () => {\n this.toggleFullscreen();\n })\n );\n\n // Picture-in-Picture\n utils.on(this.elements.buttons.pip, 'click', event =>\n proxy(event, 'pip', () => {\n this.pip = 'toggle';\n })\n );\n\n // Airplay\n utils.on(this.elements.buttons.airplay, 'click', event =>\n proxy(event, 'airplay', () => {\n this.airPlay();\n })\n );\n\n // Settings menu\n utils.on(this.elements.buttons.settings, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Click anywhere closes menu\n utils.on(document.documentElement, 'click', event => {\n controls.toggleMenu.call(this, event);\n });\n\n // Settings menu\n utils.on(this.elements.settings.form, 'click', event => {\n // Show tab in menu\n controls.showTab.call(this, event);\n\n // Settings menu items - use event delegation as items are added/removed\n // Settings - Language\n if (utils.matches(event.target, this.config.selectors.inputs.language)) {\n proxy(event, 'language', () => {\n this.toggleCaptions(true);\n this.language = event.target.value.toLowerCase();\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.quality)) {\n // Settings - Quality\n proxy(event, 'quality', () => {\n this.quality = event.target.value;\n });\n } else if (utils.matches(event.target, this.config.selectors.inputs.speed)) {\n // Settings - Speed\n proxy(event, 'speed', () => {\n this.speed = parseFloat(event.target.value);\n });\n } else if (utils.matches(event.target, this.config.selectors.buttons.loop)) {\n // Settings - Looping\n // TODO: use toggle buttons\n proxy(event, 'loop', () => {\n // TODO: This should be done in the method itself I think\n // var value = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type');\n\n this.console.warn('Set loop');\n });\n }\n });\n\n // Seek\n utils.on(this.elements.inputs.seek, inputEvent, event =>\n proxy(event, 'seek', () => {\n this.currentTime = event.target.value / event.target.max * this.duration;\n })\n );\n\n // Volume\n utils.on(this.elements.inputs.volume, inputEvent, event =>\n proxy(event, 'volume', () => {\n this.volume = event.target.value;\n })\n );\n\n // Polyfill for lower fill in for webkit\n if (browser.isWebkit) {\n utils.on(utils.getElements.call(this, 'input[type=\"range\"]'), 'input', event => {\n controls.updateRangeFill.call(this, event.target);\n });\n }\n\n // Seek tooltip\n utils.on(this.elements.progress, 'mouseenter mouseleave mousemove', event =>\n controls.updateSeekTooltip.call(this, event)\n );\n\n // Toggle controls visibility based on mouse movement\n if (this.config.hideControls) {\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mouseenter mouseleave', event => {\n this.elements.controls.hover = event.type === 'mouseenter';\n });\n\n // Watch for cursor over controls so they don't hide when trying to interact\n utils.on(this.elements.controls, 'mousedown mouseup touchstart touchend touchcancel', event => {\n this.elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);\n });\n\n // Focus in/out on controls\n // TODO: Check we need capture here\n utils.on(\n this.elements.controls,\n 'focus blur',\n event => {\n this.toggleControls(event);\n },\n true\n );\n }\n\n // Mouse wheel for volume\n utils.on(\n this.elements.inputs.volume,\n 'wheel',\n event =>\n proxy(event, 'volume', () => {\n // Detect \"natural\" scroll - suppored on OS X Safari only\n // Other browsers on OS X will be inverted until support improves\n const inverted = event.webkitDirectionInvertedFromDevice;\n const step = 1 / 50;\n let direction = 0;\n\n // Scroll down (or up on natural) to decrease\n if (event.deltaY < 0 || event.deltaX > 0) {\n if (inverted) {\n this.decreaseVolume(step);\n direction = -1;\n } else {\n this.increaseVolume(step);\n direction = 1;\n }\n }\n\n // Scroll up (or down on natural) to increase\n if (event.deltaY > 0 || event.deltaX < 0) {\n if (inverted) {\n this.increaseVolume(step);\n direction = 1;\n } else {\n this.decreaseVolume(step);\n direction = -1;\n }\n }\n\n // Don't break page scrolling at max and min\n if ((direction === 1 && this.media.volume < 1) || (direction === -1 && this.media.volume > 0)) {\n event.preventDefault();\n }\n }),\n false\n );\n },\n};\n\nexport default listeners;\n","// ==========================================================================\n// Plyr UI\n// ==========================================================================\n\nimport utils from './utils';\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\n\nconst ui = {\n addStyleHook() {\n utils.toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);\n utils.toggleClass(this.elements.container, this.config.classNames.uiSupported, this.supported.ui);\n },\n\n // Toggle native HTML5 media controls\n toggleNativeControls(toggle) {\n if (toggle && this.isHTML5) {\n this.media.setAttribute('controls', '');\n } else {\n this.media.removeAttribute('controls');\n }\n },\n\n // Setup the UI\n build() {\n // Re-attach media element listeners\n // TODO: Use event bubbling\n listeners.media.call(this);\n\n // Don't setup interface if no support\n if (!this.supported.ui) {\n this.console.warn(`Basic support only for ${this.type}`);\n\n // Remove controls\n utils.removeElement.call(this, 'controls');\n\n // Remove large play\n utils.removeElement.call(this, 'buttons.play');\n\n // Restore native controls\n ui.toggleNativeControls.call(this, true);\n\n // Bail\n return;\n }\n\n // Inject custom controls if not present\n if (!utils.is.htmlElement(this.elements.controls)) {\n // Inject custom controls\n controls.inject.call(this);\n\n // Re-attach control listeners\n listeners.controls.call(this);\n }\n\n // If there's no controls, bail\n if (!utils.is.htmlElement(this.elements.controls)) {\n return;\n }\n\n // Remove native controls\n ui.toggleNativeControls.call(this);\n\n // Setup fullscreen\n fullscreen.setup.call(this);\n\n // Captions\n captions.setup.call(this);\n\n // Reset volume\n this.volume = null;\n\n // Reset mute state\n this.muted = null;\n\n // Reset speed\n this.speed = null;\n\n // Reset loop state\n this.loop = null;\n\n // Reset quality options\n this.options.quality = [];\n\n // Reset time display\n ui.timeUpdate.call(this);\n\n // Update the UI\n ui.checkPlaying.call(this);\n\n // Ready for API calls\n this.ready = true;\n\n // Ready event at end of execution stack\n utils.dispatchEvent.call(this, this.media, 'ready');\n\n // Autoplay\n // TODO: check we still need this?\n /* if (this.isEmbed && this.config.autoplay) {\n this.play();\n } */\n },\n\n // Show the duration on metadataloaded\n displayDuration() {\n if (!this.supported.ui) {\n return;\n }\n\n // If there's only one time display, display duration there\n if (!this.elements.display.duration && this.config.displayDuration && this.paused) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.currentTime);\n }\n\n // If there's a duration element, update content\n if (this.elements.display.duration) {\n ui.updateTimeDisplay.call(this, this.duration, this.elements.display.duration);\n }\n\n // Update the tooltip (if visible)\n controls.updateSeekTooltip.call(this);\n },\n\n // Setup aria attribute for play and iframe title\n setTitle() {\n // Find the current text\n let label = this.config.i18n.play;\n\n // If there's a media title set, use that for the label\n if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {\n label += `, ${this.config.title}`;\n\n // Set container label\n this.elements.container.setAttribute('aria-label', this.config.title);\n }\n\n // If there's a play button, set label\n if (this.supported.ui) {\n if (utils.is.htmlElement(this.elements.buttons.play)) {\n this.elements.buttons.play.setAttribute('aria-label', label);\n }\n if (utils.is.htmlElement(this.elements.buttons.playLarge)) {\n this.elements.buttons.playLarge.setAttribute('aria-label', label);\n }\n }\n\n // Set iframe title\n // https://github.com/sampotts/plyr/issues/124\n if (this.isEmbed) {\n const iframe = utils.getElement.call(this, 'iframe');\n\n if (!utils.is.htmlElement(iframe)) {\n return;\n }\n\n // Default to media type\n const title = !utils.is.empty(this.config.title) ? this.config.title : 'video';\n\n iframe.setAttribute('title', this.config.i18n.frameTitle.replace('{title}', title));\n }\n },\n\n // Check playing state\n checkPlaying() {\n utils.toggleClass(this.elements.container, this.config.classNames.playing, !this.paused);\n\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.paused);\n\n this.toggleControls(this.paused);\n },\n\n // Update volume UI and storage\n updateVolume() {\n if (!this.supported.ui) {\n return;\n }\n\n // Update range\n if (utils.is.htmlElement(this.elements.inputs.volume)) {\n ui.setRange.call(this, this.elements.inputs.volume, this.muted ? 0 : this.volume);\n }\n\n // Update checkbox for mute state\n if (utils.is.htmlElement(this.elements.buttons.mute)) {\n utils.toggleState(this.elements.buttons.mute, this.muted || this.volume === 0);\n }\n },\n\n // Check if media is loading\n checkLoading(event) {\n this.loading = event.type === 'waiting';\n\n // Clear timer\n clearTimeout(this.timers.loading);\n\n // Timer to prevent flicker when seeking\n this.timers.loading = setTimeout(() => {\n // Toggle container class hook\n utils.toggleClass(this.elements.container, this.config.classNames.loading, this.loading);\n\n // Show controls if loading, hide if done\n this.toggleControls(this.loading);\n }, this.loading ? 250 : 0);\n },\n\n // Update seek value and lower fill\n setRange(target, value) {\n if (!utils.is.htmlElement(target)) {\n return;\n }\n\n // eslint-disable-next-line\n target.value = value;\n\n // Webkit range fill\n controls.updateRangeFill.call(this, target);\n },\n\n // Set value\n setProgress(target, input) {\n // Default to 0\n const value = !utils.is.undefined(input) ? input : 0;\n const progress = !utils.is.undefined(target) ? target : this.elements.display.buffer;\n\n // Update value and label\n if (utils.is.htmlElement(progress)) {\n progress.value = value;\n\n // Update text label inside\n const label = progress.getElementsByTagName('span')[0];\n if (utils.is.htmlElement(label)) {\n label.childNodes[0].nodeValue = value;\n }\n }\n },\n\n // Update elements\n updateProgress(event) {\n if (!this.supported.ui) {\n return;\n }\n\n let value = 0;\n\n if (event) {\n switch (event.type) {\n // Video playing\n case 'timeupdate':\n case 'seeking':\n value = utils.getPercentage(this.currentTime, this.duration);\n\n // Set seek range value only if it's a 'natural' time event\n if (event.type === 'timeupdate') {\n ui.setRange.call(this, this.elements.inputs.seek, value);\n }\n\n break;\n\n // Check buffer status\n case 'playing':\n case 'progress':\n value = (() => {\n const { buffered } = this.media;\n\n if (buffered && buffered.length) {\n // HTML5\n return utils.getPercentage(buffered.end(0), this.duration);\n } else if (utils.is.number(buffered)) {\n // YouTube returns between 0 and 1\n return buffered * 100;\n }\n\n return 0;\n })();\n\n ui.setProgress.call(this, this.elements.display.buffer, value);\n\n break;\n\n default:\n break;\n }\n }\n },\n\n // Update the displayed time\n updateTimeDisplay(value, element) {\n // Bail if there's no duration display\n if (!utils.is.htmlElement(element)) {\n return null;\n }\n\n // Fallback to 0\n const time = !Number.isNaN(value) ? value : 0;\n\n let secs = parseInt(time % 60, 10);\n let mins = parseInt((time / 60) % 60, 10);\n const hours = parseInt((time / 60 / 60) % 60, 10);\n\n // Do we need to display hours?\n const displayHours = parseInt((this.duration / 60 / 60) % 60, 10) > 0;\n\n // Ensure it's two digits. For example, 03 rather than 3.\n secs = `0${secs}`.slice(-2);\n mins = `0${mins}`.slice(-2);\n\n // Generate display\n const display = `${(displayHours ? `${hours}:` : '') + mins}:${secs}`;\n\n // Render\n // eslint-disable-next-line\n element.textContent = display;\n\n // Return for looping\n return display;\n },\n\n // Handle time change event\n timeUpdate(event) {\n // Duration\n ui.updateTimeDisplay.call(this, this.currentTime, this.elements.display.currentTime);\n\n // Ignore updates while seeking\n if (event && event.type === 'timeupdate' && this.media.seeking) {\n return;\n }\n\n // Playing progress\n ui.updateProgress.call(this, event);\n },\n};\n\nexport default ui;\n","// ==========================================================================\n// Plyr controls\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst controls = {\n // Webkit polyfill for lower fill range\n updateRangeFill(target) {\n // WebKit only\n if (!browser.isWebkit) {\n return;\n }\n\n // Get range from event if event passed\n const range = utils.is.event(target) ? target.target : target;\n\n // Needs to be a valid \n if (!utils.is.htmlElement(range) || range.getAttribute('type') !== 'range') {\n return;\n }\n\n // Inject the stylesheet if needed\n if (!utils.is.htmlElement(this.elements.styleSheet)) {\n this.elements.styleSheet = utils.createElement('style');\n this.elements.container.appendChild(this.elements.styleSheet);\n }\n\n const styleSheet = this.elements.styleSheet.sheet;\n const percentage = range.value / range.max * 100;\n const selector = `#${range.id}::-webkit-slider-runnable-track`;\n const styles = `{ background-image: linear-gradient(to right, currentColor ${percentage}%, transparent ${percentage}%) }`;\n\n // Find old rule if it exists\n const index = Array.from(styleSheet.rules).findIndex(rule => rule.selectorText === selector);\n\n // Remove old rule\n if (index !== -1) {\n styleSheet.deleteRule(index);\n }\n\n // Insert new one\n styleSheet.insertRule([selector, styles].join(' '));\n },\n\n // Get icon URL\n getIconUrl() {\n return {\n url: this.config.iconUrl,\n absolute: this.config.iconUrl.indexOf('http') === 0 || (browser.isIE && !window.svg4everybody),\n };\n },\n\n // Create icon\n createIcon(type, attributes) {\n const namespace = 'http://www.w3.org/2000/svg';\n const iconUrl = controls.getIconUrl.call(this);\n const iconPath = `${!iconUrl.absolute ? iconUrl.url : ''}#${this.config.iconPrefix}`;\n\n // Create \n const icon = document.createElementNS(namespace, 'svg');\n utils.setAttributes(\n icon,\n utils.extend(attributes, {\n role: 'presentation',\n })\n );\n\n // Create the to reference sprite\n const use = document.createElementNS(namespace, 'use');\n const path = `${iconPath}-${type}`;\n\n // If the new `href` attribute is supported, use that\n // https://github.com/sampotts/plyr/issues/460\n // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href\n if ('href' in use) {\n use.setAttribute('href', path);\n } else {\n use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', path);\n }\n\n // Add to \n icon.appendChild(use);\n\n return icon;\n },\n\n // Create hidden text label\n createLabel(type) {\n let text = this.config.i18n[type];\n\n switch (type) {\n case 'pip':\n text = 'PIP';\n break;\n\n case 'airplay':\n text = 'AirPlay';\n break;\n\n default:\n break;\n }\n\n return utils.createElement(\n 'span',\n {\n class: this.config.classNames.hidden,\n },\n text\n );\n },\n\n // Create a badge\n createBadge(text) {\n const badge = utils.createElement('span', {\n class: this.config.classNames.menu.value,\n });\n\n badge.appendChild(\n utils.createElement(\n 'span',\n {\n class: this.config.classNames.menu.badge,\n },\n text\n )\n );\n\n return badge;\n },\n\n // Create a
to hide the standard controls and UI\n setAspectRatio(input) {\n const ratio = utils.is.string(input) ? input.split(':') : this.config.ratio.split(':');\n const padding = 100 / ratio[0] * ratio[1];\n const offset = (300 - padding) / 6;\n this.elements.wrapper.style.paddingBottom = `${padding}%`;\n this.media.style.transform = `translateY(-${offset}%)`;\n },\n\n // API Ready\n ready() {\n const player = this;\n\n // Get Vimeo params for the iframe\n const options = {\n loop: player.config.loop.active,\n autoplay: player.autoplay,\n byline: false,\n portrait: false,\n title: false,\n speed: true,\n transparent: 0,\n };\n const params = utils.buildUrlParameters(options);\n const id = utils.parseVimeoId(player.embedId);\n\n // Build an iframe\n const iframe = utils.createElement('iframe');\n const src = `https://player.vimeo.com/video/${id}?${params}`;\n iframe.setAttribute('src', src);\n iframe.setAttribute('allowfullscreen', '');\n player.media.appendChild(iframe);\n\n // Setup instance\n // https://github.com/vimeo/player.js\n player.embed = new window.Vimeo.Player(iframe);\n\n // Create a faux HTML5 API using the Vimeo API\n player.media.play = () => {\n player.embed.play();\n player.media.paused = false;\n };\n player.media.pause = () => {\n player.embed.pause();\n player.media.paused = true;\n };\n player.media.stop = () => {\n player.embed.stop();\n player.media.paused = true;\n };\n\n player.media.paused = true;\n player.media.currentTime = 0;\n\n // Seeking\n let { currentTime } = player.media;\n Object.defineProperty(player.media, 'currentTime', {\n get() {\n return currentTime;\n },\n set(time) {\n // Get current paused state\n // Vimeo will automatically play on seek\n const { paused } = player.media;\n\n // Set seeking flag\n player.media.seeking = true;\n\n // Trigger seeking\n utils.dispatchEvent.call(player, player.media, 'seeking');\n\n // Seek after events\n player.embed.setCurrentTime(time);\n\n // Restore pause state\n if (paused) {\n player.pause();\n }\n },\n });\n\n // Playback speed\n let speed = player.config.speed.selected;\n Object.defineProperty(player.media, 'playbackRate', {\n get() {\n return speed;\n },\n set(input) {\n speed = input;\n player.embed.setPlaybackRate(input);\n utils.dispatchEvent.call(player, player.media, 'ratechange');\n },\n });\n\n // Volume\n let { volume } = player.config;\n Object.defineProperty(player.media, 'volume', {\n get() {\n return volume;\n },\n set(input) {\n volume = input;\n player.embed.setVolume(input);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Muted\n let { muted } = player.config;\n Object.defineProperty(player.media, 'muted', {\n get() {\n return muted;\n },\n set(input) {\n const toggle = utils.is.boolean(input) ? input : false;\n muted = toggle;\n player.embed.setVolume(toggle ? 0 : player.config.volume);\n utils.dispatchEvent.call(player, player.media, 'volumechange');\n },\n });\n\n // Loop\n let { loop } = player.config;\n Object.defineProperty(player.media, 'loop', {\n get() {\n return loop;\n },\n set(input) {\n loop = utils.is.boolean(input) ? input : player.config.loop.active;\n player.embed.setLoop(loop);\n },\n });\n\n // Source\n let currentSrc;\n player.embed.getVideoUrl().then(value => {\n currentSrc = value;\n });\n Object.defineProperty(player.media, 'currentSrc', {\n get() {\n return currentSrc;\n },\n });\n\n // Set aspect ratio based on video size\n Promise.all([player.embed.getVideoWidth(), player.embed.getVideoHeight()]).then(dimensions => {\n const ratio = utils.getAspectRatio(dimensions[0], dimensions[1]);\n vimeo.setAspectRatio.call(this, ratio);\n });\n\n // Get available speeds\n if (player.config.controls.includes('settings') && player.config.settings.includes('speed')) {\n controls.setSpeedMenu.call(player);\n }\n\n // Get title\n player.embed.getVideoTitle().then(title => {\n player.config.title = title;\n });\n\n // Get current time\n player.embed.getCurrentTime().then(value => {\n currentTime = value;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n // Get duration\n player.embed.getDuration().then(value => {\n player.media.duration = value;\n utils.dispatchEvent.call(player, player.media, 'durationchange');\n });\n\n // Get captions\n player.embed.getTextTracks().then(tracks => {\n player.captions.tracks = tracks;\n captions.setup.call(player);\n });\n\n player.embed.on('cuechange', data => {\n let cue = null;\n\n if (data.cues.length) {\n cue = utils.stripHTML(data.cues[0].text);\n }\n\n captions.set.call(player, cue);\n });\n\n player.embed.on('loaded', () => {\n if (utils.is.htmlElement(player.embed.element) && player.supported.ui) {\n const frame = player.embed.element;\n\n // Fix keyboard focus issues\n // https://github.com/sampotts/plyr/issues/317\n frame.setAttribute('tabindex', -1);\n }\n });\n\n player.embed.on('play', () => {\n player.media.paused = false;\n utils.dispatchEvent.call(player, player.media, 'play');\n utils.dispatchEvent.call(player, player.media, 'playing');\n });\n\n player.embed.on('pause', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'pause');\n });\n\n player.embed.on('timeupdate', data => {\n player.media.seeking = false;\n currentTime = data.seconds;\n utils.dispatchEvent.call(player, player.media, 'timeupdate');\n });\n\n player.embed.on('progress', data => {\n player.media.buffered = data.percent;\n utils.dispatchEvent.call(player, player.media, 'progress');\n\n if (parseInt(data.percent, 10) === 1) {\n // Trigger event\n utils.dispatchEvent.call(player, player.media, 'canplaythrough');\n }\n });\n\n player.embed.on('seeked', () => {\n player.media.seeking = false;\n utils.dispatchEvent.call(player, player.media, 'seeked');\n utils.dispatchEvent.call(player, player.media, 'play');\n });\n\n player.embed.on('ended', () => {\n player.media.paused = true;\n utils.dispatchEvent.call(player, player.media, 'ended');\n });\n\n // Rebuild UI\n window.setTimeout(() => ui.build.call(player), 0);\n },\n};\n\nexport default vimeo;\n","// ==========================================================================\n// Plyr Media\n// ==========================================================================\n\nimport support from './support';\nimport utils from './utils';\nimport youtube from './plugins/youtube';\nimport vimeo from './plugins/vimeo';\nimport ui from './ui';\n\n// Sniff out the browser\nconst browser = utils.getBrowser();\n\nconst media = {\n // Setup media\n setup() {\n // If there's no media, bail\n if (!this.media) {\n this.console.warn('No media element found!');\n return;\n }\n\n // Add type class\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', this.type), true);\n\n // Add video class for embeds\n // This will require changes if audio embeds are added\n if (this.isEmbed) {\n utils.toggleClass(this.elements.container, this.config.classNames.type.replace('{0}', 'video'), true);\n }\n\n if (this.supported.ui) {\n // Check for picture-in-picture support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.pip.supported,\n support.pip && this.type === 'video'\n );\n\n // Check for airplay support\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.airplay.supported,\n support.airplay && this.isHTML5\n );\n\n // If there's no autoplay attribute, assume the video is stopped and add state class\n utils.toggleClass(this.elements.container, this.config.classNames.stopped, this.config.autoplay);\n\n // Add iOS class\n utils.toggleClass(this.elements.container, this.config.classNames.isIos, browser.isIos);\n\n // Add touch class\n utils.toggleClass(this.elements.container, this.config.classNames.isTouch, support.touch);\n }\n\n // Inject the player wrapper\n if (['video', 'youtube', 'vimeo'].includes(this.type)) {\n // Create the wrapper div\n this.elements.wrapper = utils.createElement('div', {\n class: this.config.classNames.video,\n });\n\n // Wrap the video in a container\n utils.wrap(this.media, this.elements.wrapper);\n }\n\n // Embeds\n if (this.isEmbed) {\n switch (this.type) {\n case 'youtube':\n youtube.setup.call(this);\n break;\n\n case 'vimeo':\n vimeo.setup.call(this);\n break;\n\n default:\n break;\n }\n }\n\n ui.setTitle.call(this);\n },\n\n // Cancel current network requests\n // See https://github.com/sampotts/plyr/issues/174\n cancelRequests() {\n if (!this.isHTML5) {\n return;\n }\n\n // Remove child sources\n Array.from(this.media.querySelectorAll('source')).forEach(utils.removeElement);\n\n // Set blank video src attribute\n // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error\n // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection\n this.media.setAttribute('src', this.config.blankVideo);\n\n // Load the new empty source\n // This will cancel existing requests\n // See https://github.com/sampotts/plyr/issues/174\n this.media.load();\n\n // Debugging\n this.console.log('Cancelled network requests');\n },\n};\n\nexport default media;\n","// ==========================================================================\n// Plyr source update\n// ==========================================================================\n\nimport types from './types';\nimport utils from './utils';\nimport media from './media';\nimport ui from './ui';\nimport support from './support';\n\nconst source = {\n // Add elements to HTML5 media (source, tracks, etc)\n insertElements(type, attributes) {\n if (utils.is.string(attributes)) {\n utils.insertElement(type, this.media, {\n src: attributes,\n });\n } else if (utils.is.array(attributes)) {\n attributes.forEach(attribute => {\n utils.insertElement(type, this.media, attribute);\n });\n }\n },\n\n // Update source\n // Sources are not checked for support so be careful\n change(input) {\n if (!utils.is.object(input) || !('sources' in input) || !input.sources.length) {\n this.console.warn('Invalid source format');\n return;\n }\n\n // Cancel current network requests\n media.cancelRequests.call(this);\n\n // Destroy instance and re-setup\n this.destroy.call(\n this,\n () => {\n // TODO: Reset menus here\n\n // Remove elements\n utils.removeElement(this.media);\n this.media = null;\n\n // Reset class name\n if (utils.is.htmlElement(this.elements.container)) {\n this.elements.container.removeAttribute('class');\n }\n\n // Set the type\n if ('type' in input) {\n this.type = input.type;\n\n // Get child type for video (it might be an embed)\n if (this.type === 'video') {\n const firstSource = input.sources[0];\n\n if ('type' in firstSource && types.embed.includes(firstSource.type)) {\n this.type = firstSource.type;\n }\n }\n }\n\n // Check for support\n this.supported = support.check(this.type, this.config.inline);\n\n // Create new markup\n switch (this.type) {\n case 'video':\n this.media = utils.createElement('video');\n break;\n\n case 'audio':\n this.media = utils.createElement('audio');\n break;\n\n case 'youtube':\n case 'vimeo':\n this.media = utils.createElement('div');\n this.embedId = input.sources[0].src;\n break;\n\n default:\n break;\n }\n\n // Inject the new element\n this.elements.container.appendChild(this.media);\n\n // Autoplay the new source?\n if (utils.is.boolean(input.autoplay)) {\n this.config.autoplay = input.autoplay;\n }\n\n // Set attributes for audio and video\n if (this.isHTML5) {\n if (this.config.crossorigin) {\n this.media.setAttribute('crossorigin', '');\n }\n if (this.config.autoplay) {\n this.media.setAttribute('autoplay', '');\n }\n if ('poster' in input) {\n this.media.setAttribute('poster', input.poster);\n }\n if (this.config.loop.active) {\n this.media.setAttribute('loop', '');\n }\n if (this.config.muted) {\n this.media.setAttribute('muted', '');\n }\n if (this.config.inline) {\n this.media.setAttribute('playsinline', '');\n }\n }\n\n // Restore class hooks\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.captions.active,\n this.supported.ui && this.captions.enabled\n );\n\n ui.addStyleHook.call(this);\n\n // Set new sources for html5\n if (this.isHTML5) {\n source.insertElements.call(this, 'source', input.sources);\n }\n\n // Set video title\n this.config.title = input.title;\n\n // Set up from scratch\n media.setup.call(this);\n\n // HTML5 stuff\n if (this.isHTML5) {\n // Setup captions\n if ('tracks' in input) {\n source.insertElements.call(this, 'track', input.tracks);\n }\n\n // Load HTML5 sources\n this.media.load();\n }\n\n // If HTML5 or embed but not fully supported, setupInterface and call ready now\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n // Setup interface\n ui.build.call(this);\n }\n },\n true\n );\n },\n};\n\nexport default source;\n","// ==========================================================================\n// Plyr\n// plyr.js v3.0.0\n// https://github.com/sampotts/plyr\n// License: The MIT License (MIT)\n// ==========================================================================\n\nimport defaults from './defaults';\nimport types from './types';\nimport support from './support';\nimport utils from './utils';\n\nimport captions from './captions';\nimport controls from './controls';\nimport fullscreen from './fullscreen';\nimport listeners from './listeners';\nimport media from './media';\nimport storage from './storage';\nimport source from './source';\nimport ui from './ui';\n\n// Globals\nlet scrollPosition = {\n x: 0,\n y: 0,\n};\n\n// Plyr instance\nclass Plyr {\n constructor(target, options) {\n this.timers = {};\n this.ready = false;\n\n // Set the media element\n this.media = target;\n\n // String selector passed\n if (utils.is.string(this.media)) {\n this.media = document.querySelectorAll(this.media);\n }\n\n // jQuery, NodeList or Array passed, use first element\n if (\n (window.jQuery && this.media instanceof jQuery) ||\n utils.is.nodeList(this.media) ||\n utils.is.array(this.media)\n ) {\n // eslint-disable-next-line\n this.media = this.media[0];\n }\n\n // Set config\n this.config = utils.extend(\n {},\n defaults,\n options,\n (() => {\n try {\n return JSON.parse(this.media.getAttribute('data-plyr'));\n } catch (e) {\n return null;\n }\n })()\n );\n\n // Elements cache\n this.elements = {\n container: null,\n buttons: {},\n display: {},\n progress: {},\n inputs: {},\n settings: {\n menu: null,\n panes: {},\n tabs: {},\n },\n captions: null,\n };\n\n // Captions\n this.captions = {\n enabled: null,\n tracks: null,\n currentTrack: null,\n };\n\n // Fullscreen\n this.fullscreen = {\n active: false,\n };\n\n // Options\n this.options = {\n speed: [],\n quality: [],\n };\n\n // Debugging\n this.console = {\n log() {},\n warn() {},\n error() {},\n };\n if (this.config.debug && 'console' in window) {\n this.console = {\n log: console.log, // eslint-disable-line\n warn: console.warn, // eslint-disable-line\n error: console.error, // eslint-disable-line\n };\n this.console.log('Debugging enabled');\n }\n\n // Log config options and support\n this.console.log('Config', this.config);\n this.console.log('Support', support);\n\n // We need an element to setup\n if (this.media === null || utils.is.undefined(this.media) || !utils.is.htmlElement(this.media)) {\n this.console.error('Setup failed: no suitable element passed');\n return;\n }\n\n // Bail if the element is initialized\n if (this.media.plyr) {\n this.console.warn('Target already setup');\n return;\n }\n\n // Bail if not enabled\n if (!this.config.enabled) {\n this.console.error('Setup failed: disabled by config');\n return;\n }\n\n // Bail if disabled or no basic support\n // You may want to disable certain UAs etc\n if (!support.check().api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Cache original element state for .destroy()\n this.elements.original = this.media.cloneNode(true);\n\n // Set media type based on tag or data attribute\n // Supported: video, audio, vimeo, youtube\n const type = this.media.tagName.toLowerCase();\n\n // Different setup based on type\n switch (type) {\n // TODO: Handle passing an iframe for true progressive enhancement\n // case 'iframe':\n case 'div':\n this.type = this.media.getAttribute('data-type');\n this.embedId = this.media.getAttribute('data-video-id');\n\n if (utils.is.empty(this.type)) {\n this.console.error('Setup failed: embed type missing');\n return;\n }\n\n if (utils.is.empty(this.embedId)) {\n this.console.error('Setup failed: video id missing');\n return;\n }\n\n // Clean up\n this.media.removeAttribute('data-type');\n this.media.removeAttribute('data-video-id');\n break;\n\n case 'video':\n case 'audio':\n this.type = type;\n\n if (this.media.hasAttribute('crossorigin')) {\n this.config.crossorigin = true;\n }\n if (this.media.hasAttribute('autoplay')) {\n this.config.autoplay = true;\n }\n if (this.media.hasAttribute('playsinline')) {\n this.config.inline = true;\n }\n if (this.media.hasAttribute('muted')) {\n this.config.muted = true;\n }\n if (this.media.hasAttribute('loop')) {\n this.config.loop.active = true;\n }\n\n break;\n\n default:\n this.console.error('Setup failed: unsupported type');\n return;\n }\n\n // Setup local storage for user settings\n storage.setup.call(this);\n\n // Check for support again but with type\n this.supported = support.check(this.type, this.config.inline);\n\n // If no support for even API, bail\n if (!this.supported.api) {\n this.console.error('Setup failed: no support');\n return;\n }\n\n // Store reference\n this.media.plyr = this;\n\n // Wrap media\n this.elements.container = utils.createElement('div');\n utils.wrap(this.media, this.elements.container);\n\n // Allow focus to be captured\n this.elements.container.setAttribute('tabindex', 0);\n\n // Global listeners\n listeners.global.call(this);\n\n // Add style hook\n ui.addStyleHook.call(this);\n\n // Setup media\n media.setup.call(this);\n\n // Listen for events if debugging\n if (this.config.debug) {\n utils.on(this.elements.container, this.config.events.join(' '), event => {\n this.console.log(`event: ${event.type}`);\n });\n }\n\n // Setup interface\n // If embed but not fully supported, build interface now to avoid flash of controls\n if (this.isHTML5 || (this.isEmbed && !this.supported.ui)) {\n ui.build.call(this);\n }\n }\n\n // ---------------------------------------\n // API\n // ---------------------------------------\n\n /**\n * If the player is HTML5\n */\n get isHTML5() {\n return types.html5.includes(this.type);\n }\n\n /**\n * If the player is an embed - e.g. YouTube or Vimeo\n */\n get isEmbed() {\n return types.embed.includes(this.type);\n }\n\n /**\n * Play the media\n */\n play() {\n if ('play' in this.media) {\n this.media.play();\n }\n return this;\n }\n\n /**\n * Pause the media\n */\n pause() {\n if ('pause' in this.media) {\n this.media.pause();\n }\n return this;\n }\n\n get paused() {\n return this.media.paused;\n }\n\n /**\n * Toggle playback based on current status\n * @param {boolean} toggle\n */\n togglePlay(toggle) {\n // True toggle if nothing passed\n if ((!utils.is.boolean(toggle) && this.media.paused) || toggle) {\n return this.play();\n }\n\n return this.pause();\n }\n\n /**\n * Stop playback\n */\n stop() {\n return this.restart().pause();\n }\n\n /**\n * Restart playback\n */\n restart() {\n this.currentTime = 0;\n return this;\n }\n\n /**\n * Rewind\n * @param {number} seekTime - how far to rewind in seconds. Defaults to the config.seekTime\n */\n rewind(seekTime) {\n this.currentTime = this.currentTime - (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Fast forward\n * @param {number} seekTime - how far to fast forward in seconds. Defaults to the config.seekTime\n */\n forward(seekTime) {\n this.currentTime = this.currentTime + (utils.is.number(seekTime) ? seekTime : this.config.seekTime);\n return this;\n }\n\n /**\n * Seek to a time\n * @param {number} input - where to seek to in seconds. Defaults to 0 (the start)\n */\n set currentTime(input) {\n let targetTime = 0;\n\n if (utils.is.number(input)) {\n targetTime = input;\n }\n\n // Normalise targetTime\n if (targetTime < 0) {\n targetTime = 0;\n } else if (targetTime > this.duration) {\n targetTime = this.duration;\n }\n\n // Set\n this.media.currentTime = targetTime.toFixed(4);\n\n // Logging\n this.console.log(`Seeking to ${this.currentTime} seconds`);\n }\n\n get currentTime() {\n return Number(this.media.currentTime);\n }\n\n get seeking() {\n return this.media.seeking;\n }\n\n /**\n * Get the duration of the current media\n */\n get duration() {\n // Faux duration set via config\n const fauxDuration = parseInt(this.config.duration, 10);\n\n // True duration\n const realDuration = Number(this.media.duration);\n\n // If custom duration is funky, use regular duration\n return !Number.isNaN(fauxDuration) ? fauxDuration : realDuration;\n }\n\n /**\n * Set the player volume\n * @param {number} value - must be between 0 and 1. Defaults to the value from local storage and config.volume if not set in storage\n */\n set volume(value) {\n let volume = value;\n const max = 1;\n const min = 0;\n\n if (utils.is.string(volume)) {\n volume = Number(volume);\n }\n\n // Load volume from storage if no value specified\n if (!utils.is.number(volume)) {\n ({ volume } = storage.get.call(this));\n }\n\n // Use config if all else fails\n if (!utils.is.number(volume)) {\n ({ volume } = this.config);\n }\n\n // Maximum is volumeMax\n if (volume > max) {\n volume = max;\n }\n // Minimum is volumeMin\n if (volume < min) {\n volume = min;\n }\n\n // Update config\n this.config.volume = volume;\n\n // Set the player volume\n this.media.volume = volume;\n\n // If muted, and we're increasing volume, reset muted state\n if (this.muted && volume > 0) {\n this.muted = false;\n }\n }\n\n /**\n * Get the current player volume\n */\n get volume() {\n return this.media.volume;\n }\n\n // Increase volume\n increaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume + utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Decrease volume\n decreaseVolume(step) {\n const volume = this.media.muted ? 0 : this.volume;\n this.volume = volume - utils.is.number(step) ? step : 1;\n return this;\n }\n\n // Toggle mute\n set muted(mute) {\n let toggle = mute;\n\n // Load muted state from storage\n if (!utils.is.boolean(toggle)) {\n toggle = storage.get.call(this).muted;\n }\n\n // Use config if all else fails\n if (!utils.is.boolean(toggle)) {\n toggle = this.config.muted;\n }\n\n // Update config\n this.config.muted = toggle;\n\n // Set mute on the player\n this.media.muted = toggle;\n }\n\n get muted() {\n return this.media.muted;\n }\n\n // Playback speed\n set speed(input) {\n let speed = null;\n\n if (utils.is.number(input)) {\n speed = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ speed } = storage.get.call(this));\n } else {\n speed = this.config.speed.selected;\n }\n\n // Set min/max\n if (speed < 0.1) {\n speed = 0.1;\n }\n if (speed > 2.0) {\n speed = 2.0;\n }\n\n if (!this.config.speed.options.includes(speed)) {\n this.console.warn(`Unsupported speed (${speed})`);\n return;\n }\n\n // Update config\n this.config.speed.selected = speed;\n\n // Set media speed\n this.media.playbackRate = speed;\n }\n\n get speed() {\n return this.media.playbackRate;\n }\n\n // Set playback quality\n set quality(input) {\n let quality = null;\n\n if (utils.is.string(input)) {\n quality = input;\n } else if (utils.is.number(storage.get.call(this).speed)) {\n ({ quality } = storage.get.call(this));\n } else {\n quality = this.config.quality.selected;\n }\n\n if (!this.options.quality.includes(quality)) {\n this.console.warn(`Unsupported quality option (${quality})`);\n return;\n }\n\n // Update config\n this.config.quality.selected = quality;\n\n // Set quality\n this.media.quality = quality;\n }\n\n get quality() {\n return this.media.quality;\n }\n\n // Toggle loop\n // TODO: Finish fancy new logic. Set the indicator on load as user may pass loop as config\n set loop(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.loop.active;\n this.config.loop.active = toggle;\n this.media.loop = toggle;\n\n // Set default to be a true toggle\n /* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';\n\n switch (type) {\n case 'start':\n if (this.config.loop.end && this.config.loop.end <= this.currentTime) {\n this.config.loop.end = null;\n }\n this.config.loop.start = this.currentTime;\n // this.config.loop.indicator.start = this.elements.display.played.value;\n break;\n\n case 'end':\n if (this.config.loop.start >= this.currentTime) {\n return this;\n }\n this.config.loop.end = this.currentTime;\n // this.config.loop.indicator.end = this.elements.display.played.value;\n break;\n\n case 'all':\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n this.config.loop.indicator.start = 0;\n this.config.loop.indicator.end = 100;\n break;\n\n case 'toggle':\n if (this.config.loop.active) {\n this.config.loop.start = 0;\n this.config.loop.end = null;\n } else {\n this.config.loop.start = 0;\n this.config.loop.end = this.duration - 2;\n }\n break;\n\n default:\n this.config.loop.start = 0;\n this.config.loop.end = null;\n break;\n } */\n }\n\n get loop() {\n return this.media.loop;\n }\n\n // Media source\n set source(input) {\n source.change.call(this, input);\n }\n\n get source() {\n return this.media.currentSrc;\n }\n\n // Poster image\n set poster(input) {\n if (this.type !== 'video') {\n this.console.warn('Poster can only be set on HTML5 video');\n return;\n }\n\n if (utils.is.string(input)) {\n this.media.setAttribute('poster', input);\n }\n }\n\n get poster() {\n if (this.type !== 'video') {\n return null;\n }\n\n return this.media.getAttribute('poster');\n }\n\n // Autoplay\n get autoplay() {\n return this.config.autoplay;\n }\n\n set autoplay(input) {\n const toggle = utils.is.boolean(input) ? input : this.config.autoplay;\n this.config.autoplay = toggle;\n }\n\n // Toggle captions\n toggleCaptions(input) {\n // If there's no full support, or there's no caption toggle\n if (!this.supported.ui || !utils.is.htmlElement(this.elements.buttons.captions)) {\n return this;\n }\n\n // If the method is called without parameter, toggle based on current value\n const show = utils.is.boolean(input)\n ? input\n : this.elements.container.className.indexOf(this.config.classNames.captions.active) === -1;\n\n // Nothing to change...\n if (this.captions.enabled === show) {\n return this;\n }\n\n // Set global\n this.captions.enabled = show;\n\n // Toggle state\n utils.toggleState(this.elements.buttons.captions, this.captions.enabled);\n\n // Add class hook\n utils.toggleClass(this.elements.container, this.config.classNames.captions.active, this.captions.enabled);\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.captions.enabled ? 'captionsenabled' : 'captionsdisabled');\n\n // Allow chaining\n return this;\n }\n\n // Caption language\n set language(input) {\n // Nothing specified\n if (!utils.is.string(input)) {\n return;\n }\n\n // Normalize\n const language = input.toLowerCase();\n\n // If nothing to change, bail\n if (this.captions.language === language) {\n return;\n }\n\n // Reset UI\n this.toggleCaptions(true);\n\n // Update config\n this.captions.language = language;\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, 'languagechange');\n\n // Clear caption\n captions.set.call(this);\n\n // Re-run setup\n captions.setup.call(this);\n }\n\n get language() {\n return this.captions.language;\n }\n\n // Toggle fullscreen\n // Requires user input event\n toggleFullscreen(event) {\n // Check for native support\n if (fullscreen.enabled) {\n // If it's a fullscreen change event, update the UI\n if (utils.is.event(event) && event.type === fullscreen.eventType) {\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n } else {\n // Else it's a user request to enter or exit\n if (!this.fullscreen.active) {\n // Request full screen\n fullscreen.requestFullScreen(this.elements.container);\n } else {\n // Bail from fullscreen\n fullscreen.cancelFullScreen();\n }\n\n // Check if we're actually full screen (it could fail)\n this.fullscreen.active = fullscreen.isFullScreen(this.elements.container);\n\n return this;\n }\n } else {\n // Otherwise, it's a simple toggle\n this.fullscreen.active = !this.fullscreen.active;\n\n // Add class hook\n utils.toggleClass(\n this.elements.container,\n this.config.classNames.fullscreen.fallback,\n this.fullscreen.active\n );\n\n // Make sure we don't lose scroll position\n if (this.fullscreen.active) {\n scrollPosition = {\n x: window.pageXOffset || 0,\n y: window.pageYOffset || 0,\n };\n } else {\n window.scrollTo(scrollPosition.x, scrollPosition.y);\n }\n\n // Bind/unbind escape key\n document.body.style.overflow = this.fullscreen.active ? 'hidden' : '';\n }\n\n // Set button state\n if (this.elements.buttons && this.elements.buttons.fullscreen) {\n utils.toggleState(this.elements.buttons.fullscreen, this.fullscreen.active);\n }\n\n // Trigger an event\n utils.dispatchEvent.call(this, this.media, this.fullscreen.active ? 'enterfullscreen' : 'exitfullscreen');\n\n return this;\n }\n\n // Toggle picture-in-picture\n // TODO: update player with state, support, enabled\n // TODO: detect outside changes\n set pip(input) {\n const states = {\n pip: 'picture-in-picture',\n inline: 'inline',\n };\n\n // Bail if no support\n if (!support.pip) {\n return;\n }\n\n // Toggle based on current state if not passed\n const toggle = utils.is.boolean(input) ? input : this.pip === states.inline;\n\n // Toggle based on current state\n this.media.webkitSetPresentationMode(toggle ? states.pip : states.inline);\n }\n\n get pip() {\n if (!support.pip) {\n return null;\n }\n\n return this.media.webkitPresentationMode;\n }\n\n // Trigger airplay\n // TODO: update player with state, support, enabled\n airplay() {\n // Bail if no support\n if (!support.airplay) {\n return this;\n }\n\n // Show dialog\n this.media.webkitShowPlaybackTargetPicker();\n\n return this;\n }\n\n // Show the player controls in fullscreen mode\n toggleControls(toggle) {\n const player = this;\n\n // We need controls of course...\n if (!utils.is.htmlElement(this.elements.controls)) {\n return player;\n }\n\n // Don't hide if config says not to, it's audio, or not ready or loading\n if (!this.supported.ui || !this.config.hideControls || this.type === 'audio') {\n return player;\n }\n\n let delay = 0;\n let show = toggle;\n let isEnterFullscreen = false;\n const loading = utils.hasClass(this.elements.container, this.config.classNames.loading);\n\n // Default to false if no boolean\n if (!utils.is.boolean(toggle)) {\n if (utils.is.event(toggle)) {\n // Is the enter fullscreen event\n isEnterFullscreen = toggle.type === 'enterfullscreen';\n\n // Whether to show controls\n show = ['mousemove', 'touchstart', 'mouseenter', 'focus'].includes(toggle.type);\n\n // Delay hiding on move events\n if (['mousemove', 'touchmove'].includes(toggle.type)) {\n delay = 2000;\n }\n\n // Delay a little more for keyboard users\n if (toggle.type === 'focus') {\n delay = 3000;\n }\n } else {\n show = utils.hasClass(this.elements.container, this.config.classNames.hideControls);\n }\n }\n\n // Clear timer every movement\n window.clearTimeout(this.timers.hover);\n\n // If the mouse is not over the controls, set a timeout to hide them\n if (show || this.media.paused || loading) {\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, false);\n\n // Trigger event\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlsshown');\n }\n\n // Always show controls when paused or if touch\n if (this.media.paused || loading) {\n return player;\n }\n\n // Delay for hiding on touch\n if (support.touch) {\n delay = 3000;\n }\n }\n\n // If toggle is false or if we're playing (regardless of toggle),\n // then set the timer to hide the controls\n if (!show || !this.media.paused) {\n this.timers.hover = window.setTimeout(() => {\n // If the mouse is over the controls (and not entering fullscreen), bail\n if ((this.elements.controls.pressed || this.elements.controls.hover) && !isEnterFullscreen) {\n return;\n }\n\n // Check if controls toggled\n const toggled = utils.toggleClass(this.elements.container, this.config.classNames.hideControls, true);\n\n // Trigger event and close menu\n if (toggled) {\n utils.dispatchEvent.call(this, this.media, 'controlshidden');\n\n if (this.config.controls.includes('settings') && !utils.is.empty(this.config.settings)) {\n controls.toggleMenu.call(this, false);\n }\n }\n }, delay);\n }\n\n return this;\n }\n\n // Event listeners\n on(event, callback) {\n utils.on(this.elements.container, event, callback);\n return this;\n }\n\n off(event, callback) {\n utils.off(this.elements.container, event, callback);\n return this;\n }\n\n // Check for support\n supports(type) {\n return support.mime.call(this, type);\n }\n\n // Destroy an instance\n // Event listeners are removed when elements are removed\n // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory\n destroy(callback, soft = false) {\n const done = () => {\n // Reset overflow (incase destroyed while in fullscreen)\n document.body.style.overflow = '';\n\n // GC for embed\n this.embed = null;\n this.embedId = null;\n\n // If it's a soft destroy, make minimal changes\n if (soft) {\n if (Object.keys(this.elements).length) {\n // Remove buttons\n if (this.elements.buttons && this.elements.buttons.play) {\n Array.from(this.elements.buttons.play).forEach(button => utils.removeElement(button));\n }\n\n // Remove others\n utils.removeElement(this.elements.captions);\n utils.removeElement(this.elements.controls);\n utils.removeElement(this.elements.wrapper);\n\n // Clear for GC\n this.elements.buttons.play = null;\n this.elements.captions = null;\n this.elements.controls = null;\n this.elements.wrapper = null;\n }\n\n // Callback\n if (utils.is.function(callback)) {\n callback();\n }\n } else {\n // Replace the container with the original element provided\n const parent = this.elements.container.parentNode;\n\n if (utils.is.htmlElement(parent)) {\n parent.replaceChild(this.elements.original, this.elements.container);\n }\n\n // Event\n utils.dispatchEvent.call(this, this.elements.original, 'destroyed', true);\n\n // Callback\n if (utils.is.function(callback)) {\n callback.call(this.elements.original);\n }\n\n // Clear for GC\n this.elements = null;\n }\n };\n\n // Type specific stuff\n switch (this.type) {\n case 'youtube':\n // Clear timers\n window.clearInterval(this.timers.buffering);\n window.clearInterval(this.timers.playing);\n\n // Destroy YouTube API\n this.embed.destroy();\n\n // Clean up\n done();\n\n break;\n\n case 'vimeo':\n // Destroy Vimeo API\n // then clean up (wait, to prevent postmessage errors)\n this.embed.unload().then(done);\n\n // Vimeo does not always return\n window.setTimeout(done, 200);\n\n break;\n\n case 'video':\n case 'audio':\n // Restore native video controls\n ui.toggleNativeControls.call(this, true);\n\n // Clean up\n done();\n\n break;\n\n default:\n break;\n }\n }\n}\n\nexport default Plyr;\n"],"names":["get","store","window","localStorage","getItem","this","config","storage","key","utils","is","empty","JSON","parse","set","object","support","enabled","call","extend","setItem","stringify","defaults","navigator","language","split","types","input","getConstructor","Object","Number","isNaN","String","Boolean","Function","undefined","Array","isArray","NodeList","HTMLElement","Event","instanceOf","TextTrackCue","VTTCue","TextTrack","kind","string","array","nodeList","length","keys","constructor","document","documentMode","documentElement","style","test","userAgent","platform","url","callback","querySelectorAll","element","createElement","src","first","getElementsByTagName","function","addEventListener","event","parentNode","insertBefore","id","updateSprite","data","innerHTML","body","childNodes","hasId","container","setAttribute","cached","content","xhr","XMLHttpRequest","open","onload","responseText","send","prefix","Math","floor","random","self","top","e","elements","wrapper","targets","from","reverse","forEach","index","child","cloneNode","parent","sibling","nextSibling","appendChild","htmlElement","removeChild","target","type","attributes","text","setAttributes","textContent","lastChild","sel","existingAttributes","existing","selector","s","trim","className","replace","parts","value","charAt","class","toggle","contains","classList","prototype","Element","matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","includes","querySelector","controls","getElement","selectors","buttons","getElements","play","pause","restart","rewind","forward","mute","pip","airplay","settings","captions","fullscreen","progress","inputs","seek","volume","display","buffer","duration","currentTime","seekTooltip","classNames","tooltip","error","console","warn","toggleNativeControls","focused","activeElement","tabbables","last","on","keyCode","_this","active","getFocusElement","shiftKey","focus","preventDefault","passive","capture","Node","toggleListener","events","options","boolean","passiveListeners","bubbles","properties","CustomEvent","assign","Plyr","dispatchEvent","state","getAttribute","current","max","toFixed","objects","destination","shift","source","property","match","RegExp","$2","number","map","encodeURIComponent","join","fragment","createDocumentFragment","firstChild","innerText","width","height","ratio","getRatio","w","h","find","inline","api","ui","browser","getBrowser","playsInline","isIPhone","video","rangeInput","audio","removeItem","webkitSetPresentationMode","WebKitPlaybackTargetAvailabilityEvent","media","canPlayType","supported","defineProperty","range","transitionEnd","matchMedia","cancelFullScreen","some","pre","msExitFullscreen","msFullscreenEnabled","fullscreenEnabled","webkitFullscreenEnabled","mozFullScreenEnabled","fullscreenElement","mozFullScreenElement","requestFullScreen","nativeSupport","fallback","inFrame","log","toggleClass","toggleState","trapFocus","setup","parseFloat","listeners","getKeyCode","which","handleKey","code","pressed","held","editable","stopPropagation","togglePlay","increaseVolume","decreaseVolume","muted","toggleFullscreen","toggleCaptions","loop","keyboard","global","tabFocus","setTimeout","hideControls","toggleControls","eventType","timeUpdate","displayDuration","_this2","showPosterOnEnd","load","updateProgress","updateVolume","checkPlaying","checkLoading","clickToPlay","cursor","touch","paused","ended","disableContextMenu","updateSetting","speed","quality","concat","inputEvent","isIE","proxy","handlerKey","defaultHandler","customHandler","_this3","defaultPrevented","airPlay","toggleMenu","form","showTab","toLowerCase","isWebkit","updateRangeFill","updateSeekTooltip","hover","inverted","webkitDirectionInvertedFromDevice","direction","deltaY","deltaX","uiSupported","isHTML5","removeAttribute","removeElement","inject","ready","updateTimeDisplay","label","i18n","title","playLarge","isEmbed","iframe","frameTitle","playing","stopped","setRange","loading","timers","nodeValue","getPercentage","buffered","end","setProgress","time","secs","parseInt","mins","hours","displayHours","slice","seeking","styleSheet","sheet","percentage","styles","rules","findIndex","rule","selectorText","deleteRule","insertRule","iconUrl","indexOf","svg4everybody","getIconUrl","iconPath","absolute","iconPrefix","icon","createElementNS","use","path","setAttributeNS","hidden","badge","menu","buttonType","attr","button","iconDefault","iconToggled","labelKey","control","getAttributesFromSelector","createIcon","createLabel","suffix","played","tooltips","percent","clientRect","getBoundingClientRect","visible","pageX","left","hasClass","setting","tab","tabs","pane","panes","list","filter","toggleTab","emptyElement","getBadge","createBadge","item","radio","createTextNode","getLabel","getLanguage","default","checked","option","textTracks","tracks","none","currentTrack","disabled","track","toUpperCase","unshift","_this4","insertAdjacentHTML","show","isMenuItem","isButton","clone","position","opacity","name","scrollWidth","scrollHeight","getElementById","transitions","reducedMotion","size","getTabSize","restore","propertyName","off","createButton","createRange","createProgress","createTime","inner","home","_this5","back","setSpeedMenu","loadSprite","seekTime","create","findElements","labels","_this6","setCaptionsMenu","insertAfter","setCurrentTrack","setCue","mode","activeCues","embed","enableTextTrack","cue","getCueAsHTML","caption","youtube","videoId","parseYouTubeId","embedId","containers","setAspectRatio","generateId","YT","loadScript","urls","onYouTubeReadyCallbacks","push","onYouTubeIframeAPIReady","paddingBottom","player","Player","autoplay","location","hostname","href","instance","getPlaybackQuality","playbackRate","getPlaybackRate","playVideo","pauseVideo","stop","stopVideo","getDuration","getCurrentTime","seekTo","setPlaybackRate","setPlaybackQuality","setVolume","getVideoUrl","getAvailablePlaybackRates","getVideoData","clearInterval","buffering","setInterval","getVideoLoadedFraction","lastBuffered","build","setQualityMenu","getAvailableQualityLevels","vimeo","Vimeo","padding","offset","transform","params","buildUrlParameters","parseVimeoId","setCurrentTime","selected","setLoop","currentSrc","then","all","getVideoWidth","getVideoHeight","getAspectRatio","dimensions","getVideoTitle","getTextTracks","cues","stripHTML","seconds","isIos","isTouch","wrap","setTitle","blankVideo","insertElement","attribute","sources","cancelRequests","destroy","firstSource","check","crossorigin","poster","addStyleHook","insertElements","scrollPosition","jQuery","debug","plyr","original","tagName","hasAttribute","step","isFullScreen","pageXOffset","pageYOffset","scrollTo","x","y","overflow","webkitShowPlaybackTargetPicker","delay","isEnterFullscreen","clearTimeout","mime","soft","done","replaceChild","unload","html5","targetTime","fauxDuration","realDuration","change","states","webkitPresentationMode"],"mappings":"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"} \ No newline at end of file diff --git a/readme.md b/readme.md index c3fa09ac..ce63432b 100644 --- a/readme.md +++ b/readme.md @@ -66,18 +66,19 @@ Plyr extends upon the standard HTML5 markup so that's all you need for those typ #### HTML5 Video ```html ``` #### HTML5 Audio ```html ``` @@ -101,7 +102,7 @@ Include the `plyr.js` script before the closing `` tag and then call `ply ```html - + ``` If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript, you can use the following: @@ -131,7 +132,7 @@ The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https: ### LESS & SASS/SCSS -You can use `plyr.less` or `plyr.scss` file included in `/src` as part of your build and change variables to suit your design. The LESS and SASS require you to use the [autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer) plugin (you should already) as all declerations use the W3C definitions - e.g. `appearance: none;` will be prefixed to `-webkit-appearance: none;` by autoprefixer. +You can use `plyr.less` or `plyr.scss` file included in `/src` as part of your build and change variables to suit your design. The LESS and SASS require you to use the [autoprefixer](https://www.npmjs.com/package/gulp-autoprefixer) plugin (you be should already!) as all declarations use the W3C definitions. The HTML markup uses the BEM methodology with `plyr` as the block, e.g. `.plyr__controls`. You can change the class hooks in the options to match any custom CSS you write. Check out the JavaScript source for more on this. @@ -320,16 +321,16 @@ Property | Getter | Setter | Description `volume` | ✔ | ✔ | Gets or sets the volume for the player. The setter accepts a float between 0 and 1. `muted` | ✔ | ✔ | Gets or sets the muted state of the player. The setter accepts a boolean. `speed` | ✔ | ✔ | Gets or sets the speed for the player. The setter accepts a value in the options specified in your config. Generally the minimum should be 0.5. -`quality`¹ | ✔ | ✔ | Gets or sets the quality for the player. The setter accepts a value from the options specified in your config. +`quality`¹ | ✔ | ✔ | Gets or sets the quality for the player. The setter accepts a value from the options specified in your config. `loop` | ✔ | ✔ | Gets or sets the current loop state of the player. The setter accepts a boolean. `source` | ✔ | ✔ | Gets or sets the current source for the player. The setter accepts an object. See [source setter](#source-setter) below for examples. -`poster`² | ✔ | ✔ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. +`poster`² | ✔ | ✔ | Gets or sets the current poster image for the player. The setter accepts a string; the URL for the updated poster image. `autoplay` | ✔ | ✔ | Gets or sets the autoplay state of the player. The setter accepts a boolean. `language` | ✔ | ✔ | Gets or sets the preferred captions language for the player. The setter accepts an ISO two-letter language code. Support for the languages is dependent on the captions you include. `pip` | ✔ | ✔ | Gets or sets the picture-in-picture state of the player. The setter accepts a boolean. This currently only supported on Safari 10+ on MacOS Sierra+ and iOS 10+. -1. YouTube only. HTML5 will follow. -2. HTML5 only +*1. YouTube only. HTML5 will follow.* +*2. HTML5 only* #### The `.source` setter @@ -426,12 +427,12 @@ player.source = { Property | Type | Description -------- | ---- | ----------- `type` | String | Either `video` or `audio`. *Note:* YouTube and Vimeo are currently not supported as audio sources. -`title` | String | *Optional.* Title of the new media. Used for the `aria-label` attribute on the play button, and outer container. YouTube and Vimeo can be populated automatically. +`title` | String | *Optional.* Title of the new media. Used for the `aria-label` attribute on the play button, and outer container. YouTube and Vimeo are populated automatically. `sources` | Array | This is an array of sources. For HTML5 media, the properties of this object are mapped directly to HTML attributes so more can be added to the object if required. `poster`¹ | String | The URL for the poster image (HTML5 video only). `tracks`¹ | String | An array of track objects. Each element in the array is mapped directly to a track element and any keys mapped directly to HTML attributes so as in the example above, it will render as `` and similar for the French version. Booleans are converted to HTML5 value-less attributes. -1. HTML5 only +*1. HTML5 only* ## Events @@ -504,84 +505,22 @@ YouTube and Vimeo are currently supported and function much like a HTML5 video. By default, a player will bind the following keyboard shortcuts when it has focus. If you have the `global` option to `true` and there's only one player in the document then the shortcuts will work when any element has focus, apart from an element that requires input. -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyGlobalAction
0 to 9✔Seek from 0 to 90% respectively
spaceToggle playback
K✔Toggle playback
Seek backward by the seekTime option
Seek forward by the seekTime option
Increase volume
Decrease volume
M✔Toggle mute
F✔Toggle fullscreen
C✔Toggle captions
lToggle Loop All/No Loop
iSet the start marker of the loop
oSet the end marker of the loop
+Key | Action +--- | ------ +`0` to `9` | Seek from 0 to 90% respectively +`space` | Toggle playback +`K` | Toggle playback +← | Seek backward by the `seekTime` option +→ | Seek forward by the `seekTime` option +↑ | Increase volume +↓ | Decrease volume +`M` | Toggle mute +`F` | Toggle fullscreen +`C` | Toggle captions +`L` | Toggle loop ## Streaming + Because Plyr is an extension of the standard HTML5 video and audio elements, third party streaming plugins can be used with Plyr. Massive thanks to Matias Russitto ([@russitto](https://github.com/russitto)) for working on this. Here's a few examples: - Using [hls.js](https://github.com/dailymotion/hls.js) - [Demo](http://codepen.io/sampotts/pen/JKEMqB) @@ -589,62 +528,54 @@ Because Plyr is an extension of the standard HTML5 video and audio elements, thi - Using [dash.js](https://github.com/Dash-Industry-Forum/dash.js) - [Demo](http://codepen.io/sampotts/pen/BzpJXN) ## Fullscreen + Fullscreen in Plyr is supported by all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). ## Browser support - - - - - - - - - - - - - - - - - - - - - -
SafariFirefoxChromeOperaIE9IE10+
✔¹âœ”✔✔API²âœ”³
+Plyr supports the last 2 versions of most *modern* browsers. IE11 is also supported. -¹ Mobile Safari on the iPhone forces the native player for `