diff options
31 files changed, 1338 insertions, 734 deletions
@@ -9,8 +9,7 @@ "rhino" : false, "couch" : false, "wsh" : true, // Windows Scripting Host. - "jquery" : true, - "predef" : [ "jQuery", "$" ], + "jquery" : false, // Development. "debug" : false, // Allow debugger statements e.g. browser breakpoints. @@ -51,6 +50,6 @@ "plusplus" : false, // Prohibit use of `++` & `--`. "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. "trailing" : true, // Prohibit trailing whitespaces. - "white" : false, // Check against strict whitespace and indentation rules. - "indent" : 2 // Specify indentation spacing + "white" : true, // Check against strict whitespace and indentation rules. + "indent" : 4 // Specify indentation spacing }
\ No newline at end of file diff --git a/dist/plyr.css b/dist/plyr.css index 78ebe688..00f2191d 100644 --- a/dist/plyr.css +++ b/dist/plyr.css @@ -1 +1 @@ -.player-captions,.player-controls,.player-controls .player-time{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.player-controls button:focus,.player-progress-seek[type=range]:focus,.player-volume[type=range]:focus{outline:0}@-webkit-keyframes progress{to{background-position:40px 0}}@keyframes progress{to{background-position:40px 0}}.sr-only{position:absolute!important;clip:rect(1px,1px,1px,1px);padding:0!important;border:0!important;height:1px!important;width:1px!important;overflow:hidden}.player,.player-video-wrapper{position:relative}.player{max-width:100%;min-width:290px}.player,.player *,.player ::after,.player ::before{box-sizing:border-box}.player audio,.player video{width:100%;height:auto;vertical-align:middle}.player-video-embed{padding-bottom:56.25%;height:0}.player-video-embed iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:0}.player-captions{display:none;position:absolute;bottom:0;left:0;width:100%;padding:20px 20px 30px;color:#fff;font-size:20px;text-align:center}.player-captions span{border-radius:2px;padding:3px 10px;background:rgba(0,0,0,.9)}.player-captions span:empty{display:none}@media (min-width:768px){.player-captions{font-size:24px}}.player.captions-active .player-captions{display:block}.player.fullscreen-active .player-captions{font-size:32px}.player-controls{zoom:1;position:relative;padding:10px;background:#fff;line-height:1;text-align:center;box-shadow:0 1px 1px rgba(52,63,74,.2)}.player-controls:after,.player-controls:before{content:"";display:table}.player-controls:after{clear:both}.player-controls-right{display:block;margin:10px auto 0}@media (min-width:560px){.player-controls-left{float:left}.player-controls-right{float:right;margin-top:0}}.player-controls button{display:inline-block;vertical-align:middle;margin:0 2px;padding:5px 10px;overflow:hidden;border:0;background:0 0;border-radius:3px;cursor:pointer;color:#6B7D86;transition:background .3s ease,color .3s ease,opacity .3s ease}.player-controls button svg{width:18px;height:18px;display:block;fill:currentColor;transition:fill .3s ease}.player-controls button.tab-focus,.player-controls button:hover{background:#3498DB;color:#fff}.player-controls .icon-captions-on,.player-controls .icon-exit-fullscreen,.player-controls .icon-muted{display:none}.player-controls .player-time{display:inline-block;vertical-align:middle;margin-left:10px;color:#6B7D86;font-weight:600;font-size:14px}.player-controls .player-time+.player-time{display:none}@media (min-width:560px){.player-controls .player-time+.player-time{display:inline-block}}.player-controls .player-time+.player-time::before{content:'\2044';margin-right:10px}.player-tooltip{position:absolute;z-index:2;bottom:100%;margin-bottom:10px;padding:10px 15px;opacity:0;background:#fff;border:1px solid #D6DADD;border-radius:3px;color:#6B7D86;font-size:14px;line-height:1.5;font-weight:600;-webkit-transform:translate(-50%,30px) scale(0);transform:translate(-50%,30px) scale(0);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;transition:opacity .2s .1s ease,-webkit-transform .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease,-webkit-transform .2s .1s ease}.player-tooltip::after{content:'';position:absolute;z-index:1;top:100%;left:50%;display:block;width:10px;height:10px;background:#fff;-webkit-transform:translate(-50%,-50%) rotate(45deg) translateY(1px);transform:translate(-50%,-50%) rotate(45deg) translateY(1px);border:1px solid #D6DADD;border-width:0 1px 1px 0}.player button.tab-focus:focus .player-tooltip,.player button:hover .player-tooltip{opacity:1;-webkit-transform:translate(-50%,0) scale(1);transform:translate(-50%,0) scale(1)}.player button:hover .player-tooltip{z-index:3}.player-progress{position:absolute;bottom:100%;left:0;right:0;width:100%;height:10px;background:rgba(86,93,100,.2)}.player-progress-buffer[value],.player-progress-played[value],.player-progress-seek[type=range]{position:absolute;left:0;top:0;width:100%;height:10px;margin:0;padding:0;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;border:none;background:0 0}.player-progress-buffer[value]::-webkit-progress-bar,.player-progress-played[value]::-webkit-progress-bar{background:0 0}.player-progress-buffer[value]::-webkit-progress-value,.player-progress-played[value]::-webkit-progress-value{background:currentColor}.player-progress-buffer[value]::-moz-progress-bar,.player-progress-played[value]::-moz-progress-bar{background:currentColor}.player-progress-played[value]{z-index:2;color:#3498DB}.player-progress-buffer[value]{color:rgba(86,93,100,.25)}.player-progress-seek[type=range]{z-index:4;cursor:pointer;outline:0}.player-progress-seek[type=range]::-webkit-slider-runnable-track{background:0 0;border:0}.player-progress-seek[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background:0 0;border:0;width:20px;height:10px}.player-progress-seek[type=range]::-moz-range-track{background:0 0;border:0}.player-progress-seek[type=range]::-moz-range-thumb{-moz-appearance:none;background:0 0;border:0;width:20px;height:10px}.player-progress-seek[type=range]::-ms-track{color:transparent;background:0 0;border:0}.player-progress-seek[type=range]::-ms-fill-lower,.player-progress-seek[type=range]::-ms-fill-upper{background:0 0;border:0}.player-progress-seek[type=range]::-ms-thumb{background:0 0;border:0;width:20px;height:10px}.player-progress-seek[type=range]::-moz-focus-outer{border:0}.player.loading .player-progress-buffer{-webkit-animation:progress 1s linear infinite;animation:progress 1s linear infinite;background-size:40px 40px;background-repeat:repeat-x;background-color:rgba(86,93,100,.25);background-image:linear-gradient(-45deg,rgba(0,0,0,.15) 25%,transparent 25%,transparent 50%,rgba(0,0,0,.15) 50%,rgba(0,0,0,.15) 75%,transparent 75%,transparent);color:transparent}.player-controls [data-player=pause],.player.playing .player-controls [data-player=play]{display:none}.player.playing .player-controls [data-player=pause]{display:inline-block}.player-volume[type=range]{display:inline-block;vertical-align:middle;-webkit-appearance:none;-moz-appearance:none;width:100px;margin:0 10px 0 0;padding:0;cursor:pointer;background:0 0;border:none}.player-volume[type=range]::-webkit-slider-runnable-track{height:6px;background:#e6e6e6;border:0;border-radius:3px}.player-volume[type=range]::-webkit-slider-thumb{-webkit-appearance:none;margin-top:-3px;height:12px;width:12px;background:#6B7D86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.player-volume[type=range]::-moz-range-track{height:6px;background:#e6e6e6;border:0;border-radius:3px}.player-volume[type=range]::-moz-range-thumb{height:12px;width:12px;background:#6B7D86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.player-volume[type=range]::-ms-track{height:6px;background:0 0;border-color:transparent;border-width:3px 0;color:transparent}.player-volume[type=range]::-ms-fill-lower,.player-volume[type=range]::-ms-fill-upper{height:6px;background:#e6e6e6;border:0;border-radius:3px}.player-volume[type=range]::-ms-thumb{height:12px;width:12px;background:#6B7D86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.player-volume[type=range]:focus::-webkit-slider-thumb{background:#3498DB}.player-volume[type=range]:focus::-moz-range-thumb{background:#3498DB}.player-volume[type=range]:focus::-ms-thumb{background:#3498DB}.player-audio.ios .player-controls-right,.player.ios .player-volume,.player.ios [data-player=mute]{display:none}.player-audio.ios .player-controls-left{float:none}.player-audio .player-controls{padding-top:20px}.player-audio .player-progress{bottom:auto;top:0;background:#D6DADD}.player-fullscreen,.player.fullscreen-active{position:fixed;top:0;left:0;right:0;bottom:0;height:100%;width:100%;z-index:10000000;background:#000}.player-fullscreen video,.player.fullscreen-active video{height:100%}.player-fullscreen .player-video-wrapper,.player.fullscreen-active .player-video-wrapper{height:100%;width:100%}.player-fullscreen .player-controls,.player.fullscreen-active .player-controls{position:absolute;bottom:0;left:0;right:0}.player-fullscreen.fullscreen-hide-controls.playing .player-controls,.player.fullscreen-active.fullscreen-hide-controls.playing .player-controls{-webkit-transform:translateY(100%) translateY(5px);transform:translateY(100%) translateY(5px);transition:-webkit-transform .3s .2s ease;transition:transform .3s .2s ease;transition:transform .3s .2s ease,-webkit-transform .3s .2s ease}.player-fullscreen.fullscreen-hide-controls.playing.player-hover .player-controls,.player.fullscreen-active.fullscreen-hide-controls.playing.player-hover .player-controls{-webkit-transform:translateY(0);transform:translateY(0)}.player-fullscreen.fullscreen-hide-controls.playing .player-captions,.player.fullscreen-active.fullscreen-hide-controls.playing .player-captions{bottom:5px;transition:bottom .3s .2s ease}.player-fullscreen .player-captions,.player-fullscreen.fullscreen-hide-controls.playing.player-hover .player-captions,.player.fullscreen-active .player-captions,.player.fullscreen-active.fullscreen-hide-controls.playing.player-hover .player-captions{top:auto;bottom:90px}@media (min-width:560px){.player-fullscreen .player-captions,.player-fullscreen.fullscreen-hide-controls.playing.player-hover .player-captions,.player.fullscreen-active .player-captions,.player.fullscreen-active.fullscreen-hide-controls.playing.player-hover .player-captions{bottom:60px}}.player.captions-active .player-controls .icon-captions-on,.player.fullscreen-active .icon-exit-fullscreen,.player.muted .player-controls .icon-muted{display:block}.player [data-player=captions],.player [data-player=fullscreen],.player.captions-active .player-controls .icon-captions-on+svg,.player.fullscreen-active .icon-exit-fullscreen+svg,.player.muted .player-controls .icon-muted+svg{display:none}.player.captions-enabled [data-player=captions],.player.fullscreen-enabled [data-player=fullscreen]{display:inline-block}
\ No newline at end of file +.plyr-captions,.plyr-controls,.plyr-controls .plyr-time{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.plyr-controls button:focus,.plyr-progress-seek[type=range]:focus,.plyr-volume[type=range]:focus{outline:0}@-webkit-keyframes progress{to{background-position:40px 0}}@keyframes progress{to{background-position:40px 0}}.sr-only{position:absolute!important;clip:rect(1px,1px,1px,1px);padding:0!important;border:0!important;height:1px!important;width:1px!important;overflow:hidden}.plyr,.plyr-video-wrapper{position:relative}.plyr{max-width:100%;min-width:290px}.plyr,.plyr *,.plyr ::after,.plyr ::before{box-sizing:border-box}.plyr audio,.plyr video{width:100%;height:auto;vertical-align:middle}.plyr-video-embed{padding-bottom:56.25%;height:0;overflow:hidden;background:#000}.plyr-video-embed iframe{position:absolute;top:0;left:0;width:100%;height:100%;border:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.plyr-video-embed>div{position:relative;padding-bottom:200%;-webkit-transform:translateY(-35.95%);transform:translateY(-35.95%)}.plyr-captions{display:none;position:absolute;bottom:0;left:0;width:100%;padding:20px 20px 30px;color:#fff;font-size:20px;text-align:center}.plyr-captions span{border-radius:2px;padding:3px 10px;background:rgba(0,0,0,.9)}.plyr-captions span:empty{display:none}@media (min-width:768px){.plyr-captions{font-size:24px}}.plyr.captions-active .plyr-captions{display:block}.plyr.fullscreen-active .plyr-captions{font-size:32px}.plyr-controls{zoom:1;position:relative;padding:10px;background:#fff;line-height:1;text-align:center;box-shadow:0 1px 1px rgba(52,63,74,.2)}.plyr-controls:after,.plyr-controls:before{content:"";display:table}.plyr-controls:after{clear:both}.plyr-controls-right{display:block;margin:10px auto 0}@media (min-width:560px){.plyr-controls-left{float:left}.plyr-controls-right{float:right;margin-top:0}}.plyr-controls button{display:inline-block;vertical-align:middle;margin:0 2px;padding:5px 10px;overflow:hidden;border:0;background:0 0;border-radius:3px;cursor:pointer;color:#6B7D86;transition:background .3s ease,color .3s ease,opacity .3s ease}.plyr-controls button svg{width:18px;height:18px;display:block;fill:currentColor;transition:fill .3s ease}.plyr-controls button.tab-focus,.plyr-controls button:hover{background:#3498DB;color:#fff}.plyr-controls .plyr-time,.plyr-tooltip{color:#6B7D86;font-size:14px;font-weight:600}.plyr-controls .icon-captions-on,.plyr-controls .icon-exit-fullscreen,.plyr-controls .icon-muted{display:none}.plyr-controls .plyr-time{display:inline-block;vertical-align:middle;margin-left:10px}.plyr-controls .plyr-time+.plyr-time{display:none}@media (min-width:560px){.plyr-controls .plyr-time+.plyr-time{display:inline-block}}.plyr-controls .plyr-time+.plyr-time::before{content:'\2044';margin-right:10px}.plyr-tooltip{position:absolute;z-index:2;bottom:100%;margin-bottom:10px;padding:10px 15px;opacity:0;background:#fff;box-shadow:0 0 5px rgba(52,63,74,.1),0 0 0 1px rgba(52,63,74,.1);border-radius:3px;line-height:1.5;-webkit-transform:translate(-50%,30px) scale(.8);transform:translate(-50%,30px) scale(.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;transition:opacity .2s .1s ease,-webkit-transform .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease;transition:transform .2s .1s ease,opacity .2s .1s ease,-webkit-transform .2s .1s ease}.plyr-tooltip::after,.plyr-tooltip::before{content:'';position:absolute;width:0;height:0;top:100%;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.plyr-tooltip::after{bottom:-8px;border-right:7px solid transparent;border-top:7px solid rgba(52,63,74,.1);border-left:7px solid transparent;z-index:1}.plyr-tooltip::before{bottom:-6px;border-right:6px solid transparent;border-top:6px solid #fff;border-left:6px solid transparent;z-index:2}.plyr button.tab-focus:focus .plyr-tooltip,.plyr button:hover .plyr-tooltip{opacity:1;-webkit-transform:translate(-50%,0) scale(1);transform:translate(-50%,0) scale(1)}.plyr button:hover .plyr-tooltip{z-index:3}.plyr-progress{position:absolute;bottom:100%;left:0;right:0;width:100%;height:10px;background:rgba(86,93,100,.2)}.plyr-progress-buffer[value],.plyr-progress-played[value],.plyr-progress-seek[type=range]{position:absolute;left:0;top:0;width:100%;height:10px;margin:0;padding:0;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;border:none;background:0 0}.plyr-progress-buffer[value]::-webkit-progress-bar,.plyr-progress-played[value]::-webkit-progress-bar{background:0 0}.plyr-progress-buffer[value]::-webkit-progress-value,.plyr-progress-played[value]::-webkit-progress-value{background:currentColor}.plyr-progress-buffer[value]::-moz-progress-bar,.plyr-progress-played[value]::-moz-progress-bar{background:currentColor}.plyr-progress-played[value]{z-index:2;color:#3498DB}.plyr-progress-buffer[value]{color:rgba(86,93,100,.25)}.plyr-progress-seek[type=range]{z-index:4;cursor:pointer;outline:0}.plyr-progress-seek[type=range]::-webkit-slider-runnable-track{background:0 0;border:0}.plyr-progress-seek[type=range]::-webkit-slider-thumb{-webkit-appearance:none;background:0 0;border:0;width:20px;height:10px}.plyr-progress-seek[type=range]::-moz-range-track{background:0 0;border:0}.plyr-progress-seek[type=range]::-moz-range-thumb{-moz-appearance:none;background:0 0;border:0;width:20px;height:10px}.plyr-progress-seek[type=range]::-ms-track{color:transparent;background:0 0;border:0}.plyr-progress-seek[type=range]::-ms-fill-lower,.plyr-progress-seek[type=range]::-ms-fill-upper{background:0 0;border:0}.plyr-progress-seek[type=range]::-ms-thumb{background:0 0;border:0;width:20px;height:10px}.plyr-progress-seek[type=range]::-moz-focus-outer{border:0}.plyr.loading .plyr-progress-buffer{-webkit-animation:progress 1s linear infinite;animation:progress 1s linear infinite;background-size:40px 40px;background-repeat:repeat-x;background-color:rgba(86,93,100,.25);background-image:linear-gradient(-45deg,rgba(0,0,0,.15) 25%,transparent 25%,transparent 50%,rgba(0,0,0,.15) 50%,rgba(0,0,0,.15) 75%,transparent 75%,transparent);color:transparent}.plyr-controls [data-plyr=pause],.plyr.playing .plyr-controls [data-plyr=play]{display:none}.plyr.playing .plyr-controls [data-plyr=pause]{display:inline-block}.plyr-volume[type=range]{display:inline-block;vertical-align:middle;-webkit-appearance:none;-moz-appearance:none;width:100px;margin:0 10px 0 0;padding:0;cursor:pointer;background:0 0;border:none}.plyr-volume[type=range]::-webkit-slider-runnable-track{height:6px;background:#e6e6e6;border:0;border-radius:3px}.plyr-volume[type=range]::-webkit-slider-thumb{-webkit-appearance:none;margin-top:-3px;height:12px;width:12px;background:#6B7D86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.plyr-volume[type=range]::-moz-range-track{height:6px;background:#e6e6e6;border:0;border-radius:3px}.plyr-volume[type=range]::-moz-range-thumb{height:12px;width:12px;background:#6B7D86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.plyr-volume[type=range]::-ms-track{height:6px;background:0 0;border-color:transparent;border-width:3px 0;color:transparent}.plyr-volume[type=range]::-ms-fill-lower,.plyr-volume[type=range]::-ms-fill-upper{height:6px;background:#e6e6e6;border:0;border-radius:3px}.plyr-volume[type=range]::-ms-thumb{height:12px;width:12px;background:#6B7D86;border:0;border-radius:6px;transition:background .3s ease;cursor:ew-resize}.plyr-volume[type=range]:focus::-webkit-slider-thumb{background:#3498DB}.plyr-volume[type=range]:focus::-moz-range-thumb{background:#3498DB}.plyr-volume[type=range]:focus::-ms-thumb{background:#3498DB}.plyr-audio.ios .plyr-controls-right,.plyr.ios .plyr-volume,.plyr.ios [data-plyr=mute]{display:none}.plyr-audio.ios .plyr-controls-left{float:none}.plyr-audio .plyr-controls{padding-top:20px}.plyr-audio .plyr-progress{bottom:auto;top:0;background:#D6DADD}.plyr-fullscreen,.plyr.fullscreen-active{position:fixed;top:0;left:0;right:0;bottom:0;height:100%;width:100%;z-index:10000000;background:#000}.plyr-fullscreen video,.plyr.fullscreen-active video{height:100%}.plyr-fullscreen .plyr-video-wrapper,.plyr.fullscreen-active .plyr-video-wrapper{height:100%;width:100%}.plyr-fullscreen .plyr-controls,.plyr.fullscreen-active .plyr-controls{position:absolute;bottom:0;left:0;right:0}.plyr-fullscreen.fullscreen-hide-controls.playing .plyr-controls,.plyr.fullscreen-active.fullscreen-hide-controls.playing .plyr-controls{-webkit-transform:translateY(100%) translateY(5px);transform:translateY(100%) translateY(5px);transition:-webkit-transform .3s .2s ease;transition:transform .3s .2s ease;transition:transform .3s .2s ease,-webkit-transform .3s .2s ease}.plyr-fullscreen.fullscreen-hide-controls.playing.plyr-hover .plyr-controls,.plyr.fullscreen-active.fullscreen-hide-controls.playing.plyr-hover .plyr-controls{-webkit-transform:translateY(0);transform:translateY(0)}.plyr-fullscreen.fullscreen-hide-controls.playing .plyr-captions,.plyr.fullscreen-active.fullscreen-hide-controls.playing .plyr-captions{bottom:5px;transition:bottom .3s .2s ease}.plyr-fullscreen .plyr-captions,.plyr-fullscreen.fullscreen-hide-controls.playing.plyr-hover .plyr-captions,.plyr.fullscreen-active .plyr-captions,.plyr.fullscreen-active.fullscreen-hide-controls.playing.plyr-hover .plyr-captions{top:auto;bottom:90px}@media (min-width:560px){.plyr-fullscreen .plyr-captions,.plyr-fullscreen.fullscreen-hide-controls.playing.plyr-hover .plyr-captions,.plyr.fullscreen-active .plyr-captions,.plyr.fullscreen-active.fullscreen-hide-controls.playing.plyr-hover .plyr-captions{bottom:60px}}.plyr.captions-active .plyr-controls .icon-captions-on,.plyr.fullscreen-active .icon-exit-fullscreen,.plyr.muted .plyr-controls .icon-muted{display:block}.plyr [data-plyr=captions],.plyr [data-plyr=fullscreen],.plyr.captions-active .plyr-controls .icon-captions-on+svg,.plyr.fullscreen-active .icon-exit-fullscreen+svg,.plyr.muted .plyr-controls .icon-muted+svg{display:none}.plyr.captions-enabled [data-plyr=captions],.plyr.fullscreen-enabled [data-plyr=fullscreen]{display:inline-block}
\ No newline at end of file diff --git a/dist/plyr.js b/dist/plyr.js index 51c4cc20..4402a6e4 100644 --- a/dist/plyr.js +++ b/dist/plyr.js @@ -1 +1 @@ -!function(e){"use strict";function t(){var e=['<div class="player-controls">','<div class="player-progress">','<label for="seek{id}" class="sr-only">Seek</label>','<input id="seek{id}" class="player-progress-seek" type="range" min="0" max="100" step="0.5" value="0" data-player="seek">','<progress class="player-progress-played" max="100" value="0">',"<span>0</span>% "+C.i18n.played,"</progress>",'<progress class="player-progress-buffer" max="100" value="0">',"<span>0</span>% "+C.i18n.buffered,"</progress>","</div>",'<span class="player-controls-left">'];return o(C.controls,"restart")&&e.push('<button type="button" data-player="restart">','<svg><use xlink:href="#'+C.iconPrefix+'-restart" /></svg>','<span class="sr-only">'+C.i18n.restart+"</span>","</button>"),o(C.controls,"rewind")&&e.push('<button type="button" data-player="rewind">','<svg><use xlink:href="#'+C.iconPrefix+'-rewind" /></svg>','<span class="sr-only">'+C.i18n.rewind+"</span>","</button>"),o(C.controls,"play")&&e.push('<button type="button" data-player="play">','<svg><use xlink:href="#'+C.iconPrefix+'-play" /></svg>','<span class="sr-only">'+C.i18n.play+"</span>","</button>",'<button type="button" data-player="pause">','<svg><use xlink:href="#'+C.iconPrefix+'-pause" /></svg>','<span class="sr-only">'+C.i18n.pause+"</span>","</button>"),o(C.controls,"fast-forward")&&e.push('<button type="button" data-player="fast-forward">','<svg><use xlink:href="#'+C.iconPrefix+'-fast-forward" /></svg>','<span class="sr-only">'+C.i18n.forward+"</span>","</button>"),o(C.controls,"current-time")&&e.push('<span class="player-time">','<span class="sr-only">'+C.i18n.currentTime+"</span>",'<span class="player-current-time">00:00</span>',"</span>"),o(C.controls,"duration")&&e.push('<span class="player-time">','<span class="sr-only">'+C.i18n.duration+"</span>",'<span class="player-duration">00:00</span>',"</span>"),e.push("</span>",'<span class="player-controls-right">'),o(C.controls,"mute")&&e.push('<button type="button" data-player="mute">','<svg class="icon-muted"><use xlink:href="#'+C.iconPrefix+'-muted" /></svg>','<svg><use xlink:href="#'+C.iconPrefix+'-volume" /></svg>','<span class="sr-only">'+C.i18n.toggleMute+"</span>","</button>"),o(C.controls,"volume")&&e.push('<label for="volume{id}" class="sr-only">'+C.i18n.volume+"</label>",'<input id="volume{id}" class="player-volume" type="range" min="0" max="10" value="5" data-player="volume">'),o(C.controls,"captions")&&e.push('<button type="button" data-player="captions">','<svg class="icon-captions-on"><use xlink:href="#'+C.iconPrefix+'-captions-on" /></svg>','<svg><use xlink:href="#'+C.iconPrefix+'-captions-off" /></svg>','<span class="sr-only">'+C.i18n.toggleCaptions+"</span>","</button>"),o(C.controls,"fullscreen")&&e.push('<button type="button" data-player="fullscreen">','<svg class="icon-exit-fullscreen"><use xlink:href="#'+C.iconPrefix+'-exit-fullscreen" /></svg>','<svg><use xlink:href="#'+C.iconPrefix+'-enter-fullscreen" /></svg>','<span class="sr-only">'+C.i18n.toggleFullscreen+"</span>","</button>"),e.push("</span>","</div>"),e.join("")}function n(e,t){C.debug&&window.console&&console[t?"error":"log"](e)}function r(){var e,t,n,r=navigator.userAgent,a=navigator.appName,s=""+parseFloat(navigator.appVersion),o=parseInt(navigator.appVersion,10);return-1!==navigator.appVersion.indexOf("Windows NT")&&-1!==navigator.appVersion.indexOf("rv:11")?(a="IE",s="11;"):-1!==(t=r.indexOf("MSIE"))?(a="IE",s=r.substring(t+5)):-1!==(t=r.indexOf("Chrome"))?(a="Chrome",s=r.substring(t+7)):-1!==(t=r.indexOf("Safari"))?(a="Safari",s=r.substring(t+7),-1!==(t=r.indexOf("Version"))&&(s=r.substring(t+8))):-1!==(t=r.indexOf("Firefox"))?(a="Firefox",s=r.substring(t+8)):(e=r.lastIndexOf(" ")+1)<(t=r.lastIndexOf("/"))&&(a=r.substring(e,t),s=r.substring(t+1),a.toLowerCase()==a.toUpperCase()&&(a=navigator.appName)),-1!==(n=s.indexOf(";"))&&(s=s.substring(0,n)),-1!==(n=s.indexOf(" "))&&(s=s.substring(0,n)),o=parseInt(""+s,10),isNaN(o)&&(s=""+parseFloat(navigator.appVersion),o=parseInt(navigator.appVersion,10)),{name:a,version:o,ios:/(iPad|iPhone|iPod)/g.test(navigator.platform)}}function a(e,t){var n=e.media;if("video"==e.type)switch(t){case"video/webm":return!(!n.canPlayType||!n.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/,""));case"video/mp4":return!(!n.canPlayType||!n.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/,""));case"video/ogg":return!(!n.canPlayType||!n.canPlayType('video/ogg; codecs="theora"').replace(/no/,""))}else if("audio"==e.type)switch(t){case"audio/mpeg":return!(!n.canPlayType||!n.canPlayType("audio/mpeg;").replace(/no/,""));case"audio/ogg":return!(!n.canPlayType||!n.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/,""));case"audio/wav":return!(!n.canPlayType||!n.canPlayType('audio/wav; codecs="1"').replace(/no/,""))}return!1}function s(e){if(!document.querySelectorAll('script[src="'+e+'"]').length){var t=document.createElement("script");t.src=e;var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n)}}function o(e,t){return Array.prototype.indexOf&&-1!=e.indexOf(t)}function i(e,t,n){return e.replace(new RegExp(t.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),n)}function u(e,t){e.length||(e=[e]);for(var n=e.length-1;n>=0;n--){var r=n>0?t.cloneNode(!0):t,a=e[n],s=a.parentNode,o=a.nextSibling;r.appendChild(a),o?s.insertBefore(r,o):s.appendChild(r)}}function l(e){for(var t=e.parentNode;e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}function c(e){e.parentNode.removeChild(e)}function p(e,t){e.insertBefore(t,e.firstChild)}function d(e,t){for(var n in t)e.setAttribute(n,t[n])}function f(e,t,n){if(e)if(e.classList)e.classList[n?"add":"remove"](t);else{var r=(" "+e.className+" ").replace(/\s+/g," ").replace(" "+t+" ","");e.className=r+(n?" "+t:"")}}function m(e,t,n,r){var a=t.split(" ");if(e instanceof NodeList)for(var s=0;s<e.length;s++)e[s]instanceof Node&&m(e[s],arguments[1],arguments[2],arguments[3]);else for(var o=0;o<a.length;o++)e[r?"addEventListener":"removeEventListener"](a[o],n,!1)}function y(e,t,n){e&&m(e,t,n,!0)}function b(e,t,n){e&&m(e,t,n,!1)}function v(e,t){var n=document.createEvent("MouseEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function g(e,t){return t="boolean"==typeof t?t:!e.getAttribute("aria-pressed"),e.setAttribute("aria-pressed",t),t}function h(e,t){return 0===e||0===t||isNaN(e)||isNaN(t)?0:(e/t*100).toFixed(2)}function w(e,t){for(var n in t)t[n]&&t[n].constructor&&t[n].constructor===Object?(e[n]=e[n]||{},w(e[n],t[n])):e[n]=t[n];return e}function k(){var e={supportsFullScreen:!1,isFullScreen:function(){return!1},requestFullScreen:function(){},cancelFullScreen:function(){},fullScreenEventName:"",element:null,prefix:""},t="webkit moz o ms khtml".split(" ");if("undefined"!=typeof document.cancelFullScreen)e.supportsFullScreen=!0;else for(var n=0,r=t.length;r>n;n++){if(e.prefix=t[n],"undefined"!=typeof document[e.prefix+"CancelFullScreen"]){e.supportsFullScreen=!0;break}if("undefined"!=typeof document.msExitFullscreen&&document.msFullscreenEnabled){e.prefix="ms",e.supportsFullScreen=!0;break}}return e.supportsFullScreen&&(e.fullScreenEventName="ms"==e.prefix?"MSFullscreenChange":e.prefix+"fullscreenchange",e.isFullScreen=function(e){switch("undefined"==typeof e&&(e=document.body),this.prefix){case"":return document.fullscreenElement==e;case"moz":return document.mozFullScreenElement==e;default:return document[this.prefix+"FullscreenElement"]==e}},e.requestFullScreen=function(e){return"undefined"==typeof e&&(e=document.body),""===this.prefix?e.requestFullScreen():e[this.prefix+("ms"==this.prefix?"RequestFullscreen":"RequestFullScreen")]()},e.cancelFullScreen=function(){return""===this.prefix?document.cancelFullScreen():document[this.prefix+("ms"==this.prefix?"ExitFullscreen":"CancelFullScreen")]()},e.element=function(){return""===this.prefix?document.fullscreenElement:document[this.prefix+"FullscreenElement"]}),e}function x(){var e={supported:function(){try{return"localStorage"in window&&null!==window.localStorage}catch(e){return!1}}()};return e}function T(o){function w(e){if(!fe.usingTextTracks&&"video"===fe.type&&fe.supported.full){for(fe.subcount=0,e="number"==typeof e?e:fe.media.currentTime;A(fe.captions[fe.subcount][0])<e.toFixed(1);)if(fe.subcount++,fe.subcount>fe.captions.length-1){fe.subcount=fe.captions.length-1;break}if(fe.media.currentTime.toFixed(1)>=E(fe.captions[fe.subcount][0])&&fe.media.currentTime.toFixed(1)<=A(fe.captions[fe.subcount][0])){fe.currentCaption=fe.captions[fe.subcount][1];var t=fe.currentCaption.trim();fe.captionsContainer.innerHTML!=t&&(fe.captionsContainer.innerHTML="",fe.captionsContainer.innerHTML=t)}else fe.captionsContainer.innerHTML=""}}function T(){fe.buttons.captions&&(f(fe.container,C.classes.captions.enabled,!0),C.captions.defaultActive&&(f(fe.container,C.classes.captions.active,!0),g(fe.buttons.captions,!0)))}function E(e){var t=[];return t=e.split(" --> "),P(t[0])}function A(e){var t=[];return t=e.split(" --> "),P(t[1])}function P(e){if(null===e||void 0===e)return 0;var t,n=[],r=[];return n=e.split(","),r=n[0].split(":"),t=Math.floor(60*r[0]*60)+Math.floor(60*r[1])+Math.floor(r[2])}function N(e){return fe.container.querySelectorAll(e)}function M(e){return N(e)[0]}function I(){try{return window.self!==window.top}catch(e){return!0}}function L(){var e=C.html;if(n("Injecting custom controls."),e||(e=t()),e=i(e,"{seektime}",C.seekTime),e=i(e,"{id}",Math.floor(1e4*Math.random())),fe.container.insertAdjacentHTML("beforeend",e),C.tooltips)for(var r=N(C.selectors.labels),a=r.length-1;a>=0;a--){var s=r[a];f(s,C.classes.hidden,!1),f(s,C.classes.tooltip,!0)}}function O(){try{return fe.controls=M(C.selectors.controls),fe.buttons={},fe.buttons.seek=M(C.selectors.buttons.seek),fe.buttons.play=M(C.selectors.buttons.play),fe.buttons.pause=M(C.selectors.buttons.pause),fe.buttons.restart=M(C.selectors.buttons.restart),fe.buttons.rewind=M(C.selectors.buttons.rewind),fe.buttons.forward=M(C.selectors.buttons.forward),fe.buttons.fullscreen=M(C.selectors.buttons.fullscreen),fe.buttons.mute=M(C.selectors.buttons.mute),fe.buttons.captions=M(C.selectors.buttons.captions),fe.checkboxes=N('[type="checkbox"]'),fe.progress={},fe.progress.container=M(C.selectors.progress.container),fe.progress.buffer={},fe.progress.buffer.bar=M(C.selectors.progress.buffer),fe.progress.buffer.text=fe.progress.buffer.bar&&fe.progress.buffer.bar.getElementsByTagName("span")[0],fe.progress.played={},fe.progress.played.bar=M(C.selectors.progress.played),fe.progress.played.text=fe.progress.played.bar&&fe.progress.played.bar.getElementsByTagName("span")[0],fe.volume=M(C.selectors.buttons.volume),fe.duration=M(C.selectors.duration),fe.currentTime=M(C.selectors.currentTime),fe.seekTime=N(C.selectors.seekTime),!0}catch(e){return n("It looks like there's a problem with your controls html. Bailing.",!0),fe.media.setAttribute("controls",""),!1}}function q(){if(fe.buttons.play){var e=fe.buttons.play.innerText||C.i18n.play;"undefined"!=typeof C.title&&C.title.length&&(e+=", "+C.title),fe.buttons.play.setAttribute("aria-label",e)}}function V(){if(!fe.media)return n("No audio or video element found!",!0),!1;if(fe.supported.full&&(fe.media.removeAttribute("controls"),f(fe.container,C.classes.type.replace("{0}",fe.type),!0),f(fe.container,C.classes.stopped,null===fe.media.getAttribute("autoplay")&&!C.autoplay),fe.browser.ios&&f(fe.container,"ios",!0),"video"===fe.type)){var e=document.createElement("div");e.setAttribute("class",C.classes.videoWrapper),u(fe.media,e),fe.videoContainer=e}"youtube"==fe.type&&H(fe.media.getAttribute("data-video-id")),(null!==fe.media.getAttribute("autoplay")||C.autoplay)&&D()}function H(e){for(var t=N('[id^="youtube"]'),n=t.length-1;n>=0;n--)c(t[n]);var r=document.createElement("div");r.setAttribute("id","youtube-"+Math.floor(1e4*Math.random())),fe.media.appendChild(r),f(fe.media,C.classes.videoWrapper,!0),f(fe.media,C.classes.embedWrapper,!0),"object"==typeof YT?R(e,r):(s("https://www.youtube.com/iframe_api"),S.youtube.push(function(){R(e,r)}),window.onYouTubeIframeAPIReady=function(){for(var e=S.youtube.length-1;e>=0;e--)S.youtube[e](),S.youtube.splice(e,1)})}function R(e,t){n("YouTube API Ready"),"timer"in fe||(fe.timer={}),fe.embed=new YT.Player(t.id,{videoId:e,playerVars:{autoplay:C.autoplay?1:0,controls:fe.supported.full?0:1,rel:0,showinfo:0,iv_load_policy:3,cc_load_policy:C.captions.defaultActive?1:0,cc_lang_pref:"en",wmode:"transparent",modestbranding:1,disablekb:1},events:{onReady:function(e){var t=e.target;fe.media.play=function(){t.playVideo()},fe.media.pause=function(){t.pauseVideo()},fe.media.stop=function(){t.stopVideo()},fe.media.duration=t.getDuration(),fe.media.paused=!0,fe.media.currentTime=t.getCurrentTime(),fe.media.muted=t.isMuted(),v(fe.media,"timeupdate"),window.clearInterval(fe.timer.buffering),fe.timer.buffering=window.setInterval(function(){fe.media.buffered=t.getVideoLoadedFraction(),v(fe.media,"progress"),1===fe.media.buffered&&window.clearInterval(fe.timer.buffering)},200),fe.supported.full&&(fe.container.querySelectorAll(C.selectors.controls).length||de(),C.displayDuration&&re())},onStateChange:function(e){var t=e.target;switch(window.clearInterval(fe.timer.playing),e.data){case 0:fe.media.paused=!0,v(fe.media,"ended");break;case 1:fe.media.paused=!1,v(fe.media,"play"),fe.timer.playing=window.setInterval(function(){fe.media.currentTime=t.getCurrentTime(),v(fe.media,"timeupdate")},200);break;case 2:fe.media.paused=!0,v(fe.media,"pause")}}}})}function B(){if("video"===fe.type){fe.videoContainer.insertAdjacentHTML("afterbegin",'<div class="'+C.selectors.captions.replace(".","")+'"><span></span></div>'),fe.captionsContainer=M(C.selectors.captions).querySelector("span"),fe.usingTextTracks=!1,fe.media.textTracks&&(fe.usingTextTracks=!0);for(var e,t="",r=fe.media.childNodes,a=0;a<r.length;a++)"track"===r[a].nodeName.toLowerCase()&&(e=r[a].kind,("captions"===e||"subtitles"===e)&&(t=r[a].getAttribute("src")));if(fe.captionExists=!0,""===t?(fe.captionExists=!1,n("No caption track found.")):n("Caption track found; URI: "+t),fe.captionExists){for(var s=fe.media.textTracks,o=0;o<s.length;o++)s[o].mode="hidden";if(T(fe),("IE"===fe.browser.name&&fe.browser.version>=10||"Firefox"===fe.browser.name&&fe.browser.version>=31||"Chrome"===fe.browser.name&&fe.browser.version>=43||"Safari"===fe.browser.name&&fe.browser.version>=7)&&(n("Detected unsupported browser for HTML5 captions. Using fallback."),fe.usingTextTracks=!1),fe.usingTextTracks){n("TextTracks supported.");for(var i=0;i<s.length;i++){var u=s[i];("captions"===u.kind||"subtitles"===u.kind)&&y(u,"cuechange",function(){fe.captionsContainer.innerHTML="",this.activeCues[0]&&this.activeCues[0].hasOwnProperty("text")&&fe.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML().trim())})}}else if(n("TextTracks not supported so rendering captions manually."),fe.currentCaption="",fe.captions=[],""!==t){var l=new XMLHttpRequest;l.onreadystatechange=function(){if(4===l.readyState)if(200===l.status){var e,t=[],r=l.responseText;t=r.split("\n\n");for(var a=0;a<t.length;a++)e=t[a],fe.captions[a]=[],fe.captions[a]=e.split("\n");fe.captions.shift(),n("Successfully loaded the caption file via AJAX.")}else n("There was a problem loading the caption file via AJAX.",!0)},l.open("get",t,!0),l.send()}if("Safari"===fe.browser.name&&fe.browser.version>=7){n("Safari 7+ detected; removing track from DOM."),s=fe.media.getElementsByTagName("track");for(var c=0;c<s.length;c++)fe.media.removeChild(s[c])}}else f(fe.container,C.classes.captions.enabled)}}function j(){if("audio"!=fe.type&&C.fullscreen.enabled){var e=F.supportsFullScreen;e||C.fullscreen.fallback&&!I()?(n((e?"Native":"Fallback")+" fullscreen enabled."),f(fe.container,C.classes.fullscreen.enabled,!0)):n("Fullscreen not supported and fallback disabled."),g(fe.buttons.fullscreen,!1),C.fullscreen.hideControls&&f(fe.container,C.classes.fullscreen.hideControls,!0)}}function D(){fe.media.play()}function _(){fe.media.pause()}function W(e){e===!0?D():e===!1?_():fe.media[fe.media.paused?"play":"pause"]()}function Y(e){"number"!=typeof e&&(e=C.seekTime),U(fe.media.currentTime-e)}function z(e){"number"!=typeof e&&(e=C.seekTime),U(fe.media.currentTime+e)}function U(e){var t=0,r=fe.media.paused;"number"==typeof e?t=e:"object"!=typeof e||"input"!==e.type&&"change"!==e.type||(t=e.target.value/e.target.max*fe.media.duration),0>t?t=0:t>fe.media.duration&&(t=fe.media.duration);try{fe.media.currentTime=t.toFixed(1)}catch(a){}"youtube"==fe.type&&(fe.embed.seekTo(t),r&&_(),v(fe.media,"timeupdate")),n("Seeking to "+fe.media.currentTime+" seconds"),w(t)}function X(){f(fe.container,C.classes.playing,!fe.media.paused),f(fe.container,C.classes.stopped,fe.media.paused)}function J(e){function t(){f(fe.container,C.classes.hover,!0),window.clearTimeout(a),s||(a=window.setTimeout(function(){f(fe.container,C.classes.hover,!1)},2e3))}function n(e){s="mouseenter"===e.type}var r=F.supportsFullScreen;e&&e.type===F.fullScreenEventName?fe.isFullscreen=F.isFullScreen(fe.container):r?(F.isFullScreen(fe.container)?F.cancelFullScreen():F.requestFullScreen(fe.container),fe.isFullscreen=F.isFullScreen(fe.container)):(fe.isFullscreen=!fe.isFullscreen,fe.isFullscreen?(y(document,"keyup",$),document.body.style.overflow="hidden"):(b(document,"keyup",$),document.body.style.overflow="")),f(fe.container,C.classes.fullscreen.active,fe.isFullscreen),g(fe.buttons.fullscreen,fe.isFullscreen);var a,s=!1;C.fullscreen.hideControls&&(f(fe.controls,C.classes.hover,!1),m(fe.controls,"mouseenter mouseleave",n,fe.isFullscreen),m(fe.container,"mousemove",t,fe.isFullscreen))}function $(e){27===(e.which||e.charCode||e.keyCode)&&fe.isFullscreen&&J()}function G(e){"undefined"==typeof e&&(e=C.storage.enabled&&x().supported?window.localStorage[C.storage.key]||C.volume:C.volume),e>10&&(e=10),0>e&&(e=0),fe.media.volume=parseFloat(e/10),"youtube"==fe.type&&(fe.embed.setVolume(100*fe.media.volume),v(fe.media,"volumechange")),fe.media.muted&&e>0&&K()}function K(e){"boolean"!=typeof e&&(e=!fe.media.muted),g(fe.buttons.mute,e),fe.media.muted=e,"youtube"===fe.type&&(fe.embed[fe.media.muted?"mute":"unMute"](),v(fe.media,"volumechange"))}function Q(){var e=fe.media.muted?0:10*fe.media.volume;fe.supported.full&&fe.volume&&(fe.volume.value=e),C.storage.enabled&&x().supported&&window.localStorage.setItem(C.storage.key,e),f(fe.container,C.classes.muted,0===e),fe.supported.full&&fe.buttons.mute&&g(fe.buttons.mute,0===e)}function Z(e){fe.supported.full&&fe.buttons.captions&&("boolean"!=typeof e&&(e=-1===fe.container.className.indexOf(C.classes.captions.active)),g(fe.buttons.captions,e),f(fe.container,C.classes.captions.active,e))}function ee(e){var t="waiting"===e.type;clearTimeout(fe.loadingTimer),fe.loadingTimer=setTimeout(function(){f(fe.container,C.classes.loading,t)},t?250:0)}function te(e){var t=fe.progress.played.bar,n=fe.progress.played.text,r=0;if(e)switch(e.type){case"timeupdate":case"seeking":r=h(fe.media.currentTime,fe.media.duration),"timeupdate"==e.type&&fe.buttons.seek&&(fe.buttons.seek.value=r);break;case"change":case"input":r=e.target.value;break;case"playing":case"progress":t=fe.progress.buffer.bar,n=fe.progress.buffer.text,r=function(){var e=fe.media.buffered;return e&&e.length?h(e.end(0),fe.media.duration):"number"==typeof e?100*e:0}()}t&&(t.value=r),n&&(n.innerHTML=r)}function ne(e,t){if(t){fe.secs=parseInt(e%60),fe.mins=parseInt(e/60%60),fe.hours=parseInt(e/60/60%60);var n=parseInt(fe.media.duration/60/60%60)>0;fe.secs=("0"+fe.secs).slice(-2),fe.mins=("0"+fe.mins).slice(-2),t.innerHTML=(n?fe.hours+":":"")+fe.mins+":"+fe.secs}}function re(){var e=fe.media.duration||0;!fe.duration&&C.displayDuration&&fe.media.paused&&ne(e,fe.currentTime),fe.duration&&ne(e,fe.duration)}function ae(e){ne(fe.media.currentTime,fe.currentTime),te(e)}function se(){for(var e=fe.media.querySelectorAll("source"),t=e.length-1;t>=0;t--)c(e[t]);fe.media.removeAttribute("src")}function oe(e){if(e.src){var t=document.createElement("source");d(t,e),p(fe.media,t)}}function ie(e){if("youtube"===fe.type&&"string"==typeof e)return fe.embed.destroy(),H(e),void ae();if(_(),U(),se(),"string"==typeof e)oe({src:e});else if(e.constructor===Array)for(var t in e)oe(e[t]);fe.supported.full&&(ae(),X()),fe.media.load(),(null!==fe.media.getAttribute("autoplay")||C.autoplay)&&D()}function ue(e){"video"===fe.type&&fe.media.setAttribute("poster",e)}function le(){function e(){var e=document.activeElement;e=e&&e!=document.body?document.querySelector(":focus"):null;for(var t in fe.buttons){var n=fe.buttons[t];f(n,"tab-focus",n===e)}}var t="IE"==fe.browser.name?"change":"input";y(window,"keyup",function(t){var n=t.keyCode?t.keyCode:t.which;9==n&&e()});for(var n in fe.buttons){var r=fe.buttons[n];y(r,"blur",function(){f(r,"tab-focus",!1)})}y(fe.buttons.play,"click",function(){D(),setTimeout(function(){fe.buttons.pause.focus()},100)}),y(fe.buttons.pause,"click",function(){_(),setTimeout(function(){fe.buttons.play.focus()},100)}),y(fe.buttons.restart,"click",U),y(fe.buttons.rewind,"click",Y),y(fe.buttons.forward,"click",z),y(fe.buttons.seek,t,U),y(fe.volume,t,function(){G(this.value)}),y(fe.buttons.mute,"click",K),y(fe.buttons.fullscreen,"click",J),F.supportsFullScreen&&y(document,F.fullScreenEventName,J),y(fe.media,"timeupdate seeking",ae),y(fe.media,"timeupdate",w),y(fe.media,"loadedmetadata",re),y(fe.buttons.captions,"click",Z),y(fe.media,"ended",function(){"video"===fe.type&&(fe.captionsContainer.innerHTML=""),X()}),y(fe.media,"progress playing",te),y(fe.media,"volumechange",Q),y(fe.media,"play pause",X),y(fe.media,"waiting canplay seeked",ee),"video"===fe.type&&C.click&&y(fe.videoContainer,"click",function(){fe.media.paused?v(fe.buttons.play,"click"):fe.media.ended?(U(),v(fe.buttons.play,"click")):v(fe.buttons.pause,"click")})}function ce(){if(!fe.init)return null;if(fe.container.setAttribute("class",C.selectors.container.replace(".","")),fe.init=!1,c(M(C.selectors.controls)),"youtube"===fe.type)return void fe.embed.destroy();"video"===fe.type&&(c(M(C.selectors.captions)),l(fe.videoContainer)),fe.media.setAttribute("controls","");var e=fe.media.cloneNode(!0);fe.media.parentNode.replaceChild(e,fe.media)}function pe(){if(fe.init)return null;F=k(),fe.browser=r(),fe.media=fe.container.querySelectorAll("audio, video, div")[0];var t=fe.media.tagName.toLowerCase();if("div"===t?fe.type=fe.media.getAttribute("data-type"):fe.type=t,fe.supported=e.supported(fe.type),!fe.supported.basic)return!1;if(n(fe.browser.name+" "+fe.browser.version),V(),"video"==fe.type||"audio"==fe.type){if(!fe.supported.full)return void(fe.init=!0);de(),C.displayDuration&&re(),q()}fe.init=!0}function de(){return L(),O()?(B(),G(),Q(),j(),void le()):!1}var fe=this;return fe.container=o,pe(),fe.init?{media:fe.media,play:D,pause:_,restart:U,rewind:Y,forward:z,seek:U,source:ie,poster:ue,setVolume:G,togglePlay:W,toggleMute:K,toggleCaptions:Z,toggleFullscreen:J,isFullscreen:function(){return fe.isFullscreen||!1},support:function(e){return a(fe,e)},destroy:ce,restore:pe}:{}}var F,C,S={youtube:[]},E={enabled:!0,debug:!1,autoplay:!1,seekTime:10,volume:5,click:!0,tooltips:!1,displayDuration:!0,iconPrefix:"icon",selectors:{container:".player",controls:".player-controls",labels:"[data-player] .sr-only, label .sr-only",buttons:{seek:'[data-player="seek"]',play:'[data-player="play"]',pause:'[data-player="pause"]',restart:'[data-player="restart"]',rewind:'[data-player="rewind"]',forward:'[data-player="fast-forward"]',mute:'[data-player="mute"]',volume:'[data-player="volume"]',captions:'[data-player="captions"]',fullscreen:'[data-player="fullscreen"]'},progress:{container:".player-progress",buffer:".player-progress-buffer",played:".player-progress-played"},captions:".player-captions",currentTime:".player-current-time",duration:".player-duration"},classes:{videoWrapper:"player-video-wrapper",embedWrapper:"player-video-embed",type:"player-{0}",stopped:"stopped",playing:"playing",muted:"muted",loading:"loading",tooltip:"player-tooltip",hidden:"sr-only",hover:"player-hover",captions:{enabled:"captions-enabled",active:"captions-active"},fullscreen:{enabled:"fullscreen-enabled",active:"fullscreen-active",hideControls:"fullscreen-hide-controls"}},captions:{defaultActive:!1},fullscreen:{enabled:!0,fallback:!0,hideControls:!0},storage:{enabled:!0,key:"plyr_volume"},controls:["restart","rewind","play","fast-forward","current-time","duration","mute","volume","captions","fullscreen"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",played:"played",buffered:"buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",toggleMute:"Toggle Mute",toggleCaptions:"Toggle Captions",toggleFullscreen:"Toggle Fullscreen"}};e.supported=function(e){var t,n,a=r(),s="IE"===a.name&&a.version<=9,o=/iPhone|iPod/i.test(navigator.userAgent),i=!!document.createElement("audio").canPlayType,u=!!document.createElement("video").canPlayType;switch(e){case"video":t=u,n=t&&!s&&!o;break;case"audio":t=i,n=t&&!s;break;case"youtube":t=!0,n=!s&&!o;break;default:t=i&&u,n=t&&!s}return{basic:t,full:n}},e.setup=function(t){if(C=w(E,t),!C.enabled||!e.supported().basic)return!1;for(var n=document.querySelectorAll(C.selectors.container),r=[],a=n.length-1;a>=0;a--){var s=n[a];if("undefined"==typeof s.plyr){var o=new T(s);s.plyr=Object.keys(o).length?o:!1,"function"==typeof C.onSetup&&C.onSetup.apply(s.plyr)}r.push(s.plyr)}return r}}(this.plyr=this.plyr||{});
\ No newline at end of file +!function(e){"use strict";function t(){var e=['<div class="plyr-controls">','<div class="plyr-progress">','<label for="seek{id}" class="sr-only">Seek</label>','<input id="seek{id}" class="plyr-progress-seek" type="range" min="0" max="100" step="0.5" value="0" data-plyr="seek">','<progress class="plyr-progress-played" max="100" value="0">',"<span>0</span>% "+E.i18n.played,"</progress>",'<progress class="plyr-progress-buffer" max="100" value="0">',"<span>0</span>% "+E.i18n.buffered,"</progress>","</div>",'<span class="plyr-controls-left">'];return s(E.controls,"restart")&&e.push('<button type="button" data-plyr="restart">','<svg><use xlink:href="#'+E.iconPrefix+'-restart" /></svg>','<span class="sr-only">'+E.i18n.restart+"</span>","</button>"),s(E.controls,"rewind")&&e.push('<button type="button" data-plyr="rewind">','<svg><use xlink:href="#'+E.iconPrefix+'-rewind" /></svg>','<span class="sr-only">'+E.i18n.rewind+"</span>","</button>"),s(E.controls,"play")&&e.push('<button type="button" data-plyr="play">','<svg><use xlink:href="#'+E.iconPrefix+'-play" /></svg>','<span class="sr-only">'+E.i18n.play+"</span>","</button>",'<button type="button" data-plyr="pause">','<svg><use xlink:href="#'+E.iconPrefix+'-pause" /></svg>','<span class="sr-only">'+E.i18n.pause+"</span>","</button>"),s(E.controls,"fast-forward")&&e.push('<button type="button" data-plyr="fast-forward">','<svg><use xlink:href="#'+E.iconPrefix+'-fast-forward" /></svg>','<span class="sr-only">'+E.i18n.forward+"</span>","</button>"),s(E.controls,"current-time")&&e.push('<span class="plyr-time">','<span class="sr-only">'+E.i18n.currentTime+"</span>",'<span class="plyr-current-time">00:00</span>',"</span>"),s(E.controls,"duration")&&e.push('<span class="plyr-time">','<span class="sr-only">'+E.i18n.duration+"</span>",'<span class="plyr-duration">00:00</span>',"</span>"),e.push("</span>",'<span class="plyr-controls-right">'),s(E.controls,"mute")&&e.push('<button type="button" data-plyr="mute">','<svg class="icon-muted"><use xlink:href="#'+E.iconPrefix+'-muted" /></svg>','<svg><use xlink:href="#'+E.iconPrefix+'-volume" /></svg>','<span class="sr-only">'+E.i18n.toggleMute+"</span>","</button>"),s(E.controls,"volume")&&e.push('<label for="volume{id}" class="sr-only">'+E.i18n.volume+"</label>",'<input id="volume{id}" class="plyr-volume" type="range" min="0" max="10" value="5" data-plyr="volume">'),s(E.controls,"captions")&&e.push('<button type="button" data-plyr="captions">','<svg class="icon-captions-on"><use xlink:href="#'+E.iconPrefix+'-captions-on" /></svg>','<svg><use xlink:href="#'+E.iconPrefix+'-captions-off" /></svg>','<span class="sr-only">'+E.i18n.toggleCaptions+"</span>","</button>"),s(E.controls,"fullscreen")&&e.push('<button type="button" data-plyr="fullscreen">','<svg class="icon-exit-fullscreen"><use xlink:href="#'+E.iconPrefix+'-exit-fullscreen" /></svg>','<svg><use xlink:href="#'+E.iconPrefix+'-enter-fullscreen" /></svg>','<span class="sr-only">'+E.i18n.toggleFullscreen+"</span>","</button>"),e.push("</span>","</div>"),e.join("")}function n(e,t){E.debug&&window.console&&console[t?"error":"log"](e)}function r(){var e,t,n,r=navigator.userAgent,a=navigator.appName,o=""+parseFloat(navigator.appVersion),s=parseInt(navigator.appVersion,10);return-1!==navigator.appVersion.indexOf("Windows NT")&&-1!==navigator.appVersion.indexOf("rv:11")?(a="IE",o="11;"):-1!==(t=r.indexOf("MSIE"))?(a="IE",o=r.substring(t+5)):-1!==(t=r.indexOf("Chrome"))?(a="Chrome",o=r.substring(t+7)):-1!==(t=r.indexOf("Safari"))?(a="Safari",o=r.substring(t+7),-1!==(t=r.indexOf("Version"))&&(o=r.substring(t+8))):-1!==(t=r.indexOf("Firefox"))?(a="Firefox",o=r.substring(t+8)):(e=r.lastIndexOf(" ")+1)<(t=r.lastIndexOf("/"))&&(a=r.substring(e,t),o=r.substring(t+1),a.toLowerCase()==a.toUpperCase()&&(a=navigator.appName)),-1!==(n=o.indexOf(";"))&&(o=o.substring(0,n)),-1!==(n=o.indexOf(" "))&&(o=o.substring(0,n)),s=parseInt(""+o,10),isNaN(s)&&(o=""+parseFloat(navigator.appVersion),s=parseInt(navigator.appVersion,10)),{name:a,version:s,ios:/(iPad|iPhone|iPod)/g.test(navigator.platform)}}function a(e,t){var n=e.media;if("video"==e.type)switch(t){case"video/webm":return!(!n.canPlayType||!n.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/,""));case"video/mp4":return!(!n.canPlayType||!n.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/,""));case"video/ogg":return!(!n.canPlayType||!n.canPlayType('video/ogg; codecs="theora"').replace(/no/,""))}else if("audio"==e.type)switch(t){case"audio/mpeg":return!(!n.canPlayType||!n.canPlayType("audio/mpeg;").replace(/no/,""));case"audio/ogg":return!(!n.canPlayType||!n.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/,""));case"audio/wav":return!(!n.canPlayType||!n.canPlayType('audio/wav; codecs="1"').replace(/no/,""))}return!1}function o(e){if(!document.querySelectorAll('script[src="'+e+'"]').length){var t=document.createElement("script");t.src=e;var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n)}}function s(e,t){return Array.prototype.indexOf&&-1!=e.indexOf(t)}function i(e,t,n){return e.replace(new RegExp(t.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),n)}function l(e,t){e.length||(e=[e]);for(var n=e.length-1;n>=0;n--){var r=n>0?t.cloneNode(!0):t,a=e[n],o=a.parentNode,s=a.nextSibling;r.appendChild(a),s?o.insertBefore(r,s):o.appendChild(r)}}function u(e){for(var t=e.parentNode;e.firstChild;)t.insertBefore(e.firstChild,e);t.removeChild(e)}function c(e){e.parentNode.removeChild(e)}function d(e,t){e.insertBefore(t,e.firstChild)}function p(e,t){for(var n in t)e.setAttribute(n,"boolean"==typeof t[n]&&t[n]?"":t[n])}function m(e,t,n){var r=document.createElement(e);p(r,n),d(t,r)}function f(e){return e.replace(".","")}function y(e,t,n){if(e)if(e.classList)e.classList[n?"add":"remove"](t);else{var r=(" "+e.className+" ").replace(/\s+/g," ").replace(" "+t+" ","");e.className=r+(n?" "+t:"")}}function b(e,t,n,r){var a=t.split(" ");if(e instanceof NodeList)for(var o=0;o<e.length;o++)e[o]instanceof Node&&b(e[o],arguments[1],arguments[2],arguments[3]);else for(var s=0;s<a.length;s++)e[r?"addEventListener":"removeEventListener"](a[s],n,!1)}function v(e,t,n){e&&b(e,t,n,!0)}function g(e,t,n){e&&b(e,t,n,!1)}function h(e,t){var n=document.createEvent("MouseEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function w(e,t){return t="boolean"==typeof t?t:!e.getAttribute("aria-pressed"),e.setAttribute("aria-pressed",t),t}function k(e,t){return 0===e||0===t||isNaN(e)||isNaN(t)?0:(e/t*100).toFixed(2)}function T(e,t){for(var n in t)t[n]&&t[n].constructor&&t[n].constructor===Object?(e[n]=e[n]||{},T(e[n],t[n])):e[n]=t[n];return e}function x(){var e={supportsFullScreen:!1,isFullScreen:function(){return!1},requestFullScreen:function(){},cancelFullScreen:function(){},fullScreenEventName:"",element:null,prefix:""},t="webkit moz o ms khtml".split(" ");if("undefined"!=typeof document.cancelFullScreen)e.supportsFullScreen=!0;else for(var n=0,r=t.length;r>n;n++){if(e.prefix=t[n],"undefined"!=typeof document[e.prefix+"CancelFullScreen"]){e.supportsFullScreen=!0;break}if("undefined"!=typeof document.msExitFullscreen&&document.msFullscreenEnabled){e.prefix="ms",e.supportsFullScreen=!0;break}}return e.supportsFullScreen&&(e.fullScreenEventName="ms"==e.prefix?"MSFullscreenChange":e.prefix+"fullscreenchange",e.isFullScreen=function(e){switch("undefined"==typeof e&&(e=document.body),this.prefix){case"":return document.fullscreenElement==e;case"moz":return document.mozFullScreenElement==e;default:return document[this.prefix+"FullscreenElement"]==e}},e.requestFullScreen=function(e){return"undefined"==typeof e&&(e=document.body),""===this.prefix?e.requestFullScreen():e[this.prefix+("ms"==this.prefix?"RequestFullscreen":"RequestFullScreen")]()},e.cancelFullScreen=function(){return""===this.prefix?document.cancelFullScreen():document[this.prefix+("ms"==this.prefix?"ExitFullscreen":"CancelFullScreen")]()},e.element=function(){return""===this.prefix?document.fullscreenElement:document[this.prefix+"FullscreenElement"]}),e}function F(){var e={supported:function(){try{return"localStorage"in window&&null!==window.localStorage}catch(e){return!1}}()};return e}function C(T){function C(e){if(!ve.usingTextTracks&&"video"===ve.type&&ve.supported.full&&(ve.subcount=0,e="number"==typeof e?e:ve.media.currentTime,ve.captions[ve.subcount])){for(;P(ve.captions[ve.subcount][0])<e.toFixed(1);)if(ve.subcount++,ve.subcount>ve.captions.length-1){ve.subcount=ve.captions.length-1;break}if(ve.media.currentTime.toFixed(1)>=N(ve.captions[ve.subcount][0])&&ve.media.currentTime.toFixed(1)<=P(ve.captions[ve.subcount][0])){ve.currentCaption=ve.captions[ve.subcount][1];var t=ve.currentCaption.trim();ve.captionsContainer.innerHTML!=t&&(ve.captionsContainer.innerHTML="",ve.captionsContainer.innerHTML=t)}else ve.captionsContainer.innerHTML=""}}function A(){ve.buttons.captions&&(y(ve.container,E.classes.captions.enabled,!0),E.captions.defaultActive&&(y(ve.container,E.classes.captions.active,!0),w(ve.buttons.captions,!0)))}function N(e){var t=[];return t=e.split(" --> "),I(t[0])}function P(e){var t=[];return t=e.split(" --> "),I(t[1])}function I(e){if(null===e||void 0===e)return 0;var t,n=[],r=[];return n=e.split(","),r=n[0].split(":"),t=Math.floor(60*r[0]*60)+Math.floor(60*r[1])+Math.floor(r[2])}function M(e){return ve.container.querySelectorAll(e)}function L(e){return M(e)[0]}function O(){try{return window.self!==window.top}catch(e){return!0}}function V(){var e=E.html;if(n("Injecting custom controls."),e||(e=t()),e=i(e,"{seektime}",E.seekTime),e=i(e,"{id}",Math.floor(1e4*Math.random())),ve.container.insertAdjacentHTML("beforeend",e),E.tooltips)for(var r=M(E.selectors.labels),a=r.length-1;a>=0;a--){var o=r[a];y(o,E.classes.hidden,!1),y(o,E.classes.tooltip,!0)}}function q(){try{return ve.controls=L(E.selectors.controls),ve.buttons={},ve.buttons.seek=L(E.selectors.buttons.seek),ve.buttons.play=L(E.selectors.buttons.play),ve.buttons.pause=L(E.selectors.buttons.pause),ve.buttons.restart=L(E.selectors.buttons.restart),ve.buttons.rewind=L(E.selectors.buttons.rewind),ve.buttons.forward=L(E.selectors.buttons.forward),ve.buttons.fullscreen=L(E.selectors.buttons.fullscreen),ve.buttons.mute=L(E.selectors.buttons.mute),ve.buttons.captions=L(E.selectors.buttons.captions),ve.checkboxes=M('[type="checkbox"]'),ve.progress={},ve.progress.container=L(E.selectors.progress.container),ve.progress.buffer={},ve.progress.buffer.bar=L(E.selectors.progress.buffer),ve.progress.buffer.text=ve.progress.buffer.bar&&ve.progress.buffer.bar.getElementsByTagName("span")[0],ve.progress.played={},ve.progress.played.bar=L(E.selectors.progress.played),ve.progress.played.text=ve.progress.played.bar&&ve.progress.played.bar.getElementsByTagName("span")[0],ve.volume=L(E.selectors.buttons.volume),ve.duration=L(E.selectors.duration),ve.currentTime=L(E.selectors.currentTime),ve.seekTime=M(E.selectors.seekTime),!0}catch(e){return n("It looks like there's a problem with your controls html. Bailing.",!0),ve.media.setAttribute("controls",""),!1}}function H(){if(ve.buttons.play){var e=ve.buttons.play.innerText||E.i18n.play;"undefined"!=typeof E.title&&E.title.length&&(e+=", "+E.title),ve.buttons.play.setAttribute("aria-label",e)}}function j(){if(!ve.media)return n("No audio or video element found!",!0),!1;if(ve.supported.full&&(ve.media.removeAttribute("controls"),y(ve.container,E.classes.type.replace("{0}",ve.type),!0),y(ve.container,E.classes.stopped,E.autoplay),ve.browser.ios&&y(ve.container,"ios",!0),"video"===ve.type)){var e=document.createElement("div");e.setAttribute("class",E.classes.videoWrapper),l(ve.media,e),ve.videoContainer=e}s(E.types.embed,ve.type)?(D(ve.embedId,ve.type),ve.embedId=null):E.autoplay&&$()}function D(e){for(var t=document.createElement("div"),n=ve.type+"-"+Math.floor(1e4*Math.random()),r=M('[id^="'+ve.type+'-"]'),a=r.length-1;a>=0;a--)c(r[a]);if(y(ve.media,E.classes.videoWrapper,!0),y(ve.media,E.classes.embedWrapper,!0),"youtube"===ve.type)ve.media.appendChild(t),t.setAttribute("id",n),"object"==typeof YT?R(e,t):(o(E.urls.youtube.api),window.onYouTubeIframeAPIReady=function(){R(e,t)});else if("vimeo"===ve.type){var s=document.createElement("iframe");if(s.loaded=!1,v(s,"load",function(){s.loaded=!0}),p(s,{src:"https://player.vimeo.com/video/"+e+"?player_id="+n+"&api=1&badge=0&byline=0&portrait=0&title=0",id:n,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",frameborder:0}),t.appendChild(s),ve.media.appendChild(t),"function"==typeof Froogaloop)v(s,"load",_);else{o(E.urls.vimeo.api);var i=window.setInterval(function(){"$f"in window&&s.loaded&&(window.clearInterval(i),_.call(s))},50)}}}function B(){ve.supported.full&&(ve.container.querySelectorAll(E.selectors.controls).length||ye()),te(),ne()}function R(e,t){"timer"in ve||(ve.timer={}),ve.embed=new YT.Player(t.id,{videoId:e,playerVars:{autoplay:E.autoplay?1:0,controls:ve.supported.full?0:1,rel:0,showinfo:0,iv_load_policy:3,cc_load_policy:E.captions.defaultActive?1:0,cc_lang_pref:"en",wmode:"transparent",modestbranding:1,disablekb:1},events:{onReady:function(e){var t=e.target;ve.media.play=function(){t.playVideo()},ve.media.pause=function(){t.pauseVideo()},ve.media.stop=function(){t.stopVideo()},ve.media.duration=t.getDuration(),ve.media.paused=!E.autoplay,ve.media.currentTime=t.getCurrentTime(),ve.media.muted=t.isMuted(),h(ve.media,"timeupdate"),window.clearInterval(ve.timer.buffering),ve.timer.buffering=window.setInterval(function(){ve.media.buffered=t.getVideoLoadedFraction(),h(ve.media,"progress"),1===ve.media.buffered&&window.clearInterval(ve.timer.buffering)},200),B(),E.displayDuration&&ie()},onStateChange:function(e){var t=e.target;switch(window.clearInterval(ve.timer.playing),e.data){case 0:ve.media.paused=!0,h(ve.media,"ended");break;case 1:ve.media.paused=!1,h(ve.media,"play"),ve.timer.playing=window.setInterval(function(){ve.media.currentTime=t.getCurrentTime(),h(ve.media,"timeupdate")},200);break;case 2:ve.media.paused=!0,h(ve.media,"pause")}}}})}function _(){ve.embed=$f(this),ve.embed.addEvent("ready",function(){ve.media.play=function(){ve.embed.api("play")},ve.media.pause=function(){ve.embed.api("pause")},ve.media.stop=function(){ve.embed.api("stop")},ve.media.paused=!E.autoplay,ve.media.currentTime=0,B(),ve.embed.api("getCurrentTime",function(e){ve.media.currentTime=e,h(ve.media,"timeupdate")}),ve.embed.api("getDuration",function(e){ve.media.duration=e,ve.supported.full&&E.displayDuration&&ie()}),ve.embed.addEvent("play",function(){ve.media.paused=!1,h(ve.media,"play")}),ve.embed.addEvent("pause",function(){ve.media.paused=!0,h(ve.media,"pause")}),ve.embed.addEvent("playProgress",function(e){ve.media.currentTime=e.seconds,h(ve.media,"timeupdate")}),ve.embed.addEvent("loadProgress",function(e){ve.media.buffered=e.percent,h(ve.media,"progress")}),ve.embed.addEvent("finish",function(){ve.media.paused=!0,h(ve.media,"ended")})})}function W(){if("video"===ve.type){L(E.selectors.captions)||ve.videoContainer.insertAdjacentHTML("afterbegin",'<div class="'+f(E.selectors.captions)+'"><span></span></div>'),ve.captionsContainer=L(E.selectors.captions).querySelector("span"),ve.usingTextTracks=!1,ve.media.textTracks&&(ve.usingTextTracks=!0);for(var e,t="",r=ve.media.childNodes,a=0;a<r.length;a++)"track"===r[a].nodeName.toLowerCase()&&(e=r[a].kind,("captions"===e||"subtitles"===e)&&(t=r[a].getAttribute("src")));if(ve.captionExists=!0,""===t?(ve.captionExists=!1,n("No caption track found.")):n("Caption track found; URI: "+t),ve.captionExists){for(var o=ve.media.textTracks,s=0;s<o.length;s++)o[s].mode="hidden";if(A(ve),("IE"===ve.browser.name&&ve.browser.version>=10||"Firefox"===ve.browser.name&&ve.browser.version>=31||"Chrome"===ve.browser.name&&ve.browser.version>=43||"Safari"===ve.browser.name&&ve.browser.version>=7)&&(n("Detected unsupported browser for HTML5 captions. Using fallback."),ve.usingTextTracks=!1),ve.usingTextTracks){n("TextTracks supported.");for(var i=0;i<o.length;i++){var l=o[i];("captions"===l.kind||"subtitles"===l.kind)&&v(l,"cuechange",function(){ve.captionsContainer.innerHTML="",this.activeCues[0]&&this.activeCues[0].hasOwnProperty("text")&&ve.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML().trim())})}}else if(n("TextTracks not supported so rendering captions manually."),ve.currentCaption="",ve.captions=[],""!==t){var u=new XMLHttpRequest;u.onreadystatechange=function(){if(4===u.readyState)if(200===u.status){var e,t=[],r=u.responseText;t=r.split("\n\n");for(var a=0;a<t.length;a++)e=t[a],ve.captions[a]=[],ve.captions[a]=e.split("\n");ve.captions.shift(),n("Successfully loaded the caption file via AJAX.")}else n("There was a problem loading the caption file via AJAX.",!0)},u.open("get",t,!0),u.send()}if("Safari"===ve.browser.name&&ve.browser.version>=7){n("Safari 7+ detected; removing track from DOM."),o=ve.media.getElementsByTagName("track");for(var c=0;c<o.length;c++)ve.media.removeChild(o[c])}}else y(ve.container,E.classes.captions.enabled)}}function z(){if(("audio"!=ve.type||E.fullscreen.allowAudio)&&E.fullscreen.enabled){var e=S.supportsFullScreen;e||E.fullscreen.fallback&&!O()?(n((e?"Native":"Fallback")+" fullscreen enabled."),y(ve.container,E.classes.fullscreen.enabled,!0)):n("Fullscreen not supported and fallback disabled."),w(ve.buttons.fullscreen,!1),E.fullscreen.hideControls&&y(ve.container,E.classes.fullscreen.hideControls,!0)}}function $(){ve.media.play()}function U(){ve.media.pause()}function X(e){e===!0?$():e===!1?U():ve.media[ve.media.paused?"play":"pause"]()}function Y(e){"number"!=typeof e&&(e=E.seekTime),G(ve.media.currentTime-e)}function J(e){"number"!=typeof e&&(e=E.seekTime),G(ve.media.currentTime+e)}function G(e){var t=0,r=ve.media.paused;"number"==typeof e?t=e:"object"!=typeof e||"input"!==e.type&&"change"!==e.type||(t=e.target.value/e.target.max*ve.media.duration),0>t?t=0:t>ve.media.duration&&(t=ve.media.duration);try{ve.media.currentTime=t.toFixed(1)}catch(a){}"embed"in ve&&("youtube"===ve.type&&ve.embed.seekTo(t),"vimeo"===ve.type&&ve.embed.api("seekTo",t),h(ve.media,"timeupdate"),r&&U()),n("Seeking to "+ve.media.currentTime+" seconds"),C(t)}function K(){y(ve.container,E.classes.playing,!ve.media.paused),y(ve.container,E.classes.stopped,ve.media.paused)}function Q(e){function t(){y(ve.container,E.classes.hover,!0),window.clearTimeout(a),o||(a=window.setTimeout(function(){y(ve.container,E.classes.hover,!1)},2e3))}function n(e){o="mouseenter"===e.type}var r=S.supportsFullScreen;e&&e.type===S.fullScreenEventName?ve.isFullscreen=S.isFullScreen(ve.container):r?(S.isFullScreen(ve.container)?S.cancelFullScreen():S.requestFullScreen(ve.container),ve.isFullscreen=S.isFullScreen(ve.container)):(ve.isFullscreen=!ve.isFullscreen,ve.isFullscreen?(v(document,"keyup",Z),document.body.style.overflow="hidden"):(g(document,"keyup",Z),document.body.style.overflow="")),y(ve.container,E.classes.fullscreen.active,ve.isFullscreen),w(ve.buttons.fullscreen,ve.isFullscreen);var a,o=!1;E.fullscreen.hideControls&&(y(ve.controls,E.classes.hover,!1),b(ve.controls,"mouseenter mouseleave",n,ve.isFullscreen),b(ve.container,"mousemove",t,ve.isFullscreen))}function Z(e){27===(e.which||e.charCode||e.keyCode)&&ve.isFullscreen&&Q()}function ee(e){"boolean"!=typeof e&&(e=!ve.media.muted),w(ve.buttons.mute,e),ve.media.muted=e,"youtube"===ve.type&&(ve.embed[ve.media.muted?"mute":"unMute"](),h(ve.media,"volumechange")),"vimeo"===ve.type&&(ve.media.muted?ve.embed.api("setVolume",0):ve.embed.api("setVolume",parseFloat(E.volume/10)),h(ve.media,"volumechange"))}function te(e){"undefined"==typeof e&&(e=E.storage.enabled&&F().supported?window.localStorage[E.storage.key]||E.volume:E.volume),e>10&&(e=10),0>e&&(e=0),ve.media.volume=parseFloat(e/10),E.volume=e,"youtube"===ve.type&&ve.embed.setVolume(100*ve.media.volume),"vimeo"===ve.type&&ve.embed.api("setVolume",ve.media.volume),"embed"in ve&&h(ve.media,"volumechange"),ve.media.muted&&e>0&&ee()}function ne(){var e=ve.media.muted?0:10*ve.media.volume;ve.supported.full&&ve.volume&&(ve.volume.value=e),E.storage.enabled&&F().supported&&window.localStorage.setItem(E.storage.key,e),y(ve.container,E.classes.muted,0===e),ve.supported.full&&ve.buttons.mute&&w(ve.buttons.mute,0===e)}function re(e){ve.supported.full&&ve.buttons.captions&&("boolean"!=typeof e&&(e=-1===ve.container.className.indexOf(E.classes.captions.active)),ve.captionsEnabled=e,w(ve.buttons.captions,ve.captionsEnabled),y(ve.container,E.classes.captions.active,ve.captionsEnabled))}function ae(e){var t="waiting"===e.type;clearTimeout(ve.loadingTimer),ve.loadingTimer=setTimeout(function(){y(ve.container,E.classes.loading,t)},t?250:0)}function oe(e){var t=ve.progress.played.bar,n=ve.progress.played.text,r=0;if(e)switch(e.type){case"timeupdate":case"seeking":r=k(ve.media.currentTime,ve.media.duration),"timeupdate"==e.type&&ve.buttons.seek&&(ve.buttons.seek.value=r);break;case"change":case"input":r=e.target.value;break;case"playing":case"progress":t=ve.progress.buffer.bar,n=ve.progress.buffer.text,r=function(){var e=ve.media.buffered;return e&&e.length?k(e.end(0),ve.media.duration):"number"==typeof e?100*e:0}()}t&&(t.value=r),n&&(n.innerHTML=r)}function se(e,t){if(t){isNaN(e)&&(e=0),ve.secs=parseInt(e%60),ve.mins=parseInt(e/60%60),ve.hours=parseInt(e/60/60%60);var n=parseInt(ve.media.duration/60/60%60)>0;ve.secs=("0"+ve.secs).slice(-2),ve.mins=("0"+ve.mins).slice(-2),t.innerHTML=(n?ve.hours+":":"")+ve.mins+":"+ve.secs}}function ie(){var e=ve.media.duration||0;!ve.duration&&E.displayDuration&&ve.media.paused&&se(e,ve.currentTime),ve.duration&&se(e,ve.duration)}function le(e){se(ve.media.currentTime,ve.currentTime),oe(e)}function ue(e,t){if("string"==typeof t)m(e,ve.media,{src:t});else if(t.constructor===Array)for(var n=t.length-1;n>=0;n--)m(e,ve.media,t[n])}function ce(e){if("undefined"!=typeof e){switch(U(),"youtube"===ve.type?(ve.embed.destroy(),window.clearInterval(ve.timer.buffering),window.clearInterval(ve.timer.playing)):"video"===ve.type&&c(ve.videoContainer),c(ve.media),"type"in e&&e.type!==ve.type&&(ve.type=e.type),ve.type){case"video":ve.media=document.createElement("video");break;case"audio":ve.media=document.createElement("audio");break;case"youtube":case"vimeo":ve.media=document.createElement("div"),ve.embedId="string"==typeof e.sources?e.sources:e.sources[0].src}d(ve.container,ve.media),s(E.types.html5,ve.type)&&(E.crossorigin&&ve.media.setAttribute("crossorigin",""),E.autoplay&&ve.media.setAttribute("autoplay",""),"poster"in e&&ve.media.setAttribute("poster",e.poster),E.loop&&ve.media.setAttribute("loop","")),ve.container.className=ve.originalClassName,y(ve.container,E.classes.fullscreen.active,ve.isFullscreen),y(ve.container,E.classes.captions.active,ve.captionsEnabled),E.autoplay=e.autoplay||E.autoplay,s(E.types.embed,ve.type)&&(ve.embedId=e.sources),s(E.types.html5,ve.type)&&ue("source",e.sources),j(),be(),s(E.types.html5,ve.type)&&(te(),ne(),ve.supported.full&&(le(),K()),"tracks"in e&&(ue("track",e.tracks),W()),ve.media.load(),E.autoplay&&$()),"title"in e&&(E.title=e.title,H())}}function de(e){"video"===ve.type&&ve.media.setAttribute("poster",e)}function pe(){function e(){var e=document.activeElement;e&&e!=document.body?document.querySelector&&(e=document.querySelector(":focus")):e=null;for(var t in ve.buttons){var n=ve.buttons[t];y(n,"tab-focus",n===e)}}var t="IE"==ve.browser.name?"change":"input";v(window,"keyup",function(t){var n=t.keyCode?t.keyCode:t.which;9==n&&e()});for(var n in ve.buttons){var r=ve.buttons[n];v(r,"blur",function(){y(r,"tab-focus",!1)})}v(ve.buttons.play,"click",function(){$(),setTimeout(function(){ve.buttons.pause.focus()},100)}),v(ve.buttons.pause,"click",function(){U(),setTimeout(function(){ve.buttons.play.focus()},100)}),v(ve.buttons.restart,"click",G),v(ve.buttons.rewind,"click",Y),v(ve.buttons.forward,"click",J),v(ve.buttons.seek,t,G),v(ve.volume,t,function(){te(this.value)}),v(ve.buttons.mute,"click",ee),v(ve.buttons.fullscreen,"click",Q),S.supportsFullScreen&&v(document,S.fullScreenEventName,Q),v(ve.media,"timeupdate seeking",le),v(ve.media,"timeupdate",C),v(ve.media,"loadedmetadata",ie),v(ve.buttons.captions,"click",re),v(ve.media,"ended",function(){"video"===ve.type&&(ve.captionsContainer.innerHTML=""),K()}),v(ve.media,"progress playing",oe),v(ve.media,"volumechange",ne),v(ve.media,"play pause",K),v(ve.media,"waiting canplay seeked",ae),"video"===ve.type&&E.click&&v(ve.videoContainer,"click",function(){ve.media.paused?h(ve.buttons.play,"click"):ve.media.ended?(G(),h(ve.buttons.play,"click")):h(ve.buttons.pause,"click")})}function me(){if(!ve.init)return null;if(ve.container.setAttribute("class",f(E.selectors.container)),ve.init=!1,c(L(E.selectors.controls)),"youtube"===ve.type)return void ve.embed.destroy();"video"===ve.type&&(c(L(E.selectors.captions)),u(ve.videoContainer)),ve.media.setAttribute("controls","");var e=ve.media.cloneNode(!0);ve.media.parentNode.replaceChild(e,ve.media)}function fe(){if(ve.init)return null;S=x(),ve.browser=r(),ve.media=ve.container.querySelectorAll("audio, video, div")[0],ve.originalClassName=ve.container.className;var t=ve.media.tagName.toLowerCase();if("div"===t?(ve.type=ve.media.getAttribute("data-type"),ve.embedId=ve.media.getAttribute("data-video-id"),ve.media.removeAttribute("data-type"),ve.media.removeAttribute("data-video-id")):(ve.type=t,E.crossorigin=null!==ve.media.getAttribute("crossorigin"),E.autoplay=E.autoplay||null!==ve.media.getAttribute("autoplay"),E.loop=E.loop||null!==ve.media.getAttribute("loop")),ve.supported=e.supported(ve.type),!ve.supported.basic)return!1;if(n(ve.browser.name+" "+ve.browser.version),j(),"video"==ve.type||"audio"==ve.type){if(!ve.supported.full)return void(ve.init=!0);ye(),E.displayDuration&&ie(),H()}ve.init=!0}function ye(){return V(),q()?(W(),be(),te(),void ne()):!1}function be(){z(),pe()}var ve=this;return ve.container=T,fe(),ve.init?{media:ve.media,play:$,pause:U,restart:G,rewind:Y,forward:J,seek:G,source:ce,poster:de,setVolume:te,togglePlay:X,toggleMute:ee,toggleCaptions:re,toggleFullscreen:Q,isFullscreen:function(){return ve.isFullscreen||!1},support:function(e){return a(ve,e)},destroy:me,restore:fe}:{}}var S,E,A={enabled:!0,debug:!1,autoplay:!1,loop:!1,seekTime:10,volume:5,click:!0,tooltips:!1,displayDuration:!0,iconPrefix:"icon",selectors:{container:".plyr",controls:".plyr-controls",labels:"[data-plyr] .sr-only, label .sr-only",buttons:{seek:'[data-plyr="seek"]',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"]',volume:'[data-plyr="volume"]',captions:'[data-plyr="captions"]',fullscreen:'[data-plyr="fullscreen"]'},progress:{container:".plyr-progress",buffer:".plyr-progress-buffer",played:".plyr-progress-played"},captions:".plyr-captions",currentTime:".plyr-current-time",duration:".plyr-duration"},classes:{videoWrapper:"plyr-video-wrapper",embedWrapper:"plyr-video-embed",type:"plyr-{0}",stopped:"stopped",playing:"playing",muted:"muted",loading:"loading",tooltip:"plyr-tooltip",hidden:"sr-only",hover:"plyr-hover",captions:{enabled:"captions-enabled",active:"captions-active"},fullscreen:{enabled:"fullscreen-enabled",active:"fullscreen-active",hideControls:"fullscreen-hide-controls"}},captions:{defaultActive:!1},fullscreen:{enabled:!0,fallback:!0,hideControls:!0,allowAudio:!1},storage:{enabled:!0,key:"plyr_volume"},controls:["restart","rewind","play","fast-forward","current-time","duration","mute","volume","captions","fullscreen"],i18n:{restart:"Restart",rewind:"Rewind {seektime} secs",play:"Play",pause:"Pause",forward:"Forward {seektime} secs",played:"played",buffered:"buffered",currentTime:"Current time",duration:"Duration",volume:"Volume",toggleMute:"Toggle Mute",toggleCaptions:"Toggle Captions",toggleFullscreen:"Toggle Fullscreen"},types:{embed:["youtube","vimeo"],html5:["video","audio"]},urls:{vimeo:{api:"https://f.vimeocdn.com/js/froogaloop2.min.js"},youtube:{api:"https://www.youtube.com/iframe_api"}}};e.supported=function(e){var t,n,a=r(),o="IE"===a.name&&a.version<=9,s=/iPhone|iPod/i.test(navigator.userAgent),i=!!document.createElement("audio").canPlayType,l=!!document.createElement("video").canPlayType;switch(e){case"video":t=l,n=t&&!o&&!s;break;case"audio":t=i,n=t&&!o;break;case"vimeo":case"youtube":t=!0,n=!o&&!s;break;default:t=i&&l,n=t&&!o}return{basic:t,full:n}},e.setup=function(t,n){var r=[];if("string"==typeof t?t=document.querySelectorAll(t):t instanceof HTMLElement?t=[t]:t instanceof NodeList||"string"==typeof t||("undefined"==typeof n&&"object"==typeof t&&(n=t),t=document.querySelectorAll(A.selectors.container)),E=T(A,n),!E.enabled||!e.supported().basic)return!1;for(var a=t.length-1;a>=0;a--){var o=t[a];if("undefined"==typeof o.plyr){var s=new C(o);o.plyr=Object.keys(s).length?s:!1,"function"==typeof E.onSetup&&E.onSetup.apply(o.plyr)}r.push(o.plyr)}return r}}(this.plyr=this.plyr||{});
\ No newline at end of file diff --git a/dist/sprite.svg b/dist/sprite.svg index b4909d2d..c1f8a560 100644 --- a/dist/sprite.svg +++ b/dist/sprite.svg @@ -1 +1 @@ -<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg"><symbol id="icon-captions-off" viewBox="0 0 18 18"><path d="M1 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1h16c.552 0 1-.448 1-1V3c0-.552-.448-1-1-1H1zm1 12V4h14v10H2z"/></symbol><symbol id="icon-captions-on" viewBox="0 0 18 18"><path d="M1 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1h16c.552 0 1-.448 1-1V3c0-.552-.448-1-1-1H1zm1 12V4h14v10H2z"/><path d="M3 11h3v2H3zM12 11h3v2h-3zM7 11h4v2H7z"/></symbol><symbol id="icon-enter-fullscreen" viewBox="0 0 18 18"><path d="M6.425 10.165l-2.57 2.57.018-1.847c-.003-.552-.45-1-1.002-1.002-.55-.003-.994.442-.99.992l-.024 4.22c0 .264.106.518.295.707.01.007.017.016.026.023.008.007.015.017.023.025.187.188.442.294.706.295l4.22-.023c.55.002.994-.442.992-.992-.003-.55-.45-1-1.002-1.002l-1.847.017 2.568-2.57c.387-.386.387-1.012 0-1.4l-.012-.012c-.387-.386-1.014-.386-1.4 0zM14.154 5.266l-.017 1.846c.003.552.45 1 1.002 1.002.55.003.994-.442.99-.992l.025-4.22c-.002-.264-.107-.518-.296-.707-.01-.007-.017-.016-.026-.023-.008-.007-.015-.017-.023-.025-.187-.188-.442-.294-.706-.295l-4.22.023c-.55-.002-.994.442-.99.992 0 .55.45 1 1 1.002l1.847-.017-2.568 2.57c-.387.386-.387 1.012 0 1.4.4.398 1.026.398 1.413.012l2.57-2.57z"/></symbol><symbol id="icon-exit-fullscreen" viewBox="0 0 18 18"><path d="M14.425 2.165l-2.57 2.57.018-1.847c-.003-.552-.45-1-1.002-1.002-.55-.003-.994.442-.99.992l-.024 4.22c0 .264.106.518.295.707.01.007.017.016.026.023.008.007.015.017.023.025.187.188.442.294.706.295l4.22-.023c.55.002.994-.442.992-.992-.003-.55-.45-1-1.002-1.002l-1.847.017 2.568-2.57c.387-.386.387-1.012 0-1.4l-.012-.012c-.387-.386-1.014-.386-1.4 0zM6.154 13.266l-.017 1.846c.003.552.45 1 1.002 1.002.55.003.994-.442.99-.992l.025-4.22c-.002-.264-.107-.518-.296-.707-.01-.007-.017-.016-.026-.023-.008-.007-.015-.017-.023-.025-.187-.188-.442-.294-.706-.295l-4.22.023c-.55-.002-.994.442-.99.992 0 .55.45 1 1 1.002l1.847-.017-2.568 2.57c-.387.386-.387 1.012 0 1.4.4.398 1.026.398 1.413.012l2.57-2.57z"/></symbol><symbol id="icon-fast-forward" viewBox="0 0 18 18"><path d="M17.57 8.246L7 2c-.552 0-1 .448-1 1v1.954L1 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1l5-2.955V15c0 .552.448 1 1 1l10.57-6.246c.266-.158.43-.444.43-.754s-.164-.597-.43-.754zM6 10.722l-4 2.364V4.914l4 2.364v3.444zm2 2.364V4.914L14.915 9 8 13.086z"/></symbol><symbol id="icon-muted" viewBox="0 0 18 18"><path d="M9.214 2c-.11 0-.225.032-.334.1L4.832 4.91C4.75 4.97 4.65 5 4.55 5H.995C.446 5 0 5.448 0 6v6c0 .552.446 1 .996 1H4.55c.1 0 .2.03.282.09L8.88 15.9c.11.068.223.1.334.1.392 0 .747-.4.747-.95V2.95c0-.55-.354-.95-.746-.95zM7.97 12.834L5.58 11.177c-.166-.115-.364-.178-.566-.178H2.49c-.274 0-.497-.225-.497-.5v-3c0-.277.223-.5.498-.5h2.526c.202 0 .4-.063.566-.18L7.97 5.165v7.67zM14.934 8.8c-.086-1.75-1.514-2.992-2.507-3.65-.47-.312-1.094-.122-1.325.408l-.038.086c-.188.43-.045.94.336 1.194.706.473 1.586 1.247 1.624 2.065.032.676-.553 1.468-1.663 2.27-.397.288-.528.84-.284 1.275l.042.075c.266.475.866.624 1.3.312 1.74-1.25 2.586-2.606 2.516-4.037z"/><path d="M13.957 9.2c.086 1.747 1.514 2.99 2.507 3.648.47.312 1.094.122 1.325-.408l.037-.086c.188-.43.045-.94-.336-1.194-.705-.473-1.585-1.247-1.623-2.065-.032-.676.553-1.468 1.663-2.27.398-.288.53-.84.285-1.275l-.042-.075c-.266-.475-.866-.624-1.3-.312-1.74 1.25-2.586 2.606-2.516 4.037z"/></symbol><symbol id="icon-pause" viewBox="0 0 18 18"><path d="M2 4v10c0 2 2 2 2 2h2s2 0 2-2V4c0-2-2-2-2-2H4S2 2 2 4zm2 0h2v10H4V4zM10 4v10c0 2 2 2 2 2h2s2 0 2-2V4c0-2-2-2-2-2h-2s-2 0-2 2zm2 0h2v10h-2V4z"/></symbol><symbol id="icon-play" viewBox="0 0 18 18"><path d="M5 4.914L11.915 9 5 13.086V4.914zM4 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1l10.57-6.246c.266-.158.43-.444.43-.754s-.164-.597-.43-.754L4 2z"/></symbol><symbol id="icon-restart" viewBox="0 0 18 18"><path d="M1 2c.552 0 1 .448 1 1v4.318L11 2c.552 0 1 .448 1 1v1.954L17 2c.552 0 1 .448 1 1v12c0 .552-.448 1-1 1l-5-2.955V15c0 .552-.448 1-1 1l-9-5.318V15c0 .552-.448 1-1 1s-1-.448-1-1V3c0-.552.448-1 1-1zm11 8.722l4 2.364V4.914l-4 2.364v3.444zm-2 2.364V4.914L3.085 9 10 13.086z"/></symbol><symbol id="icon-rewind" viewBox="0 0 18 21"><path d="M.43 10.754L11 17c.552 0 1-.448 1-1v-1.954L17 17c.552 0 1-.448 1-1V4c0-.552-.448-1-1-1l-5 2.955V4c0-.552-.448-1-1-1L.43 9.246C.165 9.404 0 9.69 0 10s.164.597.43.754zM12 8.278l4-2.364v8.172l-4-2.364V8.278zm-2-2.364v8.172L3.085 10 10 5.914z"/></symbol><symbol id="icon-volume" viewBox="0 0 18 18"><path d="M10.214 2c-.11 0-.225.032-.334.1L5.832 4.91C5.75 4.97 5.65 5 5.55 5H1.995C1.446 5 1 5.448 1 6v6c0 .552.446 1 .996 1H5.55c.1 0 .2.03.282.09L9.88 15.9c.11.068.223.1.334.1.392 0 .747-.4.747-.95V2.95c0-.55-.354-.95-.746-.95zM8.97 12.834L6.58 11.177c-.166-.115-.364-.178-.566-.178H3.49c-.274 0-.497-.225-.497-.5v-3c0-.277.223-.5.498-.5h2.526c.202 0 .4-.063.566-.18L8.97 5.165v7.67zM16.934 8.8c-.086-1.75-1.514-2.992-2.507-3.65-.47-.312-1.094-.122-1.325.408l-.038.086c-.188.43-.045.94.336 1.194.706.473 1.586 1.247 1.624 2.065.032.676-.553 1.468-1.663 2.27-.397.288-.528.84-.284 1.275l.042.075c.266.475.866.624 1.3.312 1.74-1.25 2.586-2.606 2.516-4.037z"/></symbol></svg>
\ No newline at end of file +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg"><symbol id="icon-captions-off" viewBox="0 0 18 18"><title>Captions Off</title><path d="M1 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1h16c.552 0 1-.448 1-1V3c0-.552-.448-1-1-1H1zm1 12V4h14v10H2z"/></symbol><symbol id="icon-captions-on" viewBox="0 0 18 18"><title>Captions On</title><path d="M1 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1h16c.552 0 1-.448 1-1V3c0-.552-.448-1-1-1H1zm1 12V4h14v10H2z"/><path d="M3 11h3v2H3zM12 11h3v2h-3zM7 11h4v2H7z"/></symbol><symbol id="icon-enter-fullscreen" viewBox="0 0 18 18"><title>Enter Fullscreen</title><path d="M10.3 9.7c.7.677 1.4 0 1.4 0L16 5.4V10h2V3c0-.6-.4-1-1-1h-7v2h4.6l-4.3 4.3s-.7.723 0 1.4z"/><path d="M7 2v2H2v10h14v-1h2v2c0 .6-.4 1-1 1H1c-.6 0-1-.4-1-1V3c0-.6.4-1 1-1h6z"/></symbol><symbol id="icon-exit-fullscreen" viewBox="0 0 18 18"><title>Exit Fullscreen</title><path d="M7.7 8.3c-.7-.677-1.4 0-1.4 0L2 12.6V8H0v7c0 .6.4 1 1 1h7v-2H3.4l4.3-4.3s.7-.723 0-1.4z"/><path d="M11 16v-2h5V4H2v1H0V3c0-.6.4-1 1-1h16c.6 0 1 .4 1 1v12c0 .6-.4 1-1 1h-6z"/></symbol><symbol id="icon-fast-forward" viewBox="0 0 18 18"><title>Fast Forward</title><path d="M17.57 8.246L7 2c-.552 0-1 .448-1 1v1.954L1 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1l5-2.955V15c0 .552.448 1 1 1l10.57-6.246c.266-.158.43-.444.43-.754s-.164-.597-.43-.754zM6 10.722l-4 2.364V4.914l4 2.364v3.444zm2 2.364V4.914L14.915 9 8 13.086z"/></symbol><symbol id="icon-muted" viewBox="0 0 18 18"><title>Muted</title><path d="M9.214 2c-.11 0-.225.032-.334.1L4.832 4.91C4.75 4.97 4.65 5 4.55 5H.995C.446 5 0 5.448 0 6v6c0 .552.446 1 .996 1H4.55c.1 0 .2.03.282.09L8.88 15.9c.11.068.223.1.334.1.392 0 .747-.4.747-.95V2.95c0-.55-.354-.95-.746-.95zM7.97 12.834L5.58 11.177c-.166-.115-.364-.178-.566-.178H2.49c-.274 0-.497-.225-.497-.5v-3c0-.277.223-.5.498-.5h2.526c.202 0 .4-.063.566-.18L7.97 5.165v7.67zM14.934 8.8c-.086-1.75-1.514-2.992-2.507-3.65-.47-.312-1.094-.122-1.325.408l-.038.086c-.188.43-.045.94.336 1.194.706.473 1.586 1.247 1.624 2.065.032.676-.553 1.468-1.663 2.27-.397.288-.528.84-.284 1.275l.042.075c.266.475.866.624 1.3.312 1.74-1.25 2.586-2.606 2.516-4.037z"/><path d="M13.957 9.2c.086 1.747 1.514 2.99 2.507 3.648.47.312 1.094.122 1.325-.408l.037-.086c.188-.43.045-.94-.336-1.194-.705-.473-1.585-1.247-1.623-2.065-.032-.676.553-1.468 1.663-2.27.398-.288.53-.84.285-1.275l-.042-.075c-.266-.475-.866-.624-1.3-.312-1.74 1.25-2.586 2.606-2.516 4.037z"/></symbol><symbol id="icon-pause" viewBox="0 0 18 18"><title>Pause</title><path d="M2 4v10c0 2 2 2 2 2h2s2 0 2-2V4c0-2-2-2-2-2H4S2 2 2 4zm2 0h2v10H4V4zM10 4v10c0 2 2 2 2 2h2s2 0 2-2V4c0-2-2-2-2-2h-2s-2 0-2 2zm2 0h2v10h-2V4z"/></symbol><symbol id="icon-play" viewBox="0 0 18 18"><title>Play</title><path d="M5 4.914L11.915 9 5 13.086V4.914zM4 2c-.552 0-1 .448-1 1v12c0 .552.448 1 1 1l10.57-6.246c.266-.158.43-.444.43-.754s-.164-.597-.43-.754L4 2z"/></symbol><symbol id="icon-restart" viewBox="0 0 18 18"><title>Restart</title><path d="M1 2c.552 0 1 .448 1 1v4.318L11 2c.552 0 1 .448 1 1v1.954L17 2c.552 0 1 .448 1 1v12c0 .552-.448 1-1 1l-5-2.955V15c0 .552-.448 1-1 1l-9-5.318V15c0 .552-.448 1-1 1s-1-.448-1-1V3c0-.552.448-1 1-1zm11 8.722l4 2.364V4.914l-4 2.364v3.444zm-2 2.364V4.914L3.085 9 10 13.086z"/></symbol><symbol id="icon-rewind" viewBox="0 0 18 21"><title>Rewind</title><path d="M.43 10.754L11 17c.552 0 1-.448 1-1v-1.954L17 17c.552 0 1-.448 1-1V4c0-.552-.448-1-1-1l-5 2.955V4c0-.552-.448-1-1-1L.43 9.246C.165 9.404 0 9.69 0 10s.164.597.43.754zM12 8.278l4-2.364v8.172l-4-2.364V8.278zm-2-2.364v8.172L3.085 10 10 5.914z"/></symbol><symbol id="icon-volume" viewBox="0 0 18 18"><title>Volume</title><path d="M10.214 2c-.11 0-.225.032-.334.1L5.832 4.91C5.75 4.97 5.65 5 5.55 5H1.995C1.446 5 1 5.448 1 6v6c0 .552.446 1 .996 1H5.55c.1 0 .2.03.282.09L9.88 15.9c.11.068.223.1.334.1.392 0 .747-.4.747-.95V2.95c0-.55-.354-.95-.746-.95zM8.97 12.834L6.58 11.177c-.166-.115-.364-.178-.566-.178H3.49c-.274 0-.497-.225-.497-.5v-3c0-.277.223-.5.498-.5h2.526c.202 0 .4-.063.566-.18L8.97 5.165v7.67zM16.934 8.8c-.086-1.75-1.514-2.992-2.507-3.65-.47-.312-1.094-.122-1.325.408l-.038.086c-.188.43-.045.94.336 1.194.706.473 1.586 1.247 1.624 2.065.032.676-.553 1.468-1.663 2.27-.397.288-.528.84-.284 1.275l.042.075c.266.475.866.624 1.3.312 1.74-1.25 2.586-2.606 2.516-4.037z"/></symbol></svg>
\ No newline at end of file diff --git a/docs/dist/docs.css b/docs/dist/docs.css index dfbc0cb4..38dcd187 100644 --- a/docs/dist/docs.css +++ b/docs/dist/docs.css @@ -1 +1 @@ -/*! normalize.css v2.1.3 | MIT License | git.io/normalize */a.logo,img,legend{border:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,small,summary{display:block}[hidden],template{display:none}body,figure,ul li{margin:0}body,h1,h2{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}body,small{padding:0 10px}nav ul,ul li{list-style:none;padding:0}legend,nav ul,ul li{padding:0}.btn-bar,sub,sup{position:relative}.example-video .player iframe,.example-video .player-video iframe,.example-video .player-youtube iframe{-webkit-mask-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC)}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a{background:0 0;text-decoration:none;color:#3498db;border-bottom:1px dotted currentColor;transition:background .3s ease,color .3s ease,border .3s ease}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}.btn-bar,nav li{white-space:nowrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}.btn-bar::before,.btn-count::before{content:"";top:50%}sub{bottom:-.25em}svg:not(:root){overflow:hidden}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@-webkit-keyframes fade-in{0%{opacity:0}100%{opacity:1}}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-medium.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-medium.woff) format("woff");font-style:normal;font-weight:400}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-bold.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-bold.woff) format("woff");font-style:normal;font-weight:600}h1,h2{letter-spacing:-.025em;color:#2E3C44;margin:0 0 10px;line-height:1.2}h1{font-size:64px;font-size:4rem;color:#3498DB}p,small{margin:0 0 20px}small{font-size:14px;font-size:.875rem}a:focus,a:hover{color:#343f4a;border-bottom-color:transparent}a:focus{outline:#343f4a dotted thin;outline-offset:1px}.color-vimeo{color:#19b7ed}.color-youtube{color:#cc181e}*,::after,::before{box-sizing:border-box}.btn-bar ul,nav li{display:inline-block}html{height:100%;font-size:100%;background:linear-gradient(#fff,#f2f5f7) fixed}body{font-family:Avenir,"Helvetica Neue",Helvetica,Arial,sans-serif;line-height:1.5;text-align:center;color:#55646b}header{padding:20px;margin-bottom:20px}header p{font-size:18px;font-size:1.125rem}section{padding-bottom:20px}@media (min-width:480px){header{padding-top:60px;padding-bottom:60px}section{padding-bottom:40px}}.icon{fill:currentColor;width:18px;height:18px;vertical-align:-3px}a svg,button svg,label svg{pointer-events:none}.btn .icon,a .icon{margin-right:10px}nav ul{margin:0;font-size:0}nav li{margin-top:10px;font-size:16px;font-size:1rem}nav li+li{margin-left:20px}.btn-bar{margin:0 auto 20px;max-width:1200px}.btn-bar::before{position:absolute;left:0;right:0;height:1px;background:#dbe3e8}.btn-bar ul{position:relative;z-index:1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn-bar li{margin:0}.btn-bar li:first-child .btn{border-radius:4px 0 0 4px}.btn-bar li:last-child .btn{border-radius:0 4px 4px 0}.btn-bar li+li .btn{margin-left:-1px}.btn-bar .btn{display:block;border-radius:0}.btn-bar .btn.active{box-shadow:inset 0 1px 1px rgba(0,0,0,.2);position:relative;z-index:1}.btn-bar .btn.active .icon{color:inherit}@media (min-width:560px){.btn-bar{margin-bottom:40px}}.btn,.btn-count{display:inline-block;vertical-align:middle;border-radius:4px;font-weight:600;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn{padding:10px 20px;background:#f2f5f7;border:1px solid #cbd0d3;box-shadow:inset 0 1px 0 #fff,0 1px 1px rgba(0,0,0,.05);text-shadow:0 1px 1px #fff;color:#55646b;transition:background .3s ease,border .3s ease,color .3s ease}.btn:focus,.btn:hover{border-color:#b5bcc0;color:#55646b;outline:0}.btn-youtube .icon{color:#cc181e}.btn-vimeo .icon{color:#19b7ed}.btn-twitter .icon{color:#4BAAF4}.btn-bar .active,.btn-primary{background-image:linear-gradient(#3498db,#2791d9);background-color:#3498db;border-color:#217dbb;box-shadow:0 1px 1px rgba(0,0,0,.15);text-shadow:0 1px 1px rgba(0,0,0,.1);color:#fff}.btn-primary:focus,.btn-primary:hover{color:#fff;border-color:#196090}.btn-small{padding-top:7px;padding-bottom:7px}.btn-count{position:relative;margin-left:10px;padding:10px 15px;background:#fff;border:1px solid #cbd0d3}.btn-count::before{position:absolute;display:block;width:8px;height:8px;left:1px;margin-top:-4px;background:inherit;border:inherit;border-width:1px 0 0 1px;-webkit-transform:rotate(-45deg) translate(-50%,-50%);transform:rotate(-45deg) translate(-50%,-50%)}.panel{display:none}.panel.active{display:block;-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease}.error body,html.error{height:100%}.error body{width:100%;display:table;table-layout:fixed}.error main{display:table-cell;width:100%;vertical-align:middle}.example-audio .player,.example-video .player{margin:0 auto 20px}.example-audio .player-controls,.example-video .player-controls{border-radius:0 0 4px 4px}.example-audio .player{max-width:520px}.example-audio .player-controls{border-radius:4px}.example-audio .player-progress{border-radius:4px 4px 0 0;overflow:hidden}.example-video .player{max-width:1200px}.example-video .player iframe,.example-video .player video{border-radius:4px}.example-video .player-video iframe,.example-video .player-video video,.example-video .player-youtube iframe,.example-video .player-youtube video{border-radius:4px 4px 0 0}.example-video .player-video-fullscreen,.example-video .player-video.fullscreen-active,.example-video .player-youtube-fullscreen,.example-video .player-youtube.fullscreen-active{max-width:none}.example-video .player-video-fullscreen .player-controls,.example-video .player-video-fullscreen iframe,.example-video .player-video-fullscreen video,.example-video .player-video.fullscreen-active .player-controls,.example-video .player-video.fullscreen-active iframe,.example-video .player-video.fullscreen-active video,.example-video .player-youtube-fullscreen .player-controls,.example-video .player-youtube-fullscreen iframe,.example-video .player-youtube-fullscreen video,.example-video .player-youtube.fullscreen-active .player-controls,.example-video .player-youtube.fullscreen-active iframe,.example-video .player-youtube.fullscreen-active video{border-radius:0}.example-video .player-video-fullscreen iframe,.example-video .player-video.fullscreen-active iframe,.example-video .player-youtube-fullscreen iframe,.example-video .player-youtube.fullscreen-active iframe{-webkit-mask-image:none}
\ No newline at end of file +/*! normalize.css v2.1.3 | MIT License | git.io/normalize */a.logo,img,legend{border:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,small,summary{display:block}[hidden],template{display:none}body,figure,ul li{margin:0}body,h1,h2{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}body,small{padding:0 10px}nav ul,ul li{list-style:none;padding:0}legend,nav ul,ul li{padding:0}.btn-bar,sub,sup{position:relative}.btn-bar,.plyr{max-width:1200px}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a{background:0 0;text-decoration:none;color:#3498db;border-bottom:1px dotted currentColor;transition:background .3s ease,color .3s ease,border .3s ease}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}.btn-bar,nav li{white-space:nowrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}sub,sup{font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}.btn-bar::before,.btn-count::before{content:"";top:50%}sub{bottom:-.25em}svg:not(:root){overflow:hidden}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@-webkit-keyframes fade-in{0%{opacity:0}100%{opacity:1}}@keyframes fade-in{0%{opacity:0}100%{opacity:1}}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-medium.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-medium.woff) format("woff");font-style:normal;font-weight:400}@font-face{font-family:Avenir;src:url(//cdn.plyr.io/fonts/avenir-bold.woff2) format("woff2"),url(//cdn.plyr.io/fonts/avenir-bold.woff) format("woff");font-style:normal;font-weight:600}h1,h2{letter-spacing:-.025em;color:#2E3C44;margin:0 0 10px;line-height:1.2}h1{font-size:64px;font-size:4rem;color:#3498DB}p,small{margin:0 0 20px}small{font-size:14px;font-size:.875rem}a:focus,a:hover{color:#343f4a;border-bottom-color:transparent}a:focus{outline:#343f4a dotted thin;outline-offset:1px}.color-vimeo{color:#19b7ed}.color-youtube{color:#cc181e}*,::after,::before{box-sizing:border-box}.btn-bar ul,nav li{display:inline-block}html{height:100%;font-size:100%;background:linear-gradient(#fff,#f2f5f7) fixed}body{font-family:Avenir,"Helvetica Neue",Helvetica,Arial,sans-serif;line-height:1.5;text-align:center;color:#55646b}header{padding:20px;margin-bottom:20px}header p{font-size:18px;font-size:1.125rem}section{padding-bottom:20px}@media (min-width:480px){header{padding-top:60px;padding-bottom:60px}section{padding-bottom:40px}}.icon{fill:currentColor;width:18px;height:18px;vertical-align:-3px}a svg,button svg,label svg{pointer-events:none}.btn .icon,a .icon{margin-right:10px}nav ul{margin:0;font-size:0}nav li{margin-top:10px;font-size:16px;font-size:1rem}nav li+li{margin-left:20px}.btn-bar{margin:0 auto 20px}.btn-bar::before{position:absolute;left:0;right:0;height:1px;background:#dbe3e8}.btn-bar ul{position:relative;z-index:1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn-bar li{margin:0}.btn-bar li:first-child .btn{border-radius:4px 0 0 4px}.btn-bar li:last-child .btn{border-radius:0 4px 4px 0}.btn-bar li+li .btn{margin-left:-1px}.btn-bar .btn{display:block;border-radius:0}.btn-bar .btn.active{box-shadow:inset 0 1px 1px rgba(0,0,0,.2);position:relative;z-index:1}.btn-bar .btn.active .icon{color:inherit}@media (min-width:560px){.btn-bar{margin-bottom:40px}}.btn,.btn-count{display:inline-block;vertical-align:middle;border-radius:4px;font-weight:600;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn{padding:10px 20px;background:#f2f5f7;border:1px solid #cbd0d3;box-shadow:inset 0 1px 0 #fff,0 1px 1px rgba(0,0,0,.05);text-shadow:0 1px 1px #fff;color:#55646b;transition:background .3s ease,border .3s ease,color .3s ease}.btn:focus,.btn:hover{border-color:#b5bcc0;color:#55646b;outline:0}.btn-youtube .icon{color:#cc181e}.btn-vimeo .icon{color:#19b7ed}.btn-twitter .icon{color:#4BAAF4}.btn-bar .active,.btn-primary{background-image:linear-gradient(#3498db,#2791d9);background-color:#3498db;border-color:#217dbb;box-shadow:0 1px 1px rgba(0,0,0,.15);text-shadow:0 1px 1px rgba(0,0,0,.1);color:#fff}.btn-primary:focus,.btn-primary:hover{color:#fff;border-color:#196090}.btn-small{padding-top:7px;padding-bottom:7px}.btn-count{position:relative;margin-left:10px;padding:10px 15px;background:#fff;border:1px solid #cbd0d3}.btn-count::before{position:absolute;display:block;width:8px;height:8px;left:1px;margin-top:-4px;background:inherit;border:inherit;border-width:1px 0 0 1px;-webkit-transform:rotate(-45deg) translate(-50%,-50%);transform:rotate(-45deg) translate(-50%,-50%)}.panel{display:none}.panel.active{display:block;-webkit-animation:fade-in .3s ease;animation:fade-in .3s ease}.error body,html.error{height:100%}.error body{width:100%;display:table;table-layout:fixed}.error main{display:table-cell;width:100%;vertical-align:middle}.plyr-video-embed,video{border-radius:4px}.plyr-video-embed{-webkit-mask-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC)}.plyr{margin:0 auto 20px}.plyr-controls{border-radius:0 0 4px 4px}.plyr .plyr-video-embed,.plyr video{border-radius:4px 4px 0 0}.plyr-fullscreen,.plyr.fullscreen-active{max-width:none}.plyr-fullscreen .plyr-controls,.plyr-fullscreen iframe,.plyr-fullscreen video,.plyr.fullscreen-active .plyr-controls,.plyr.fullscreen-active iframe,.plyr.fullscreen-active video{border-radius:0}.plyr-fullscreen iframe,.plyr.fullscreen-active iframe{-webkit-mask-image:none}.plyr-audio{max-width:520px}.plyr-audio .plyr-controls{border-radius:4px}.plyr-audio .plyr-progress{border-radius:4px 4px 0 0;overflow:hidden}.cite{display:none}.cite .icon{margin-right:5px}.plyr-audio~ul .cite-audio,.plyr-video~ul .cite-video,.plyr-vimeo~ul .cite-vimeo,.plyr-youtube~ul .cite-youtube{display:block}
\ No newline at end of file diff --git a/docs/dist/docs.js b/docs/dist/docs.js index d4b4b57a..4376d476 100644 --- a/docs/dist/docs.js +++ b/docs/dist/docs.js @@ -1 +1 @@ -"document"in self&&("classList"in document.createElement("_")?!function(){"use strict";var t=document.createElement("_");if(t.classList.add("c1","c2"),!t.classList.contains("c2")){var e=function(t){var e=DOMTokenList.prototype[t];DOMTokenList.prototype[t]=function(t){var n,i=arguments.length;for(n=0;i>n;n++)t=arguments[n],e.call(this,t)}};e("add"),e("remove")}if(t.classList.toggle("c3",!1),t.classList.contains("c3")){var n=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t,e){return 1 in arguments&&!this.contains(t)==!e?e:n.call(this,t)}}t=null}():!function(t){"use strict";if("Element"in t){var e="classList",n="prototype",i=t.Element[n],s=Object,r=String[n].trim||function(){return this.replace(/^\s+|\s+$/g,"")},o=Array[n].indexOf||function(t){for(var e=0,n=this.length;n>e;e++)if(e in this&&this[e]===t)return e;return-1},a=function(t,e){this.name=t,this.code=DOMException[t],this.message=e},c=function(t,e){if(""===e)throw new a("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(e))throw new a("INVALID_CHARACTER_ERR","String contains an invalid character");return o.call(t,e)},l=function(t){for(var e=r.call(t.getAttribute("class")||""),n=e?e.split(/\s+/):[],i=0,s=n.length;s>i;i++)this.push(n[i]);this._updateClassName=function(){t.setAttribute("class",this.toString())}},u=l[n]=[],f=function(){return new l(this)};if(a[n]=Error[n],u.item=function(t){return this[t]||null},u.contains=function(t){return t+="",-1!==c(this,t)},u.add=function(){var t,e=arguments,n=0,i=e.length,s=!1;do t=e[n]+"",-1===c(this,t)&&(this.push(t),s=!0);while(++n<i);s&&this._updateClassName()},u.remove=function(){var t,e,n=arguments,i=0,s=n.length,r=!1;do for(t=n[i]+"",e=c(this,t);-1!==e;)this.splice(e,1),r=!0,e=c(this,t);while(++i<s);r&&this._updateClassName()},u.toggle=function(t,e){t+="";var n=this.contains(t),i=n?e!==!0&&"remove":e!==!1&&"add";return i&&this[i](t),e===!0||e===!1?e:!n},u.toString=function(){return this.join(" ")},s.defineProperty){var d={get:f,enumerable:!0,configurable:!0};try{s.defineProperty(i,e,d)}catch(g){-2146823252===g.number&&(d.enumerable=!1,s.defineProperty(i,e,d))}}else s[n].__defineGetter__&&i.__defineGetter__(e,f)}}(self)),plyr.setup({debug:!0,volume:9,title:"Video demo",tooltips:!0,captions:{defaultActive:!0},onSetup:function(){if("media"in this){var t=this,e=t.media.tagName.toLowerCase(),n=document.querySelector("[data-toggle='fullscreen']");console.log("✓ Setup done for <"+e+">"),"video"===e&&n&&n.addEventListener("click",t.toggleFullscreen,!1)}}}),shr.setup({count:{classname:"btn-count"}}),function(){function t(t){t.preventDefault();for(var s=t.target,r=document.querySelector(s.getAttribute("href")),o=n.length-1;o>=0;o--)n[o].classList.remove(i);for(var a=e.length-1;a>=0;a--)e[a].classList.remove(i);r.classList.add(i),t.target.classList.add(i)}for(var e=document.querySelectorAll(".nav-panel a"),n=document.querySelectorAll(".panels > .panel"),i="active",s=e.length-1;s>=0;s--)e[s].addEventListener("click",t)}(),document.domain.indexOf("plyr.io")>-1&&(!function(t,e,n,i,s,r,o){t.GoogleAnalyticsObject=s,t[s]=t[s]||function(){(t[s].q=t[s].q||[]).push(arguments)},t[s].l=1*new Date,r=e.createElement(n),o=e.getElementsByTagName(n)[0],r.async=1,r.src=i,o.parentNode.insertBefore(r,o)}(window,document,"script","//www.google-analytics.com/analytics.js","ga"),ga("create","UA-40881672-11","auto"),ga("send","pageview"));
\ No newline at end of file +"document"in self&&("classList"in document.createElement("_")?!function(){"use strict";var t=document.createElement("_");if(t.classList.add("c1","c2"),!t.classList.contains("c2")){var e=function(t){var e=DOMTokenList.prototype[t];DOMTokenList.prototype[t]=function(t){var s,n=arguments.length;for(s=0;n>s;s++)t=arguments[s],e.call(this,t)}};e("add"),e("remove")}if(t.classList.toggle("c3",!1),t.classList.contains("c3")){var s=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t,e){return 1 in arguments&&!this.contains(t)==!e?e:s.call(this,t)}}t=null}():!function(t){"use strict";if("Element"in t){var e="classList",s="prototype",n=t.Element[s],i=Object,o=String[s].trim||function(){return this.replace(/^\s+|\s+$/g,"")},r=Array[s].indexOf||function(t){for(var e=0,s=this.length;s>e;e++)if(e in this&&this[e]===t)return e;return-1},c=function(t,e){this.name=t,this.code=DOMException[t],this.message=e},a=function(t,e){if(""===e)throw new c("SYNTAX_ERR","An invalid or illegal string was specified");if(/\s/.test(e))throw new c("INVALID_CHARACTER_ERR","String contains an invalid character");return r.call(t,e)},l=function(t){for(var e=o.call(t.getAttribute("class")||""),s=e?e.split(/\s+/):[],n=0,i=s.length;i>n;n++)this.push(s[n]);this._updateClassName=function(){t.setAttribute("class",this.toString())}},u=l[s]=[],p=function(){return new l(this)};if(c[s]=Error[s],u.item=function(t){return this[t]||null},u.contains=function(t){return t+="",-1!==a(this,t)},u.add=function(){var t,e=arguments,s=0,n=e.length,i=!1;do t=e[s]+"",-1===a(this,t)&&(this.push(t),i=!0);while(++s<n);i&&this._updateClassName()},u.remove=function(){var t,e,s=arguments,n=0,i=s.length,o=!1;do for(t=s[n]+"",e=a(this,t);-1!==e;)this.splice(e,1),o=!0,e=a(this,t);while(++n<i);o&&this._updateClassName()},u.toggle=function(t,e){t+="";var s=this.contains(t),n=s?e!==!0&&"remove":e!==!1&&"add";return n&&this[n](t),e===!0||e===!1?e:!s},u.toString=function(){return this.join(" ")},i.defineProperty){var d={get:p,enumerable:!0,configurable:!0};try{i.defineProperty(n,e,d)}catch(m){-2146823252===m.number&&(d.enumerable=!1,i.defineProperty(n,e,d))}}else i[s].__defineGetter__&&n.__defineGetter__(e,p)}}(self)),plyr.setup({debug:!0,title:"Video demo",tooltips:!0,captions:{defaultActive:!0},onSetup:function(){console.log("✓ Setup done")}}),shr.setup({count:{classname:"btn-count"}}),function(){function t(){var t=this,s=t.getAttribute("data-source"),n=document.querySelector(".plyr").plyr;switch(s){case"video":n.source({type:"video",title:"Bug Buck Bunny",sources:[{src:"https://cdn.selz.com/plyr/1.0/movie.mp4",type:"video/mp4"},{src:"https://cdn.selz.com/plyr/1.0/movie.webm",type:"video/webm"}],poster:"https://cdn.selz.com/plyr/1.0/poster.jpg",tracks:[{kind:"captions",label:"English",srclang:"en",src:"https://cdn.selz.com/plyr/1.0/example_captions_en.vtt","default":!0}]});break;case"audio":n.source({type:"audio",title:"96 by Logistics",sources:[{src:"https://cdn.selz.com/plyr/1.0/logistics-96-sample.mp3",type:"audio/mp3"},{src:"https://cdn.selz.com/plyr/1.0/logistics-96-sample.ogg",type:"audio/ogg"}]});break;case"youtube":n.source({type:"youtube",title:"Enovato interview of Dan Cederholm for Made By",sources:"Au87oAJ2jeE"});break;case"vimeo":n.source({type:"vimeo",title:"Yosemite HD II",sources:"87701971"})}for(var i=e.length-1;i>=0;i--)e[i].classList.remove("active");event.target.classList.add("active")}for(var e=document.querySelectorAll("[data-source]"),s=e.length-1;s>=0;s--)e[s].addEventListener("click",t)}(),document.domain.indexOf("plyr.io")>-1&&(!function(t,e,s,n,i,o,r){t.GoogleAnalyticsObject=i,t[i]=t[i]||function(){(t[i].q=t[i].q||[]).push(arguments)},t[i].l=1*new Date,o=e.createElement(s),r=e.getElementsByTagName(s)[0],o.async=1,o.src=n,r.parentNode.insertBefore(o,r)}(window,document,"script","//www.google-analytics.com/analytics.js","ga"),ga("create","UA-40881672-11","auto"),ga("send","pageview"));
\ No newline at end of file diff --git a/docs/dist/sprite.svg b/docs/dist/sprite.svg new file mode 100644 index 00000000..6f09b44b --- /dev/null +++ b/docs/dist/sprite.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg"><symbol id="icon-github" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M8 .2c-4.4 0-8 3.6-8 8 0 3.5 2.3 6.5 5.5 7.6.4.1.5-.2.5-.4V14c-2.2.5-2.7-1-2.7-1-.4-.9-.9-1.2-.9-1.2-.7-.5.1-.5.1-.5.8.1 1.2.8 1.2.8.7 1.3 1.9.9 2.3.7.1-.5.3-.9.5-1.1-1.8-.2-3.6-.9-3.6-4 0-.9.3-1.6.8-2.1-.1-.2-.4-1 .1-2.1 0 0 .7-.2 2.2.8.6-.2 1.3-.3 2-.3s1.4.1 2 .3c1.5-1 2.2-.8 2.2-.8.4 1.1.2 1.9.1 2.1.5.6.8 1.3.8 2.1 0 3.1-1.9 3.7-3.7 3.9.3.4.6.9.6 1.6v2.2c0 .2.1.5.6.4 3.2-1.1 5.5-4.1 5.5-7.6-.1-4.4-3.7-8-8.1-8z"/></symbol><symbol id="icon-twitter" viewBox="0 0 16 16"><title>Twitter</title><path d="M16 3c-.6.3-1.2.4-1.9.5.7-.4 1.2-1 1.4-1.8-.6.4-1.3.6-2.1.8-.6-.6-1.5-1-2.4-1-1.7 0-3.2 1.5-3.2 3.3 0 .3 0 .5.1.7-2.7-.1-5.2-1.4-6.8-3.4-.3.5-.4 1-.4 1.7 0 1.1.6 2.1 1.5 2.7-.5 0-1-.2-1.5-.4C.7 7.7 1.8 9 3.3 9.3c-.3.1-.6.1-.9.1-.2 0-.4 0-.6-.1.4 1.3 1.6 2.3 3.1 2.3-1.1.9-2.5 1.4-4.1 1.4H0c1.5.9 3.2 1.5 5 1.5 6 0 9.3-5 9.3-9.3v-.4C15 4.3 15.6 3.7 16 3z"/></symbol><symbol id="icon-vimeo" viewBox="0 0 16 16"><path d="M16 4.3c-.1 1.6-1.2 3.7-3.3 6.4-2.2 2.8-4 4.2-5.5 4.2-.9 0-1.7-.9-2.4-2.6C4 9.9 3.4 5 2 5c-.1 0-.5.3-1.2.8l-.8-1c.8-.7 3.5-3.4 4.7-3.5 1.2-.1 2 .7 2.3 2.5.3 2 .8 6.1 1.8 6.1.9 0 2.5-3.4 2.6-4 .1-.9-.3-1.9-2.3-1.1.8-2.6 2.3-3.8 4.5-3.8 1.7.1 2.5 1.2 2.4 3.3z"/></symbol><symbol id="icon-youtube" viewBox="0 0 16 16"><path d="M15.8 4.8c-.2-1.3-.8-2.2-2.2-2.4C11.4 2 8 2 8 2s-3.4 0-5.6.4C1 2.6.3 3.5.2 4.8 0 6.1 0 8 0 8s0 1.9.2 3.2c.2 1.3.8 2.2 2.2 2.4C4.6 14 8 14 8 14s3.4 0 5.6-.4c1.4-.3 2-1.1 2.2-2.4C16 9.9 16 8 16 8s0-1.9-.2-3.2zM6 11V5l5 3-5 3z"/></symbol></svg>
\ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 88d3c44b..cd4248a0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -16,7 +16,7 @@ <body> <header> <h1>Plyr</h1> - <p>A simple HTML5 media player with custom controls and WebVTT captions by <a href="https://twitter.com/sam_potts" target="_blank">@sam_potts</a> from <a href="https://twitter.com/selz" target="_blank">@selz</a></p> + <p>A simple, accessible HTML5 media player by <a href="https://twitter.com/sam_potts" target="_blank">@sam_potts</a> from <a href="https://twitter.com/selz" target="_blank">@selz</a></p> <nav> <ul> <li> @@ -36,48 +36,44 @@ <main role="main" id="main"> <nav class="btn-bar nav-panel"> <ul> - <li><a href="#video" class="btn active btn-small">Video</a></li> - <li><a href="#youtube" class="btn btn-small">YouTube</a></li> - <li><a href="#audio" class="btn btn-small">Audio</a></li> + <li> + <button type="button" class="btn active" data-source="video">Video</button> + </li> + <li> + <button type="button" class="btn" data-source="audio">Audio</button> + </li> + <li> + <button type="button" class="btn btn-youtube" data-source="youtube"><svg class="icon"><use xlink:href="#icon-youtube"/></svg>YouTube</button> + </li> + <li> + <button type="button" class="btn btn-vimeo" data-source="vimeo"><svg class="icon"><use xlink:href="#icon-vimeo"/></svg>Vimeo</button> + </li> </ul> </nav> - <div class="panels"> - <section class="panel example-video active" id="video"> - <div class="player"> - <video poster="poster.jpg" controls crossorigin> - <!-- Video files --> - <source src="https://cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4"> - <source src="https://cdn.selz.com/plyr/1.0/movie.webm" type="video/webm"> + <section> + <div class="plyr"> + <video poster="https://cdn.selz.com/plyr/1.0/poster.jpg" controls crossorigin> + <!-- Video files --> + <source src="https://cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4"> + <source src="https://cdn.selz.com/plyr/1.0/movie.webm" type="video/webm"> - <!-- Text track file --> - <track kind="captions" label="English" srclang="en" src="https://cdn.selz.com/plyr/1.0/example_captions_en.vtt" default> + + <!-- Text track file --> + <track kind="captions" label="English" srclang="en" src="https://cdn.selz.com/plyr/1.0/example_captions_en.vtt" default> - <!-- Fallback for browsers that don't support the <video> element --> - <a href="https://cdn.selz.com/plyr/1.0/movie.mp4">Download</a> - </video> - </div> - <small>Big Buck Bunny. More info can be found at <a href="https://peach.blender.org" target="_blank">peach.blender.org</a>.</small> - </section> - <section class="panel example-video" id="youtube"> - <div class="player"> - <div data-video-id="Au87oAJ2jeE" data-type="youtube"></div> - </div> - <small>Envato's "Made By" interview of <a href="https://www.youtube.com/watch?v=Au87oAJ2jeE" target="_blank">Dan Cederholm</a> from <a href="https://dribbble.com" target="_blank">Dribbble</a>.</small> - </section> - <section class="panel example-audio" id="audio"> - <div class="player"> - <audio controls> - <!-- Audio files --> - <source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3" type="audio/mp3"> - <source src="//cdn.selz.com/plyr/1.0/logistics-96-sample.ogg" type="audio/ogg"> + + <!-- Fallback for browsers that don't support the <video> element --> + <a href="https://cdn.selz.com/plyr/1.0/movie.mp4">Download</a> + </video> + </div> - <!-- Fallback for browsers that don't support the <audio> element --> - <a href="//cdn.selz.com/plyr/1.0/logistics-96-sample.mp3">Download</a> - </audio> - </div> - <small>"96" by Logistics, which can be purchased from <a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">Hospital Records</a>.</small> - </section> - </div> + <ul> + <li class="cite cite-video"><small><a href="https://www.bigbuckbunny.org" target="_blank">Big Buck Bunny</a> © Copyright 2008, Blender Foundation</small></li> + <li class="cite cite-audio"><small><a href="https://www.hospitalrecords.com/shop/artist/logistics" target="_blank">96 by Logistics</a> © Copyright, Hospital Records</small></li> + <li class="cite cite-youtube"><small><a href="https://www.youtube.com/watch?v=Au87oAJ2jeE" target="_blank">Envato's "Made By" interview of Dan Cederholm</a> on <span class="color-youtube"><svg class="icon"><use xlink:href="#icon-youtube"/></svg>YouTube</span></small> + <li class="cite cite-vimeo"><small><a href="https://vimeo.com/87701971" target="_blank">Yosemite HD II</a> on <span class="color-vimeo"><svg class="icon"><use xlink:href="#icon-vimeo"/></svg>Vimeo</span></small> + </ul> + </section> </main> <!-- Load SVG defs --> @@ -116,6 +112,11 @@ } }); })(); + // Load the plyr sprite + loadSprite(document, "../dist/sprite.svg"); + + // This is for the docs only + loadSprite(document, "dist/sprite.svg"); </script> <!-- Plyr core script --> diff --git a/docs/src/js/docs.js b/docs/src/js/docs.js index 518e4e0c..1e3c3206 100644 --- a/docs/src/js/docs.js +++ b/docs/src/js/docs.js @@ -6,74 +6,110 @@ // Setup the player plyr.setup({ - debug: true, - volume: 9, - title: "Video demo", - tooltips: true, + debug: true, + title: 'Video demo', + tooltips: true, captions: { defaultActive: true }, onSetup: function() { - if(!("media" in this)) { - return; - } - - var player = this, - type = player.media.tagName.toLowerCase(), - toggle = document.querySelector("[data-toggle='fullscreen']"); - - console.log("✓ Setup done for <" + type + ">"); - - if(type === "video" && toggle) { - toggle.addEventListener("click", player.toggleFullscreen, false); - } + console.log('✓ Setup done'); } }); // Setup shr shr.setup({ count: { - classname: "btn-count" + classname: 'btn-count' } }); // General functions (function() { - // Tabs - var tabs = document.querySelectorAll(".nav-panel a"), - panels = document.querySelectorAll(".panels > .panel"), - activeClass = "active"; + var buttons = document.querySelectorAll('[data-source]'); - for (var i = tabs.length - 1; i >= 0; i--) { - tabs[i].addEventListener("click", togglePanel); + // Bind to each button + for (var i = buttons.length - 1; i >= 0; i--) { + buttons[i].addEventListener('click', newSource); } - function togglePanel(event) { - event.preventDefault(); + // Set a new source + function newSource() { + var trigger = this, + type = trigger.getAttribute('data-source'), + player = document.querySelector('.plyr').plyr; + + switch(type) { + case 'video': + player.source({ + type: 'video', + title: 'Bug Buck Bunny', + sources: [{ + src: 'https://cdn.selz.com/plyr/1.0/movie.mp4', + type: 'video/mp4' + }, + { + src: 'https://cdn.selz.com/plyr/1.0/movie.webm', + type: 'video/webm' + }], + poster: 'https://cdn.selz.com/plyr/1.0/poster.jpg', + tracks: [{ + kind: 'captions', + label: 'English', + srclang:'en', + src: 'https://cdn.selz.com/plyr/1.0/example_captions_en.vtt', + default: true + }] + }); + break; + + case 'audio': + player.source({ + type: 'audio', + title: '96 by Logistics', + sources: [{ + src: 'https://cdn.selz.com/plyr/1.0/logistics-96-sample.mp3', + type: 'audio/mp3' + }, + { + src: 'https://cdn.selz.com/plyr/1.0/logistics-96-sample.ogg', + type: 'audio/ogg' + }] + }); + break; - var tab = event.target, - panel = document.querySelector(tab.getAttribute("href")); + case 'youtube': + player.source({ + type: 'youtube', + title: 'Enovato interview of Dan Cederholm for Made By', + sources: 'Au87oAJ2jeE' + }); + break; - for (var i = panels.length - 1; i >= 0; i--) { - panels[i].classList.remove(activeClass); + case 'vimeo': + player.source({ + type: 'vimeo', + title: 'Yosemite HD II', + sources: '87701971' + }); + break; } - for (var x = tabs.length - 1; x >= 0; x--) { - tabs[x].classList.remove(activeClass); + for (var x = buttons.length - 1; x >= 0; x--) { + buttons[x].classList.remove('active'); } - panel.classList.add(activeClass); - event.target.classList.add(activeClass); + event.target.classList.add('active'); } })(); // Google analytics // For demo site (http://[www.]plyr.io) only -if(document.domain.indexOf("plyr.io") > -1) { +if(document.domain.indexOf('plyr.io') > -1) { (function(i,s,o,g,r,a,m){i.GoogleAnalyticsObject=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,"script","//www.google-analytics.com/analytics.js","ga"); - ga("create", "UA-40881672-11", "auto"); - ga("send", "pageview"); + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); + ga('create', 'UA-40881672-11', 'auto'); + ga('send', 'pageview'); } diff --git a/docs/src/less/components/examples.less b/docs/src/less/components/examples.less index 97087b02..6312b642 100644 --- a/docs/src/less/components/examples.less +++ b/docs/src/less/components/examples.less @@ -2,54 +2,31 @@ // Examples // ========================================================================== +video, +.plyr-video-embed { + border-radius: @border-radius-base; +} +.plyr-video-embed { + -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); +} + // Example players -.example-audio .player, -.example-video .player { +.plyr { margin: 0 auto @padding-base; + max-width: @example-width-video; &-controls { border-radius: 0 0 @border-radius-base @border-radius-base; } -} -.example-audio .player { - max-width: @example-width-audio; - - &-controls { - border-radius: @border-radius-base; - } - &-progress { - border-radius: @border-radius-base @border-radius-base 0 0; - overflow: hidden; - } -} -// Base styles -.example-video .player { - max-width: @example-width-video; - video, - iframe { - border-radius: @border-radius-base; - } - iframe { - -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); - } -} - -// Style full supported player -.example-video .player-video, -.example-video .player-youtube { - video, - iframe { + .plyr-video-embed { border-radius: @border-radius-base @border-radius-base 0 0; } - iframe { - -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); - } &-fullscreen, &.fullscreen-active { max-width: none; - .player-controls, + .plyr-controls, video, iframe { border-radius: 0; @@ -58,4 +35,31 @@ -webkit-mask-image: none; } } +} +.plyr-audio { + max-width: @example-width-audio; + + .plyr-controls { + border-radius: @border-radius-base; + } + .plyr-progress { + border-radius: @border-radius-base @border-radius-base 0 0; + overflow: hidden; + } +} + +// Style full supported player +.cite { + display: none; + + .icon { + margin-right: (@padding-base / 4); + } +} + +.plyr-video ~ ul .cite-video, +.plyr-audio ~ ul .cite-audio, +.plyr-youtube ~ ul .cite-youtube, +.plyr-vimeo ~ ul .cite-vimeo { + display: block; }
\ No newline at end of file diff --git a/docs/src/sprite/icon-github.svg b/docs/src/sprite/icon-github.svg new file mode 100755 index 00000000..685dd746 --- /dev/null +++ b/docs/src/sprite/icon-github.svg @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8,0.2c-4.4,0-8,3.6-8,8c0,3.5,2.3,6.5,5.5,7.6
+ C5.9,15.9,6,15.6,6,15.4c0-0.2,0-0.7,0-1.4C3.8,14.5,3.3,13,3.3,13c-0.4-0.9-0.9-1.2-0.9-1.2c-0.7-0.5,0.1-0.5,0.1-0.5
+ c0.8,0.1,1.2,0.8,1.2,0.8C4.4,13.4,5.6,13,6,12.8c0.1-0.5,0.3-0.9,0.5-1.1c-1.8-0.2-3.6-0.9-3.6-4c0-0.9,0.3-1.6,0.8-2.1
+ c-0.1-0.2-0.4-1,0.1-2.1c0,0,0.7-0.2,2.2,0.8c0.6-0.2,1.3-0.3,2-0.3c0.7,0,1.4,0.1,2,0.3c1.5-1,2.2-0.8,2.2-0.8
+ c0.4,1.1,0.2,1.9,0.1,2.1c0.5,0.6,0.8,1.3,0.8,2.1c0,3.1-1.9,3.7-3.7,3.9C9.7,12,10,12.5,10,13.2c0,1.1,0,1.9,0,2.2
+ c0,0.2,0.1,0.5,0.6,0.4c3.2-1.1,5.5-4.1,5.5-7.6C16,3.8,12.4,0.2,8,0.2z"/>
+</svg>
diff --git a/docs/src/sprite/icon-twitter.svg b/docs/src/sprite/icon-twitter.svg new file mode 100755 index 00000000..b3f644b1 --- /dev/null +++ b/docs/src/sprite/icon-twitter.svg @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
+ <title>Twitter</title>
+<path d="M16,3c-0.6,0.3-1.2,0.4-1.9,0.5c0.7-0.4,1.2-1,1.4-1.8c-0.6,0.4-1.3,0.6-2.1,0.8c-0.6-0.6-1.5-1-2.4-1
+ C9.3,1.5,7.8,3,7.8,4.8c0,0.3,0,0.5,0.1,0.7C5.2,5.4,2.7,4.1,1.1,2.1c-0.3,0.5-0.4,1-0.4,1.7c0,1.1,0.6,2.1,1.5,2.7
+ c-0.5,0-1-0.2-1.5-0.4c0,0,0,0,0,0c0,1.6,1.1,2.9,2.6,3.2C3,9.4,2.7,9.4,2.4,9.4c-0.2,0-0.4,0-0.6-0.1c0.4,1.3,1.6,2.3,3.1,2.3
+ c-1.1,0.9-2.5,1.4-4.1,1.4c-0.3,0-0.5,0-0.8,0c1.5,0.9,3.2,1.5,5,1.5c6,0,9.3-5,9.3-9.3c0-0.1,0-0.3,0-0.4C15,4.3,15.6,3.7,16,3z"/>
+</svg>
diff --git a/docs/src/sprite/icon-vimeo.svg b/docs/src/sprite/icon-vimeo.svg new file mode 100755 index 00000000..83dd3dc0 --- /dev/null +++ b/docs/src/sprite/icon-vimeo.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
+<path d="M16,4.3c-0.1,1.6-1.2,3.7-3.3,6.4c-2.2,2.8-4,4.2-5.5,4.2c-0.9,0-1.7-0.9-2.4-2.6C4,9.9,3.4,5,2,5
+ C1.9,5,1.5,5.3,0.8,5.8L0,4.8c0.8-0.7,3.5-3.4,4.7-3.5C5.9,1.2,6.7,2,7,3.8c0.3,2,0.8,6.1,1.8,6.1c0.9,0,2.5-3.4,2.6-4
+ c0.1-0.9-0.3-1.9-2.3-1.1c0.8-2.6,2.3-3.8,4.5-3.8C15.3,1.1,16.1,2.2,16,4.3z"/>
+</svg>
diff --git a/docs/src/sprite/icon-youtube.svg b/docs/src/sprite/icon-youtube.svg new file mode 100755 index 00000000..8b5d6897 --- /dev/null +++ b/docs/src/sprite/icon-youtube.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="16px" height="16px" viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
+<path d="M15.8,4.8c-0.2-1.3-0.8-2.2-2.2-2.4C11.4,2,8,2,8,2S4.6,2,2.4,2.4C1,2.6,0.3,3.5,0.2,4.8C0,6.1,0,8,0,8
+ s0,1.9,0.2,3.2c0.2,1.3,0.8,2.2,2.2,2.4C4.6,14,8,14,8,14s3.4,0,5.6-0.4c1.4-0.3,2-1.1,2.2-2.4C16,9.9,16,8,16,8S16,6.1,15.8,4.8z
+ M6,11V5l5,3L6,11z"/>
+</svg>
diff --git a/gulpfile.js b/gulpfile.js index 865f2a56..3e7979a2 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -127,7 +127,7 @@ var build = { })(key); } }, - sprite: function() { + sprite: function(bundle) { // Process Icons gulp.task("sprite", function () { return gulp @@ -168,7 +168,7 @@ gulp.task("watch", function () { // Plyr core gulp.watch(paths.plyr.src.js, tasks.js); gulp.watch(paths.plyr.src.less, tasks.less); - gulp.watch(paths.plyr.src.sprite, ["sprite"]); + gulp.watch(paths.plyr.src.sprite, ["sprite-plyr"]); // Docs gulp.watch(paths.docs.src.js, tasks.js); diff --git a/package.json b/package.json index db78a333..0300322f 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "plyr", - "version": "1.3.7", + "version": "1.4.0", "description": "A simple HTML5 media player using custom controls", "homepage": "http://plyr.io", "main": "gulpfile.js", "dependencies": {}, "devDependencies": { - "gulp": "^3.8.6", + "gulp": "^3.9.0", "gulp-autoprefixer": "^3.1.0", "gulp-concat": "^2.3.3", "gulp-gzip": "^1.0.0", @@ -100,7 +100,7 @@ and the AJAX technique here: ### HTML The only extra markup that's needed to use plyr is a `<div>` wrapper. Replace the source, poster and captions with urls for your media. ```html -<div class="player"> +<div class="plyr"> <video poster="https://cdn.selz.com/plyr/1.0/poster.jpg" controls crossorigin> <!-- Video files --> <source src="https://cdn.selz.com/plyr/1.0/movie.mp4" type="video/mp4"> @@ -117,7 +117,7 @@ The only extra markup that's needed to use plyr is a `<div>` wrapper. Replace th And the same for `<audio>` ```html -<div class="player"> +<div class="plyr"> <audio controls> <!-- Audio files --> <source src="https://cdn.selz.com/plyr/1.0/logistics-96-sample.mp3" type="audio/mp3"> @@ -132,7 +132,7 @@ And the same for `<audio>` For YouTube, Plyr uses the standard YouTube API markup (an empty `<div>`): ```html -<div class="player"> +<div class="plyr"> <div data-video-id="L1h9xxCU20g" data-type="youtube"></div> </div> ``` @@ -144,16 +144,43 @@ More info on CORS here: [https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS) ### JavaScript -Much of the behaviour of the player is configurable when initialising the library. Here's an example of a default setup: + +#### Quick setup + +Here's an example of a default setup: ```html -<script src="dist/plyr.js"></script> +<script src="https://cdn.plyr.io/1.3.5/plyr.js"></script> <script>plyr.setup();</script> ``` +This will look for all elements with the `plyr` classname and setup plyr on each element found. You can specify other options, including a different selector hook below. + +You can initialise the player a few other ways: + +Passing a [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList): +```javascript +plyr.setup(document.querySelectorAll('.js-plyr'), options); +``` + +Passing a [HTMLElement](https://developer.mozilla.org/en/docs/Web/API/HTMLElement): +```javascript +plyr.setup(document.querySelector('.js-plyr'), options); +``` + +Passing a [string selector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll): +```javascript +plyr.setup('.js-plyr', options); +``` + +Passing just the options object: +```javascript +plyr.setup(options); +``` + #### Options -You can pass the following options to the setup method using `plyr.setup({...})`. +Options must be passed as an object to the `setup()` method as above. <table class="table" width="100%"> <thead> @@ -235,7 +262,7 @@ You can pass the following options to the setup method using `plyr.setup({...})` <td><code>selectors</code></td> <td>Object</td> <td>—</td> - <td>See <code>plyr.js</code> in <code>/src</code> for more info. The only option you might want to change is <code>player</code> which is the hook used for Plyr, the default is <code>.player</code>.</td> + <td>See <code>plyr.js</code> in <code>/src</code> for more info. You probably don't need to change any of these.</td> </tr> <tr> <td><code>classes</code></td> @@ -253,7 +280,7 @@ You can pass the following options to the setup method using `plyr.setup({...})` <td><code>fullscreen</code></td> <td>Object</td> <td>—</td> - <td>Three properties; <code>enabled</code> which toggles if fullscreen should be enabled (if the browser supports it). The default value is <code>true</code>. A <code>fallback</code> property which will enable a full window view for older browsers. The default value is <code>true</code>. A <code>hideControls</code> property which will hide the controls when fullscreen is active and the video is playing, after 1s. The controls reappear on hover of the progress bar (mouse), focusing a child control or pausing the video (by tap/click of video if `click` is `true`). The default value is <code>true</code>.</td> + <td>See <a href="#fullscreen-options">below</a></td> </tr> <tr> <td><code>storage</code></td> @@ -270,12 +297,68 @@ You can pass the following options to the setup method using `plyr.setup({...})` </tbody> </table> +#### Fullscreen options + +<table class="table" width="100%" id="fullscreen-options"> +<thead> + <tr> + <th width="20%">Option</th> + <th width="15%">Type</th> + <th width="15%">Default</th> + <th width="50%">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>enabled</code></td> + <td>Boolean</td> + <td><code>true</code></td> + <td>Toggles if fullscreen should be enabled (if the browser supports it).</td> + </tr> + <tr> + <td><code>fallback</code></td> + <td>Boolean</td> + <td><code>true</code></td> + <td>Enable a full viewport view for older browsers.</td> + </tr> + <tr> + <td><code>hideControls</code></td> + <td>Boolean</td> + <td><code>true</code></td> + <td>Hide the controls when fullscreen is active and the video is playing, after 1s. The controls reappear on hover of the progress bar (mouse), focusing a child control or pausing the video (by tap/click of video if `click` is `true`).</td> + </tr> + <tr> + <td><code>allowAudio</code></td> + <td>Boolean</td> + <td><code>false</code></td> + <td>Allow audio play to toggle fullscreen. This will be more useful later when posters are supported.</td> + </tr> + </tbody> +</table> + ## API -A `plyr` object is added to any element that Plyr is initialised on. You can then control the player by accessing methods in the `plyr` object. For example if you wanted to pause Plyr: +#### Fetching the plyr instance +A `plyr` object is added to any element that Plyr is initialised on. You can then control the player by accessing methods in the `plyr` object. + +There are two ways to access the instance, firstly you re-query the element container you used for setup (e.g. `.js-plyr`) like so: + +```javascript +var player = document.querySelector('.js-plyr'); +``` + +Or you can use the returned object from your call to the setup method: + +```javascript +var player = plyr.setup('.js-plyr')[0]; +``` + +This will return an array of plyr instances setup, so you need to specify the index of the instance you want. This is less useful if you are setting up mutliple instances. You can also use the `onSetup` callback documented below which will return each instance one by one, as they are setup. + +Once you have your instance, you can use the API methods below on it. For example to pause it: ```javascript -document.querySelectorAll(".player")[0].plyr.pause(); +player.pause(); ``` Here's a list of the methods supported: @@ -287,8 +370,8 @@ Here's a list of the methods supported: <th width="15%">Parameters</th> <th width="65%">Description</th> </tr> - </thead> - <tbody> +</thead> +<tbody> <tr> <td><code>play()</code></td> <td>—</td> @@ -356,7 +439,7 @@ Here's a list of the methods supported: </tr> <tr> <td><code>source(...)</code></td> - <td>String or Array</td> + <td>Array</td> <td> Set the media source. <br><br> @@ -390,12 +473,118 @@ Here's a list of the methods supported: </tbody> </table> +#### .source() method + +This allows changing the plyr source and type on the fly. + +Video example: + +```javascript +player.source({ + type: 'video', + title: 'Bug Buck Bunny', + sources: [{ + src: 'https://cdn.selz.com/plyr/1.0/movie.mp4', + type: 'video/mp4' + }, + { + src: 'https://cdn.selz.com/plyr/1.0/movie.webm', + type: 'video/webm' + }], + poster: 'https://cdn.selz.com/plyr/1.0/poster.jpg', + tracks: [{ + kind: 'captions', + label: 'English', + srclang:'en', + src: 'https://cdn.selz.com/plyr/1.0/example_captions_en.vtt', + default: true + }] +}); +``` + +Audio example: + +```javascript +player.source({ + type: 'audio', + title: '96 by Logistics', + sources: [{ + src: 'https://cdn.selz.com/plyr/1.0/logistics-96-sample.mp3', + type: 'audio/mp3' + }, + { + src: 'https://cdn.selz.com/plyr/1.0/logistics-96-sample.ogg', + type: 'audio/ogg' + }] +}); +``` + +YouTube example: + +```javascript +player.source({ + type: 'youtube', + title: 'Enovato interview of Dan Cederholm for Made By', + sources: 'Au87oAJ2jeE' +}); +``` + +Vimeo example + +```javascript +player.source({ + type: 'vimeo', + title: 'Yosemite HD II', + sources: '87701971' +}); +``` + +Some more details on the object parameters + +<table class="table" width="100%"> + <thead> + <tr> + <th width="20%">Key</th> + <th width="15%">Type</th> + <th width="65%">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>type</code></td> + <td>String</td> + <td>Options are <code>video</code>, <code>audio</code>, <code>youtube</code> and <code>vimeo</code></td> + </tr> + <tr> + <td><code>title</code></td> + <td>String</td> + <td>Title of the new media. Used for the aria labelling.</td> + </tr> + <tr> + <td><code>sources</code></td> + <td>Array or String</td> + <td>This is an array of sources or optionally a string for embedded players (YouTube and Vimeo). `type` is also optional for YouTube and Vimeo when specifying an array. For YouTube and Vimeo media, only the video ID 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.</td> + </tr> + <tr> + <td><code>poster</code></td> + <td>String</td> + <td>URL for the poster image (video only).</td> + </tr> + <tr> + <td><code>tracks</code></td> + <td>Array</td> + <td>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 `<track kind="captions" label="English" srclang="en" src="https://cdn.selz.com/plyr/1.0/example_captions_en.vtt" default>`. Booleans are converted to HTML5 value-less attributes.</td> + </tr> + </tbody> +</table> + + ## Events/Callbacks The `plyr` object on the player element also contains a `media` property which is a reference to the `<audio>` or `<video>` element within the player which you can use to listen for events. Here's an example: ```javascript -var media = document.querySelectorAll(".player")[0].plyr.media; +var media = document.querySelector(".plyr").plyr.media; media.addEventListener("playing", function() { console.log("playing"); @@ -415,7 +604,7 @@ Currently only YouTube is supported. Vimeo will be coming soon. Some HTML5 media Due to the way the YouTube API works, the `timeupdate` and `progress` events are triggered by polling every 200ms so the event may trigger without an actual value change. Buffering progress is `media.buffered` in the `plyr` object. It is a a number between 0 and 1 that specifies the percentage of the video that the player shows as buffered. ```javascript -document.querySelector(".player").plyr.media.addEventListener("play", function() { +document.querySelector(".plyr").plyr.media.addEventListener("play", function() { console.log("play"); }); ``` @@ -426,7 +615,7 @@ Currently caption control is not supported but I will work on this. ## Fullscreen -Fullscreen in Plyr is supported for all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). If you're using the default CSS, you can also use a "full browser" mode which will use the full browser window by adding the `player-fullscreen` class to your container. +Fullscreen in Plyr is supported for all browsers that [currently support it](http://caniuse.com/#feat=fullscreen). If you're using the default CSS, you can also use a "full browser" mode which will use the full browser window by adding the `plyr-fullscreen` class to your container. ## Browser support diff --git a/src/js/plyr.js b/src/js/plyr.js index ed328202..55bfd62e 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -1,6 +1,6 @@ // ========================================================================== // Plyr -// plyr.js v1.3.6 +// plyr.js v1.4.0 // https://github.com/selz/plyr // License: The MIT License (MIT) // ========================================================================== @@ -9,16 +9,17 @@ (function (api) { 'use strict'; - /*global YT*/ + /*global YT,$f*/ // Globals - var fullscreen, config, callbacks = { youtube: [] }; + var fullscreen, config; // Default config var defaults = { enabled: true, debug: false, autoplay: false, + loop: false, seekTime: 10, volume: 5, click: true, @@ -26,41 +27,41 @@ displayDuration: true, iconPrefix: 'icon', selectors: { - container: '.player', - controls: '.player-controls', - labels: '[data-player] .sr-only, label .sr-only', + container: '.plyr', + controls: '.plyr-controls', + labels: '[data-plyr] .sr-only, label .sr-only', buttons: { - seek: '[data-player="seek"]', - play: '[data-player="play"]', - pause: '[data-player="pause"]', - restart: '[data-player="restart"]', - rewind: '[data-player="rewind"]', - forward: '[data-player="fast-forward"]', - mute: '[data-player="mute"]', - volume: '[data-player="volume"]', - captions: '[data-player="captions"]', - fullscreen: '[data-player="fullscreen"]' + seek: '[data-plyr="seek"]', + 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"]', + volume: '[data-plyr="volume"]', + captions: '[data-plyr="captions"]', + fullscreen: '[data-plyr="fullscreen"]' }, progress: { - container: '.player-progress', - buffer: '.player-progress-buffer', - played: '.player-progress-played' + container: '.plyr-progress', + buffer: '.plyr-progress-buffer', + played: '.plyr-progress-played' }, - captions: '.player-captions', - currentTime: '.player-current-time', - duration: '.player-duration' + captions: '.plyr-captions', + currentTime: '.plyr-current-time', + duration: '.plyr-duration' }, classes: { - videoWrapper: 'player-video-wrapper', - embedWrapper: 'player-video-embed', - type: 'player-{0}', + videoWrapper: 'plyr-video-wrapper', + embedWrapper: 'plyr-video-embed', + type: 'plyr-{0}', stopped: 'stopped', playing: 'playing', muted: 'muted', loading: 'loading', - tooltip: 'player-tooltip', + tooltip: 'plyr-tooltip', hidden: 'sr-only', - hover: 'player-hover', + hover: 'plyr-hover', captions: { enabled: 'captions-enabled', active: 'captions-active' @@ -77,7 +78,8 @@ fullscreen: { enabled: true, fallback: true, - hideControls: true + hideControls: true, + allowAudio: false }, storage: { enabled: true, @@ -98,6 +100,18 @@ toggleMute: 'Toggle Mute', toggleCaptions: 'Toggle Captions', toggleFullscreen: 'Toggle Fullscreen' + }, + types: { + embed: ['youtube','vimeo'], + html5: ['video', 'audio'] + }, + urls: { + vimeo: { + api: 'https://f.vimeocdn.com/js/froogaloop2.min.js' + }, + youtube: { + api: 'https://www.youtube.com/iframe_api' + } } }; @@ -105,23 +119,23 @@ function _buildControls() { // Open and add the progress and seek elements var html = [ - '<div class="player-controls">', - '<div class="player-progress">', + '<div class="plyr-controls">', + '<div class="plyr-progress">', '<label for="seek{id}" class="sr-only">Seek</label>', - '<input id="seek{id}" class="player-progress-seek" type="range" min="0" max="100" step="0.5" value="0" data-player="seek">', - '<progress class="player-progress-played" max="100" value="0">', + '<input id="seek{id}" class="plyr-progress-seek" type="range" min="0" max="100" step="0.5" value="0" data-plyr="seek">', + '<progress class="plyr-progress-played" max="100" value="0">', '<span>0</span>% ' + config.i18n.played, '</progress>', - '<progress class="player-progress-buffer" max="100" value="0">', + '<progress class="plyr-progress-buffer" max="100" value="0">', '<span>0</span>% ' + config.i18n.buffered, '</progress>', '</div>', - '<span class="player-controls-left">']; + '<span class="plyr-controls-left">']; // Restart button if (_inArray(config.controls, 'restart')) { html.push( - '<button type="button" data-player="restart">', + '<button type="button" data-plyr="restart">', '<svg><use xlink:href="#' + config.iconPrefix + '-restart" /></svg>', '<span class="sr-only">' + config.i18n.restart + '</span>', '</button>' @@ -131,7 +145,7 @@ // Rewind button if (_inArray(config.controls, 'rewind')) { html.push( - '<button type="button" data-player="rewind">', + '<button type="button" data-plyr="rewind">', '<svg><use xlink:href="#' + config.iconPrefix + '-rewind" /></svg>', '<span class="sr-only">' + config.i18n.rewind + '</span>', '</button>' @@ -141,11 +155,11 @@ // Play/pause button if (_inArray(config.controls, 'play')) { html.push( - '<button type="button" data-player="play">', + '<button type="button" data-plyr="play">', '<svg><use xlink:href="#' + config.iconPrefix + '-play" /></svg>', '<span class="sr-only">' + config.i18n.play + '</span>', '</button>', - '<button type="button" data-player="pause">', + '<button type="button" data-plyr="pause">', '<svg><use xlink:href="#' + config.iconPrefix + '-pause" /></svg>', '<span class="sr-only">' + config.i18n.pause + '</span>', '</button>' @@ -155,7 +169,7 @@ // Fast forward button if (_inArray(config.controls, 'fast-forward')) { html.push( - '<button type="button" data-player="fast-forward">', + '<button type="button" data-plyr="fast-forward">', '<svg><use xlink:href="#' + config.iconPrefix + '-fast-forward" /></svg>', '<span class="sr-only">' + config.i18n.forward + '</span>', '</button>' @@ -165,9 +179,9 @@ // Media current time display if (_inArray(config.controls, 'current-time')) { html.push( - '<span class="player-time">', + '<span class="plyr-time">', '<span class="sr-only">' + config.i18n.currentTime + '</span>', - '<span class="player-current-time">00:00</span>', + '<span class="plyr-current-time">00:00</span>', '</span>' ); } @@ -175,9 +189,9 @@ // Media duration display if (_inArray(config.controls, 'duration')) { html.push( - '<span class="player-time">', + '<span class="plyr-time">', '<span class="sr-only">' + config.i18n.duration + '</span>', - '<span class="player-duration">00:00</span>', + '<span class="plyr-duration">00:00</span>', '</span>' ); } @@ -185,13 +199,13 @@ // Close left controls html.push( '</span>', - '<span class="player-controls-right">' + '<span class="plyr-controls-right">' ); // Toggle mute button if (_inArray(config.controls, 'mute')) { html.push( - '<button type="button" data-player="mute">', + '<button type="button" data-plyr="mute">', '<svg class="icon-muted"><use xlink:href="#' + config.iconPrefix + '-muted" /></svg>', '<svg><use xlink:href="#' + config.iconPrefix + '-volume" /></svg>', '<span class="sr-only">' + config.i18n.toggleMute + '</span>', @@ -203,14 +217,14 @@ if (_inArray(config.controls, 'volume')) { html.push( '<label for="volume{id}" class="sr-only">' + config.i18n.volume + '</label>', - '<input id="volume{id}" class="player-volume" type="range" min="0" max="10" value="5" data-player="volume">' + '<input id="volume{id}" class="plyr-volume" type="range" min="0" max="10" value="5" data-plyr="volume">' ); } // Toggle captions button if (_inArray(config.controls, 'captions')) { html.push( - '<button type="button" data-player="captions">', + '<button type="button" data-plyr="captions">', '<svg class="icon-captions-on"><use xlink:href="#' + config.iconPrefix + '-captions-on" /></svg>', '<svg><use xlink:href="#' + config.iconPrefix + '-captions-off" /></svg>', '<span class="sr-only">' + config.i18n.toggleCaptions + '</span>', @@ -221,7 +235,7 @@ // Toggle fullscreen button if (_inArray(config.controls, 'fullscreen')) { html.push( - '<button type="button" data-player="fullscreen">', + '<button type="button" data-plyr="fullscreen">', '<svg class="icon-exit-fullscreen"><use xlink:href="#' + config.iconPrefix + '-exit-fullscreen" /></svg>', '<svg><use xlink:href="#' + config.iconPrefix + '-enter-fullscreen" /></svg>', '<span class="sr-only">' + config.i18n.toggleFullscreen + '</span>', @@ -317,12 +331,12 @@ // Check for mime type support against a player instance // Credits: http://diveintohtml5.info/everything.html - // Related: http://www.leanbackplayer.com/test/h5mt.html - function _supportMime(player, mimeType) { - var media = player.media; + // Related: http://www.leanbackplyr.com/test/h5mt.html + function _supportMime(plyr, mimeType) { + var media = plyr.media; // Only check video types for video players - if (player.type == 'video') { + if (plyr.type == 'video') { // Check type switch (mimeType) { case 'video/webm': return !!(media.canPlayType && media.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, '')); @@ -332,7 +346,7 @@ } // Only check audio types for audio players - else if (player.type == 'audio') { + else if (plyr.type == 'audio') { // Check type switch (mimeType) { case 'audio/mpeg': return !!(media.canPlayType && media.canPlayType('audio/mpeg;').replace(/no/, '')); @@ -428,10 +442,27 @@ // Set attributes function _setAttributes(element, attributes) { for (var key in attributes) { - element.setAttribute(key, attributes[key]); + element.setAttribute(key, (typeof attributes[key] === 'boolean' && attributes[key]) ? '' : attributes[key]); } } + // Insert a HTML element + function _insertElement(type, parent, attributes) { + // Create a new <element> + var element = document.createElement(type); + + // Set all passed attributes + _setAttributes(element, attributes); + + // Inject the new element + _prependChild(parent, element); + } + + // Get a classname from selector + function _getClassname(selector) { + return selector.replace('.', ''); + } + // Toggle class on an element function _toggleClass(element, name, state) { if (element) { @@ -614,68 +645,73 @@ // Player instance function Plyr(container) { - var player = this; - player.container = container; + var plyr = this; + plyr.container = container; // Captions functions // Seek the manual caption time and update UI function _seekManualCaptions(time) { // If it's not video, or we're using textTracks, bail. - if (player.usingTextTracks || player.type !== 'video' || !player.supported.full) { + if (plyr.usingTextTracks || plyr.type !== 'video' || !plyr.supported.full) { return; } // Reset subcount - player.subcount = 0; + plyr.subcount = 0; // Check time is a number, if not use currentTime // IE has a bug where currentTime doesn't go to 0 // https://twitter.com/Sam_Potts/status/573715746506731521 - time = typeof time === 'number' ? time : player.media.currentTime; + time = typeof time === 'number' ? time : plyr.media.currentTime; + + // If there's no subs available, bail + if (!plyr.captions[plyr.subcount]) { + return; + } - while (_timecodeMax(player.captions[player.subcount][0]) < time.toFixed(1)) { - player.subcount++; - if (player.subcount > player.captions.length-1) { - player.subcount = player.captions.length-1; + while (_timecodeMax(plyr.captions[plyr.subcount][0]) < time.toFixed(1)) { + plyr.subcount++; + if (plyr.subcount > plyr.captions.length-1) { + plyr.subcount = plyr.captions.length-1; break; } } // Check if the next caption is in the current time range - if (player.media.currentTime.toFixed(1) >= _timecodeMin(player.captions[player.subcount][0]) && - player.media.currentTime.toFixed(1) <= _timecodeMax(player.captions[player.subcount][0])) { - player.currentCaption = player.captions[player.subcount][1]; + if (plyr.media.currentTime.toFixed(1) >= _timecodeMin(plyr.captions[plyr.subcount][0]) && + plyr.media.currentTime.toFixed(1) <= _timecodeMax(plyr.captions[plyr.subcount][0])) { + plyr.currentCaption = plyr.captions[plyr.subcount][1]; // Trim caption text - var content = player.currentCaption.trim(); + var content = plyr.currentCaption.trim(); // Render the caption (only if changed) - if (player.captionsContainer.innerHTML != content) { + if (plyr.captionsContainer.innerHTML != content) { // Empty caption // Otherwise NVDA reads it twice - player.captionsContainer.innerHTML = ''; + plyr.captionsContainer.innerHTML = ''; // Set new caption text - player.captionsContainer.innerHTML = content; + plyr.captionsContainer.innerHTML = content; } } else { - player.captionsContainer.innerHTML = ''; + plyr.captionsContainer.innerHTML = ''; } } // Display captions container and button (for initialization) function _showCaptions() { // If there's no caption toggle, bail - if (!player.buttons.captions) { + if (!plyr.buttons.captions) { return; } - _toggleClass(player.container, config.classes.captions.enabled, true); + _toggleClass(plyr.container, config.classes.captions.enabled, true); if (config.captions.defaultActive) { - _toggleClass(player.container, config.classes.captions.active, true); - _toggleState(player.buttons.captions, true); + _toggleClass(plyr.container, config.classes.captions.active, true); + _toggleState(plyr.buttons.captions, true); } } @@ -707,7 +743,7 @@ // Find all elements function _getElements(selector) { - return player.container.querySelectorAll(selector); + return plyr.container.querySelectorAll(selector); } // Find a single element @@ -745,7 +781,7 @@ html = _replaceAll(html, '{id}', Math.floor(Math.random() * (10000))); // Inject into the container - player.container.insertAdjacentHTML('beforeend', html); + plyr.container.insertAdjacentHTML('beforeend', html); // Setup tooltips if (config.tooltips) { @@ -763,44 +799,44 @@ // Find the UI controls and store references function _findElements() { try { - player.controls = _getElement(config.selectors.controls); + plyr.controls = _getElement(config.selectors.controls); // Buttons - player.buttons = {}; - player.buttons.seek = _getElement(config.selectors.buttons.seek); - player.buttons.play = _getElement(config.selectors.buttons.play); - player.buttons.pause = _getElement(config.selectors.buttons.pause); - player.buttons.restart = _getElement(config.selectors.buttons.restart); - player.buttons.rewind = _getElement(config.selectors.buttons.rewind); - player.buttons.forward = _getElement(config.selectors.buttons.forward); - player.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen); + plyr.buttons = {}; + plyr.buttons.seek = _getElement(config.selectors.buttons.seek); + plyr.buttons.play = _getElement(config.selectors.buttons.play); + plyr.buttons.pause = _getElement(config.selectors.buttons.pause); + plyr.buttons.restart = _getElement(config.selectors.buttons.restart); + plyr.buttons.rewind = _getElement(config.selectors.buttons.rewind); + plyr.buttons.forward = _getElement(config.selectors.buttons.forward); + plyr.buttons.fullscreen = _getElement(config.selectors.buttons.fullscreen); // Inputs - player.buttons.mute = _getElement(config.selectors.buttons.mute); - player.buttons.captions = _getElement(config.selectors.buttons.captions); - player.checkboxes = _getElements('[type="checkbox"]'); + plyr.buttons.mute = _getElement(config.selectors.buttons.mute); + plyr.buttons.captions = _getElement(config.selectors.buttons.captions); + plyr.checkboxes = _getElements('[type="checkbox"]'); // Progress - player.progress = {}; - player.progress.container = _getElement(config.selectors.progress.container); + plyr.progress = {}; + plyr.progress.container = _getElement(config.selectors.progress.container); // Progress - Buffering - player.progress.buffer = {}; - player.progress.buffer.bar = _getElement(config.selectors.progress.buffer); - player.progress.buffer.text = player.progress.buffer.bar && player.progress.buffer.bar.getElementsByTagName('span')[0]; + plyr.progress.buffer = {}; + plyr.progress.buffer.bar = _getElement(config.selectors.progress.buffer); + plyr.progress.buffer.text = plyr.progress.buffer.bar && plyr.progress.buffer.bar.getElementsByTagName('span')[0]; // Progress - Played - player.progress.played = {}; - player.progress.played.bar = _getElement(config.selectors.progress.played); - player.progress.played.text = player.progress.played.bar && player.progress.played.bar.getElementsByTagName('span')[0]; + plyr.progress.played = {}; + plyr.progress.played.bar = _getElement(config.selectors.progress.played); + plyr.progress.played.text = plyr.progress.played.bar && plyr.progress.played.bar.getElementsByTagName('span')[0]; // Volume - player.volume = _getElement(config.selectors.buttons.volume); + plyr.volume = _getElement(config.selectors.buttons.volume); // Timing - player.duration = _getElement(config.selectors.duration); - player.currentTime = _getElement(config.selectors.currentTime); - player.seekTime = _getElements(config.selectors.seekTime); + plyr.duration = _getElement(config.selectors.duration); + plyr.currentTime = _getElement(config.selectors.currentTime); + plyr.seekTime = _getElements(config.selectors.seekTime); return true; } @@ -808,7 +844,7 @@ _log('It looks like there\'s a problem with your controls html. Bailing.', true); // Restore native video controls - player.media.setAttribute('controls', ''); + plyr.media.setAttribute('controls', ''); return false; } @@ -817,126 +853,178 @@ // Setup aria attribute for play function _setupPlayAria() { // If there's no play button, bail - if (!player.buttons.play) { + if (!plyr.buttons.play) { return; } // Find the current text - var label = player.buttons.play.innerText || config.i18n.play; + var label = plyr.buttons.play.innerText || config.i18n.play; // If there's a media title set, use that for the label if (typeof(config.title) !== 'undefined' && config.title.length) { label += ', ' + config.title; } - player.buttons.play.setAttribute('aria-label', label); + plyr.buttons.play.setAttribute('aria-label', label); } // Setup media function _setupMedia() { // If there's no media, bail - if (!player.media) { + if (!plyr.media) { _log('No audio or video element found!', true); return false; } - if (player.supported.full) { + if (plyr.supported.full) { // Remove native video controls - player.media.removeAttribute('controls'); + plyr.media.removeAttribute('controls'); // Add type class - _toggleClass(player.container, config.classes.type.replace('{0}', player.type), true); + _toggleClass(plyr.container, config.classes.type.replace('{0}', plyr.type), true); // If there's no autoplay attribute, assume the video is stopped and add state class - _toggleClass(player.container, config.classes.stopped, ((player.media.getAttribute('autoplay') === null) && !config.autoplay)); + _toggleClass(plyr.container, config.classes.stopped, config.autoplay); // Add iOS class - if (player.browser.ios) { - _toggleClass(player.container, 'ios', true); + if (plyr.browser.ios) { + _toggleClass(plyr.container, 'ios', true); } // Inject the player wrapper - if (player.type === 'video') { + if (plyr.type === 'video') { // Create the wrapper div var wrapper = document.createElement('div'); wrapper.setAttribute('class', config.classes.videoWrapper); // Wrap the video in a container - _wrap(player.media, wrapper); + _wrap(plyr.media, wrapper); // Cache the container - player.videoContainer = wrapper; + plyr.videoContainer = wrapper; } } - // YouTube - if (player.type == 'youtube') { - _setupYouTube(player.media.getAttribute('data-video-id')); - } + // Embeds + if (_inArray(config.types.embed, plyr.type)) { + _setupEmbed(plyr.embedId, plyr.type); - // Autoplay - if (player.media.getAttribute('autoplay') !== null || config.autoplay) { - _play(); + // Clean up + plyr.embedId = null; + } + else { + // Autoplay + if (config.autoplay) { + _play(); + } } } - // Setup YouTube - function _setupYouTube(id) { + // Setup YouTube/Vimeo + function _setupEmbed(videoId) { + var container = document.createElement('div'), + id = plyr.type + '-' + Math.floor(Math.random() * (10000)); + // Remove old containers - var containers = _getElements('[id^="youtube"]'); + var containers = _getElements('[id^="' + plyr.type + '-"]'); for (var i = containers.length - 1; i >= 0; i--) { _remove(containers[i]); } - // Create the YouTube container - var container = document.createElement('div'); - container.setAttribute('id', 'youtube-' + Math.floor(Math.random() * (10000))); - player.media.appendChild(container); - // Add embed class for responsive - _toggleClass(player.media, config.classes.videoWrapper, true); - _toggleClass(player.media, config.classes.embedWrapper, true); + _toggleClass(plyr.media, config.classes.videoWrapper, true); + _toggleClass(plyr.media, config.classes.embedWrapper, true); - if (typeof YT === 'object') { - _YTReady(id, container); - } - else { - // Load the API - _injectScript('https://www.youtube.com/iframe_api'); + // YouTube + if (plyr.type === 'youtube') { + // Create the YouTube container + plyr.media.appendChild(container); - // Add callback to queue - callbacks.youtube.push(function() { _YTReady(id, container); }); + // Set ID + container.setAttribute('id', id); - // Setup callback for the API - window.onYouTubeIframeAPIReady = function () { - for (var i = callbacks.youtube.length - 1; i >= 0; i--) { - // Fire callback - callbacks.youtube[i](); + // Setup API + if (typeof YT === 'object') { + _youTubeReady(videoId, container); + } + else { + // Load the API + _injectScript(config.urls.youtube.api); - // Remove from queue - callbacks.youtube.splice(i, 1); - } - }; + // Setup callback for the API + window.onYouTubeIframeAPIReady = function () { _youTubeReady(videoId, container); }; + } + } + // Vimeo + else if (plyr.type === 'vimeo') { + // Inject the iframe + var iframe = document.createElement('iframe'); + + // Watch for iframe load + iframe.loaded = false; + _on(iframe, 'load', function() { iframe.loaded = true; }); + + _setAttributes(iframe, { + 'src': 'https://player.vimeo.com/video/' + videoId + '?player_id=' + id + '&api=1&badge=0&byline=0&portrait=0&title=0', + 'id': id, + 'webkitallowfullscreen': '', + 'mozallowfullscreen': '', + 'allowfullscreen': '', + 'frameborder': 0 + }); + container.appendChild(iframe); + plyr.media.appendChild(container); + + // Setup API + if (typeof Froogaloop === 'function') { + _on(iframe, 'load', _vimeoReady); + } + else { + // Load the API + _injectScript(config.urls.vimeo.api); + + // Wait for fragaloop load + var timer = window.setInterval(function() { + if ('$f' in window && iframe.loaded) { + window.clearInterval(timer); + + _vimeoReady.call(iframe); + } + }, 50); + } } } - // Handle API ready - function _YTReady(id, container) { - _log('YouTube API Ready'); + // When embeds are ready + function _embedReady() { + // Inject and update UI + if (plyr.supported.full) { + // Only setup controls once + if (!plyr.container.querySelectorAll(config.selectors.controls).length) { + _setupInterface(); + } + } + + // Set the volume + _setVolume(); + _updateVolume(); + } + // Handle YouTube API ready + function _youTubeReady(videoId, container) { // Setup timers object // We have to poll YouTube for updates - if (!('timer' in player)) { - player.timer = {}; + if (!('timer' in plyr)) { + plyr.timer = {}; } // Setup instance // https://developers.google.com/youtube/iframe_api_reference - player.embed = new YT.Player(container.id, { - videoId: id, + plyr.embed = new YT.Player(container.id, { + videoId: videoId, playerVars: { autoplay: (config.autoplay ? 1 : 0), - controls: (player.supported.full ? 0 : 1), + controls: (plyr.supported.full ? 0 : 1), rel: 0, showinfo: 0, iv_load_policy: 3, @@ -952,44 +1040,40 @@ var instance = event.target; // Create a faux HTML5 API using the YouTube API - player.media.play = function() { instance.playVideo(); }; - player.media.pause = function() { instance.pauseVideo(); }; - player.media.stop = function() { instance.stopVideo(); }; - player.media.duration = instance.getDuration(); - player.media.paused = true; - player.media.currentTime = instance.getCurrentTime(); - player.media.muted = instance.isMuted(); + plyr.media.play = function() { instance.playVideo(); }; + plyr.media.pause = function() { instance.pauseVideo(); }; + plyr.media.stop = function() { instance.stopVideo(); }; + plyr.media.duration = instance.getDuration(); + plyr.media.paused = !config.autoplay; + plyr.media.currentTime = instance.getCurrentTime(); + plyr.media.muted = instance.isMuted(); // Trigger timeupdate - _triggerEvent(player.media, 'timeupdate'); + _triggerEvent(plyr.media, 'timeupdate'); // Reset timer - window.clearInterval(player.timer.buffering); + window.clearInterval(plyr.timer.buffering); // Setup buffering - player.timer.buffering = window.setInterval(function() { + plyr.timer.buffering = window.setInterval(function() { // Get loaded % from YouTube - player.media.buffered = instance.getVideoLoadedFraction(); + plyr.media.buffered = instance.getVideoLoadedFraction(); // Trigger progress - _triggerEvent(player.media, 'progress'); + _triggerEvent(plyr.media, 'progress'); // Bail if we're at 100% - if (player.media.buffered === 1) { - window.clearInterval(player.timer.buffering); + if (plyr.media.buffered === 1) { + window.clearInterval(plyr.timer.buffering); } }, 200); - if (player.supported.full) { - // Only setup controls once - if (!player.container.querySelectorAll(config.selectors.controls).length) { - _setupInterface(); - } + // Update UI + _embedReady(); - // Display duration if available - if (config.displayDuration) { - _displayDuration(); - } + // Display duration if available + if (config.displayDuration) { + _displayDuration(); } }, 'onStateChange': function(event) { @@ -997,7 +1081,7 @@ var instance = event.target; // Reset timer - window.clearInterval(player.timer.playing); + window.clearInterval(plyr.timer.playing); // Handle events // -1 Unstarted @@ -1008,53 +1092,124 @@ // 5 Video cued switch (event.data) { case 0: - player.media.paused = true; - _triggerEvent(player.media, 'ended'); + plyr.media.paused = true; + _triggerEvent(plyr.media, 'ended'); break; case 1: - player.media.paused = false; - _triggerEvent(player.media, 'play'); + plyr.media.paused = false; + _triggerEvent(plyr.media, 'play'); // Poll to get playback progress - player.timer.playing = window.setInterval(function() { + plyr.timer.playing = window.setInterval(function() { // Set the current time - player.media.currentTime = instance.getCurrentTime(); + plyr.media.currentTime = instance.getCurrentTime(); // Trigger timeupdate - _triggerEvent(player.media, 'timeupdate'); + _triggerEvent(plyr.media, 'timeupdate'); }, 200); break; case 2: - player.media.paused = true; - _triggerEvent(player.media, 'pause'); + plyr.media.paused = true; + _triggerEvent(plyr.media, 'pause'); } } } }); } + // Vimeo ready + function _vimeoReady() { + /* jshint validthis: true */ + plyr.embed = $f(this); + + // Setup on ready + plyr.embed.addEvent('ready', function() { + + // Create a faux HTML5 API using the Vimeo API + plyr.media.play = function() { plyr.embed.api('play'); }; + plyr.media.pause = function() { plyr.embed.api('pause'); }; + plyr.media.stop = function() { plyr.embed.api('stop') }; + plyr.media.paused = !config.autoplay; + plyr.media.currentTime = 0; + + // Update UI + _embedReady(); + + plyr.embed.api('getCurrentTime', function (value) { + plyr.media.currentTime = value; + + // Trigger timeupdate + _triggerEvent(plyr.media, 'timeupdate'); + }); + + plyr.embed.api('getDuration', function(value) { + plyr.media.duration = value; + + // Display duration if available + if (plyr.supported.full && config.displayDuration) { + _displayDuration(); + } + }); + + plyr.embed.addEvent('play', function() { + plyr.media.paused = false; + _triggerEvent(plyr.media, 'play'); + }); + + plyr.embed.addEvent('pause', function() { + plyr.media.paused = true; + _triggerEvent(plyr.media, 'pause'); + }); + + plyr.embed.addEvent('playProgress', function(data) { + plyr.media.currentTime = data.seconds; + _triggerEvent(plyr.media, 'timeupdate'); + }); + + plyr.embed.addEvent('loadProgress', function(data) { + plyr.media.buffered = data.percent; + _triggerEvent(plyr.media, 'progress'); + }); + + plyr.embed.addEvent('finish', function() { + plyr.media.paused = true; + _triggerEvent(plyr.media, 'ended'); + }); + + // Always seek to 0 + //plyr.embed.api('seekTo', 0); + + // Prevent autoplay if needed (seek will play) + //if (!config.autoplay) { + // plyr.embed.api('pause'); + //} + }); + } + // Setup captions function _setupCaptions() { - if (player.type === 'video') { + if (plyr.type === 'video') { // Inject the container - player.videoContainer.insertAdjacentHTML('afterbegin', '<div class="' + config.selectors.captions.replace('.', '') + '"><span></span></div>'); + if (!_getElement(config.selectors.captions)) { + plyr.videoContainer.insertAdjacentHTML('afterbegin', '<div class="' + _getClassname(config.selectors.captions) + '"><span></span></div>'); + } // Cache selector - player.captionsContainer = _getElement(config.selectors.captions).querySelector('span'); + plyr.captionsContainer = _getElement(config.selectors.captions).querySelector('span'); // Determine if HTML5 textTracks is supported - player.usingTextTracks = false; - if (player.media.textTracks) { - player.usingTextTracks = true; + plyr.usingTextTracks = false; + if (plyr.media.textTracks) { + plyr.usingTextTracks = true; } // Get URL of caption file if exists var captionSrc = '', kind, - children = player.media.childNodes; + children = plyr.media.childNodes; for (var i = 0; i < children.length; i++) { if (children[i].nodeName.toLowerCase() === 'track') { @@ -1066,9 +1221,9 @@ } // Record if caption file exists or not - player.captionExists = true; + plyr.captionExists = true; if (captionSrc === '') { - player.captionExists = false; + plyr.captionExists = false; _log('No caption track found.'); } else { @@ -1076,36 +1231,36 @@ } // If no caption file exists, hide container for caption text - if (!player.captionExists) { - _toggleClass(player.container, config.classes.captions.enabled); + if (!plyr.captionExists) { + _toggleClass(plyr.container, config.classes.captions.enabled); } // If caption file exists, process captions else { // Turn off native caption rendering to avoid double captions // This doesn't seem to work in Safari 7+, so the <track> elements are removed from the dom below - var tracks = player.media.textTracks; + var tracks = plyr.media.textTracks; for (var x = 0; x < tracks.length; x++) { tracks[x].mode = 'hidden'; } // Enable UI - _showCaptions(player); + _showCaptions(plyr); // Disable unsupported browsers than report false positive - if ((player.browser.name === 'IE' && player.browser.version >= 10) || - (player.browser.name === 'Firefox' && player.browser.version >= 31) || - (player.browser.name === 'Chrome' && player.browser.version >= 43) || - (player.browser.name === 'Safari' && player.browser.version >= 7)) { + if ((plyr.browser.name === 'IE' && plyr.browser.version >= 10) || + (plyr.browser.name === 'Firefox' && plyr.browser.version >= 31) || + (plyr.browser.name === 'Chrome' && plyr.browser.version >= 43) || + (plyr.browser.name === 'Safari' && plyr.browser.version >= 7)) { // Debugging _log('Detected unsupported browser for HTML5 captions. Using fallback.'); // Set to false so skips to 'manual' captioning - player.usingTextTracks = false; + plyr.usingTextTracks = false; } // Rendering caption tracks // Native support required - http://caniuse.com/webvtt - if (player.usingTextTracks) { + if (plyr.usingTextTracks) { _log('TextTracks supported.'); for (var y = 0; y < tracks.length; y++) { @@ -1114,11 +1269,11 @@ if (track.kind === 'captions' || track.kind === 'subtitles') { _on(track, 'cuechange', function() { // Clear container - player.captionsContainer.innerHTML = ''; + plyr.captionsContainer.innerHTML = ''; // Display a cue, if there is one if (this.activeCues[0] && this.activeCues[0].hasOwnProperty('text')) { - player.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML().trim()); + plyr.captionsContainer.appendChild(this.activeCues[0].getCueAsHTML().trim()); } }); } @@ -1129,8 +1284,8 @@ _log('TextTracks not supported so rendering captions manually.'); // Render captions from array at appropriate time - player.currentCaption = ''; - player.captions = []; + plyr.currentCaption = ''; + plyr.captions = []; if (captionSrc !== '') { // Create XMLHttpRequest Object @@ -1147,12 +1302,12 @@ for (var r = 0; r < records.length; r++) { record = records[r]; - player.captions[r] = []; - player.captions[r] = record.split('\n'); + plyr.captions[r] = []; + plyr.captions[r] = record.split('\n'); } // Remove first element ('VTT') - player.captions.shift(); + plyr.captions.shift(); _log('Successfully loaded the caption file via AJAX.'); } @@ -1169,15 +1324,15 @@ } // If Safari 7+, removing track from DOM [see 'turn off native caption rendering' above] - if (player.browser.name === 'Safari' && player.browser.version >= 7) { + if (plyr.browser.name === 'Safari' && plyr.browser.version >= 7) { _log('Safari 7+ detected; removing track from DOM.'); // Find all <track> elements - tracks = player.media.getElementsByTagName('track'); + tracks = plyr.media.getElementsByTagName('track'); // Loop through and remove one by one for (var t = 0; t < tracks.length; t++) { - player.media.removeChild(tracks[t]); + plyr.media.removeChild(tracks[t]); } } } @@ -1186,7 +1341,7 @@ // Setup fullscreen function _setupFullscreen() { - if (player.type != 'audio' && config.fullscreen.enabled) { + if ((plyr.type != 'audio' || config.fullscreen.allowAudio) && config.fullscreen.enabled) { // Check for native support var nativeSupport = fullscreen.supportsFullScreen; @@ -1194,30 +1349,30 @@ _log((nativeSupport ? 'Native' : 'Fallback') + ' fullscreen enabled.'); // Add styling hook - _toggleClass(player.container, config.classes.fullscreen.enabled, true); + _toggleClass(plyr.container, config.classes.fullscreen.enabled, true); } else { _log('Fullscreen not supported and fallback disabled.'); } // Toggle state - _toggleState(player.buttons.fullscreen, false); + _toggleState(plyr.buttons.fullscreen, false); // Set control hide class hook if (config.fullscreen.hideControls) { - _toggleClass(player.container, config.classes.fullscreen.hideControls, true); + _toggleClass(plyr.container, config.classes.fullscreen.hideControls, true); } } } // Play media function _play() { - player.media.play(); + plyr.media.play(); } // Pause media function _pause() { - player.media.pause(); + plyr.media.pause(); } // Toggle playback @@ -1232,7 +1387,7 @@ } // True toggle else { - player.media[player.media.paused ? 'play' : 'pause'](); + plyr.media[plyr.media.paused ? 'play' : 'pause'](); } } @@ -1242,7 +1397,7 @@ if (typeof seekTime !== 'number') { seekTime = config.seekTime; } - _seek(player.media.currentTime - seekTime); + _seek(plyr.media.currentTime - seekTime); } // Fast forward @@ -1251,14 +1406,14 @@ if (typeof seekTime !== 'number') { seekTime = config.seekTime; } - _seek(player.media.currentTime + seekTime); + _seek(plyr.media.currentTime + seekTime); } // Seek to time // The input parameter can be an event or a number function _seek(input) { var targetTime = 0, - paused = player.media.paused; + paused = plyr.media.paused; // Explicit position if (typeof input === 'number') { @@ -1268,38 +1423,46 @@ else if (typeof input === 'object' && (input.type === 'input' || input.type === 'change')) { // It's the seek slider // Seek to the selected time - targetTime = ((input.target.value / input.target.max) * player.media.duration); + targetTime = ((input.target.value / input.target.max) * plyr.media.duration); } // Normalise targetTime if (targetTime < 0) { targetTime = 0; } - else if (targetTime > player.media.duration) { - targetTime = player.media.duration; + else if (targetTime > plyr.media.duration) { + targetTime = plyr.media.duration; } // Set the current time // Try/catch incase the media isn't set and we're calling seek() from source() and IE moans try { - player.media.currentTime = targetTime.toFixed(1); + plyr.media.currentTime = targetTime.toFixed(1); } catch(e) {} - // YouTube - if (player.type == 'youtube') { - player.embed.seekTo(targetTime); + // Trigger timeupdate for embed and restore pause state + if ('embed' in plyr) { + // YouTube + if (plyr.type === 'youtube') { + plyr.embed.seekTo(targetTime); + } - if (paused) { - _pause(); + // Vimeo + if (plyr.type === 'vimeo') { + plyr.embed.api('seekTo', targetTime); } // Trigger timeupdate - _triggerEvent(player.media, 'timeupdate'); + _triggerEvent(plyr.media, 'timeupdate'); + + if (paused) { + _pause(); + } } // Logging - _log('Seeking to ' + player.media.currentTime + ' seconds'); + _log('Seeking to ' + plyr.media.currentTime + ' seconds'); // Special handling for 'manual' captions _seekManualCaptions(targetTime); @@ -1307,8 +1470,8 @@ // Check playing state function _checkPlaying() { - _toggleClass(player.container, config.classes.playing, !player.media.paused); - _toggleClass(player.container, config.classes.stopped, player.media.paused); + _toggleClass(plyr.container, config.classes.playing, !plyr.media.paused); + _toggleClass(plyr.container, config.classes.stopped, plyr.media.paused); } // Toggle fullscreen @@ -1318,13 +1481,13 @@ // If it's a fullscreen change event, it's probably a native close if (event && event.type === fullscreen.fullScreenEventName) { - player.isFullscreen = fullscreen.isFullScreen(player.container); + plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); } // If there's native support, use it else if (nativeSupport) { // Request fullscreen - if (!fullscreen.isFullScreen(player.container)) { - fullscreen.requestFullScreen(player.container); + if (!fullscreen.isFullScreen(plyr.container)) { + fullscreen.requestFullScreen(plyr.container); } // Bail from fullscreen else { @@ -1332,14 +1495,14 @@ } // Check if we're actually full screen (it could fail) - player.isFullscreen = fullscreen.isFullScreen(player.container); + plyr.isFullscreen = fullscreen.isFullScreen(plyr.container); } else { // Otherwise, it's a simple toggle - player.isFullscreen = !player.isFullscreen; + plyr.isFullscreen = !plyr.isFullscreen; // Bind/unbind escape key - if (player.isFullscreen) { + if (plyr.isFullscreen) { _on(document, 'keyup', _handleEscapeFullscreen); document.body.style.overflow = 'hidden'; } @@ -1350,10 +1513,10 @@ } // Set class hook - _toggleClass(player.container, config.classes.fullscreen.active, player.isFullscreen); + _toggleClass(plyr.container, config.classes.fullscreen.active, plyr.isFullscreen); // Set button state - _toggleState(player.buttons.fullscreen, player.isFullscreen); + _toggleState(plyr.buttons.fullscreen, plyr.isFullscreen); // Toggle controls visibility based on mouse movement and location var hoverTimer, isMouseOver = false; @@ -1361,7 +1524,7 @@ // Show the player controls function _showControls() { // Set shown class - _toggleClass(player.container, config.classes.hover, true); + _toggleClass(plyr.container, config.classes.hover, true); // Clear timer every movement window.clearTimeout(hoverTimer); @@ -1369,7 +1532,7 @@ // If the mouse is not over the controls, set a timeout to hide them if (!isMouseOver) { hoverTimer = window.setTimeout(function() { - _toggleClass(player.container, config.classes.hover, false); + _toggleClass(plyr.container, config.classes.hover, false); }, 2000); } } @@ -1381,24 +1544,59 @@ if (config.fullscreen.hideControls) { // Hide on entering full screen - _toggleClass(player.controls, config.classes.hover, false); + _toggleClass(plyr.controls, config.classes.hover, false); // Keep an eye on the mouse location in relation to controls - _toggleHandler(player.controls, 'mouseenter mouseleave', _setMouseOver, player.isFullscreen); + _toggleHandler(plyr.controls, 'mouseenter mouseleave', _setMouseOver, plyr.isFullscreen); // Show the controls on mouse move - _toggleHandler(player.container, 'mousemove', _showControls, player.isFullscreen); + _toggleHandler(plyr.container, 'mousemove', _showControls, plyr.isFullscreen); } } // Bail from faux-fullscreen function _handleEscapeFullscreen(event) { // If it's a keypress and not escape, bail - if ((event.which || event.charCode || event.keyCode) === 27 && player.isFullscreen) { + if ((event.which || event.charCode || event.keyCode) === 27 && plyr.isFullscreen) { _toggleFullscreen(); } } + // Mute + function _toggleMute(muted) { + // If the method is called without parameter, toggle based on current value + if (typeof muted !== 'boolean') { + muted = !plyr.media.muted; + } + + // Set button state + _toggleState(plyr.buttons.mute, muted); + + // Set mute on the player + plyr.media.muted = muted; + + // YouTube + if (plyr.type === 'youtube') { + plyr.embed[plyr.media.muted ? 'mute' : 'unMute'](); + + // Trigger timeupdate + _triggerEvent(plyr.media, 'volumechange'); + } + + // Vimeo + if (plyr.type === 'vimeo') { + if (plyr.media.muted) { + plyr.embed.api('setVolume', 0); + } + else { + plyr.embed.api('setVolume', parseFloat(config.volume / 10)); + } + + // Trigger timeupdate + _triggerEvent(plyr.media, 'volumechange'); + } + } + // Set volume function _setVolume(volume) { // Use default if no value specified @@ -1421,52 +1619,40 @@ } // Set the player volume - player.media.volume = parseFloat(volume / 10); + plyr.media.volume = parseFloat(volume / 10); + + // Store in config + config.volume = volume; // YouTube - if (player.type == 'youtube') { - player.embed.setVolume(player.media.volume * 100); + if (plyr.type === 'youtube') { + plyr.embed.setVolume(plyr.media.volume * 100); + } - // Trigger timeupdate - _triggerEvent(player.media, 'volumechange'); + // Vimeo + if (plyr.type === 'vimeo') { + plyr.embed.api('setVolume', plyr.media.volume); + } + + // Trigger volumechange for embeds + if ('embed' in plyr) { + _triggerEvent(plyr.media, 'volumechange'); } // Toggle muted state - if (player.media.muted && volume > 0) { + if (plyr.media.muted && volume > 0) { _toggleMute(); } } - // Mute - function _toggleMute(muted) { - // If the method is called without parameter, toggle based on current value - if (typeof muted !== 'boolean') { - muted = !player.media.muted; - } - - // Set button state - _toggleState(player.buttons.mute, muted); - - // Set mute on the player - player.media.muted = muted; - - // YouTube - if (player.type === 'youtube') { - player.embed[player.media.muted ? 'mute' : 'unMute'](); - - // Trigger timeupdate - _triggerEvent(player.media, 'volumechange'); - } - } - // Update volume UI and storage function _updateVolume() { // Get the current volume - var volume = player.media.muted ? 0 : (player.media.volume * 10); + var volume = plyr.media.muted ? 0 : (plyr.media.volume * 10); // Update the <input type="range"> if present - if (player.supported.full && player.volume) { - player.volume.value = volume; + if (plyr.supported.full && plyr.volume) { + plyr.volume.value = volume; } // Store the volume in storage @@ -1475,31 +1661,34 @@ } // Toggle class if muted - _toggleClass(player.container, config.classes.muted, (volume === 0)); + _toggleClass(plyr.container, config.classes.muted, (volume === 0)); // Update checkbox for mute state - if (player.supported.full && player.buttons.mute) { - _toggleState(player.buttons.mute, (volume === 0)); + if (plyr.supported.full && plyr.buttons.mute) { + _toggleState(plyr.buttons.mute, (volume === 0)); } } // Toggle captions function _toggleCaptions(show) { // If there's no full support, or there's no caption toggle - if (!player.supported.full || !player.buttons.captions) { + if (!plyr.supported.full || !plyr.buttons.captions) { return; - } + } // If the method is called without parameter, toggle based on current value if (typeof show !== 'boolean') { - show = (player.container.className.indexOf(config.classes.captions.active) === -1); + show = (plyr.container.className.indexOf(config.classes.captions.active) === -1); } + // Set global + plyr.captionsEnabled = show; + // Toggle state - _toggleState(player.buttons.captions, show); + _toggleState(plyr.buttons.captions, plyr.captionsEnabled); // Add class hook - _toggleClass(player.container, config.classes.captions.active, show); + _toggleClass(plyr.container, config.classes.captions.active, plyr.captionsEnabled); } // Check if media is loading @@ -1507,18 +1696,18 @@ var loading = (event.type === 'waiting'); // Clear timer - clearTimeout(player.loadingTimer); + clearTimeout(plyr.loadingTimer); // Timer to prevent flicker when seeking - player.loadingTimer = setTimeout(function() { - _toggleClass(player.container, config.classes.loading, loading); + plyr.loadingTimer = setTimeout(function() { + _toggleClass(plyr.container, config.classes.loading, loading); }, (loading ? 250 : 0)); } // Update <progress> elements function _updateProgress(event) { - var progress = player.progress.played.bar, - text = player.progress.played.text, + var progress = plyr.progress.played.bar, + text = plyr.progress.played.text, value = 0; if (event) { @@ -1526,11 +1715,11 @@ // Video playing case 'timeupdate': case 'seeking': - value = _getPercentage(player.media.currentTime, player.media.duration); + value = _getPercentage(plyr.media.currentTime, plyr.media.duration); // Set seek range value only if it's a 'natural' time event - if (event.type == 'timeupdate' && player.buttons.seek) { - player.buttons.seek.value = value; + if (event.type == 'timeupdate' && plyr.buttons.seek) { + plyr.buttons.seek.value = value; } break; @@ -1545,14 +1734,14 @@ // Check buffer status case 'playing': case 'progress': - progress = player.progress.buffer.bar; - text = player.progress.buffer.text; + progress = plyr.progress.buffer.bar; + text = plyr.progress.buffer.text; value = (function() { - var buffered = player.media.buffered; + var buffered = plyr.media.buffered; // HTML5 if (buffered && buffered.length) { - return _getPercentage(buffered.end(0), player.media.duration); + return _getPercentage(buffered.end(0), plyr.media.duration); } // YouTube returns between 0 and 1 else if (typeof buffered === 'number') { @@ -1580,144 +1769,205 @@ return; } - player.secs = parseInt(time % 60); - player.mins = parseInt((time / 60) % 60); - player.hours = parseInt(((time / 60) / 60) % 60); + // Fallback to 0 + if (isNaN(time)) { + time = 0; + } + + plyr.secs = parseInt(time % 60); + plyr.mins = parseInt((time / 60) % 60); + plyr.hours = parseInt(((time / 60) / 60) % 60); // Do we need to display hours? - var displayHours = (parseInt(((player.media.duration / 60) / 60) % 60) > 0); + var displayHours = (parseInt(((plyr.media.duration / 60) / 60) % 60) > 0); // Ensure it's two digits. For example, 03 rather than 3. - player.secs = ('0' + player.secs).slice(-2); - player.mins = ('0' + player.mins).slice(-2); + plyr.secs = ('0' + plyr.secs).slice(-2); + plyr.mins = ('0' + plyr.mins).slice(-2); // Render - element.innerHTML = (displayHours ? player.hours + ':' : '') + player.mins + ':' + player.secs; + element.innerHTML = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs; } // Show the duration on metadataloaded function _displayDuration() { - var duration = player.media.duration || 0; + var duration = plyr.media.duration || 0; // If there's only one time display, display duration there - if (!player.duration && config.displayDuration && player.media.paused) { - _updateTimeDisplay(duration, player.currentTime); + if (!plyr.duration && config.displayDuration && plyr.media.paused) { + _updateTimeDisplay(duration, plyr.currentTime); } // If there's a duration element, update content - if (player.duration) { - _updateTimeDisplay(duration, player.duration); + if (plyr.duration) { + _updateTimeDisplay(duration, plyr.duration); } } // Handle time change event function _timeUpdate(event) { // Duration - _updateTimeDisplay(player.media.currentTime, player.currentTime); + _updateTimeDisplay(plyr.media.currentTime, plyr.currentTime); // Playing progress _updateProgress(event); } - // Remove <source> children and src attribute - function _removeSources() { - // Find child <source> elements - var sources = player.media.querySelectorAll('source'); - - // Remove each - for (var i = sources.length - 1; i >= 0; i--) { - _remove(sources[i]); + // Add elements to HTML5 media (source, tracks, etc) + function _insertChildElements(type, attributes) { + if (typeof attributes === 'string') { + _insertElement(type, plyr.media, { src: attributes }); } - - // Remove src attribute - player.media.removeAttribute('src'); - } - - // Inject a source - function _addSource(attributes) { - if (attributes.src) { - // Create a new <source> - var element = document.createElement('source'); - - // Set all passed attributes - _setAttributes(element, attributes); - - // Inject the new source - _prependChild(player.media, element); + else if (attributes.constructor === Array) { + for (var i = attributes.length - 1; i >= 0; i--) { + _insertElement(type, plyr.media, attributes[i]); + } } } // Update source // Sources are not checked for support so be careful - function _parseSource(sources) { - // YouTube - if (player.type === 'youtube' && typeof sources === 'string') { - // Destroy YouTube instance - player.embed.destroy(); + function _updateSource(source) { + if (typeof source === 'undefined') { + return; + } - // Re-setup YouTube - // We don't use loadVideoBy[x] here since it has issues - _setupYouTube(sources); + // Pause playback + _pause(); - // Update times - _timeUpdate(); + // Clean up YouTube stuff + if (plyr.type === 'youtube') { + // Destroy the embed instance + plyr.embed.destroy(); - // Bail - return; + // Clear timer + window.clearInterval(plyr.timer.buffering); + window.clearInterval(plyr.timer.playing); + } + else if (plyr.type === 'video') { + // Remove video wrapper + _remove(plyr.videoContainer); } + + // Remove the old media + _remove(plyr.media); - // Pause playback (webkit freaks out) - _pause(); + // Set the new type + if ('type' in source && source.type !== plyr.type) { + plyr.type = source.type; + } - // Restart - _seek(); + // Create new markup + switch(plyr.type) { + case 'video': + plyr.media = document.createElement('video'); + break; - // Remove current sources - _removeSources(); + case 'audio': + plyr.media = document.createElement('audio'); + break; - // If a single source is passed - // .source('path/to/video.mp4') - if (typeof sources === 'string') { - _addSource({ src: sources }); + case 'youtube': + case 'vimeo': + plyr.media = document.createElement('div'); + plyr.embedId = (typeof source.sources === 'string' ? source.sources : source.sources[0].src); + break; } - // An array of source objects - // Check if a source exists, use that or set the 'src' attribute? - // .source([{ src: 'path/to/video.mp4', type: 'video/mp4' },{ src: 'path/to/video.webm', type: 'video/webm' }]) - else if (sources.constructor === Array) { - for (var index in sources) { - _addSource(sources[index]); + // Inject the new element + _prependChild(plyr.container, plyr.media); + + // Set attributes for audio video + if (_inArray(config.types.html5, plyr.type)) { + if (config.crossorigin) { + plyr.media.setAttribute('crossorigin', ''); + } + if (config.autoplay) { + plyr.media.setAttribute('autoplay', ''); + } + if ('poster' in source) { + plyr.media.setAttribute('poster', source.poster); + } + if (config.loop) { + plyr.media.setAttribute('loop', ''); } } - if (player.supported.full) { - // Reset time display - _timeUpdate(); + // Classname reset + plyr.container.className = plyr.originalClassName; - // Update the UI - _checkPlaying(); - } + // Restore class hooks + _toggleClass(plyr.container, config.classes.fullscreen.active, plyr.isFullscreen); + _toggleClass(plyr.container, config.classes.captions.active, plyr.captionsEnabled); - // Re-load sources - player.media.load(); + // Autoplay the new source? + config.autoplay = (source.autoplay || config.autoplay); + + // Set media id for embeds + if (_inArray(config.types.embed, plyr.type)) { + plyr.embedId = source.sources; + } - // Play if autoplay attribute is present - if (player.media.getAttribute('autoplay') !== null || config.autoplay) { - _play(); + // Set new sources for html5 + if (_inArray(config.types.html5, plyr.type)) { + _insertChildElements('source', source.sources); } + + // Set up from scratch + _setupMedia(); + + // Trigger media updated + _mediaUpdated(); + + // HTML5 stuff + if (_inArray(config.types.html5, plyr.type)) { + // Set volume + _setVolume(); + _updateVolume(); + + // UI updates + if (plyr.supported.full) { + // Reset time display + _timeUpdate(); + + // Update the UI + _checkPlaying(); + } + + // Setup captions + if ('tracks' in source) { + _insertChildElements('track', source.tracks); + + // Captions + _setupCaptions(); + } + + // Load HTML5 sources + plyr.media.load(); + + // Play if autoplay attribute is present + if (config.autoplay) { + _play(); + } + } + + if ('title' in source) { + config.title = source.title; + _setupPlayAria(); + } } // Update poster function _updatePoster(source) { - if (player.type === 'video') { - player.media.setAttribute('poster', source); + if (plyr.type === 'video') { + plyr.media.setAttribute('poster', source); } } // Listen for events function _listeners() { // IE doesn't support input event, so we fallback to change - var inputEvent = (player.browser.name == 'IE' ? 'change' : 'input'); + var inputEvent = (plyr.browser.name == 'IE' ? 'change' : 'input'); // Detect tab focus function checkFocus() { @@ -1725,11 +1975,11 @@ if (!focused || focused == document.body) { focused = null; } - else { + else if (document.querySelector) { focused = document.querySelector(':focus'); } - for (var button in player.buttons) { - var element = player.buttons[button]; + for (var button in plyr.buttons) { + var element = plyr.buttons[button]; _toggleClass(element, 'tab-focus', (element === focused)); } @@ -1741,8 +1991,8 @@ checkFocus(); } }); - for (var button in player.buttons) { - var element = player.buttons[button]; + for (var button in plyr.buttons) { + var element = plyr.buttons[button]; _on(element, 'blur', function() { _toggleClass(element, 'tab-focus', false); @@ -1750,39 +2000,39 @@ } // Play - _on(player.buttons.play, 'click', function() { + _on(plyr.buttons.play, 'click', function() { _play(); - setTimeout(function() { player.buttons.pause.focus(); }, 100); + setTimeout(function() { plyr.buttons.pause.focus(); }, 100); }); // Pause - _on(player.buttons.pause, 'click', function() { + _on(plyr.buttons.pause, 'click', function() { _pause(); - setTimeout(function() { player.buttons.play.focus(); }, 100); + setTimeout(function() { plyr.buttons.play.focus(); }, 100); }); // Restart - _on(player.buttons.restart, 'click', _seek); + _on(plyr.buttons.restart, 'click', _seek); // Rewind - _on(player.buttons.rewind, 'click', _rewind); + _on(plyr.buttons.rewind, 'click', _rewind); // Fast forward - _on(player.buttons.forward, 'click', _forward); + _on(plyr.buttons.forward, 'click', _forward); // Seek - _on(player.buttons.seek, inputEvent, _seek); + _on(plyr.buttons.seek, inputEvent, _seek); // Set volume - _on(player.volume, inputEvent, function() { + _on(plyr.volume, inputEvent, function() { _setVolume(this.value); }); // Mute - _on(player.buttons.mute, 'click', _toggleMute); + _on(plyr.buttons.mute, 'click', _toggleMute); // Fullscreen - _on(player.buttons.fullscreen, 'click', _toggleFullscreen); + _on(plyr.buttons.fullscreen, 'click', _toggleFullscreen); // Handle user exiting fullscreen by escaping etc if (fullscreen.supportsFullScreen) { @@ -1790,22 +2040,22 @@ } // Time change on media - _on(player.media, 'timeupdate seeking', _timeUpdate); + _on(plyr.media, 'timeupdate seeking', _timeUpdate); // Update manual captions - _on(player.media, 'timeupdate', _seekManualCaptions); + _on(plyr.media, 'timeupdate', _seekManualCaptions); // Display duration - _on(player.media, 'loadedmetadata', _displayDuration); + _on(plyr.media, 'loadedmetadata', _displayDuration); // Captions - _on(player.buttons.captions, 'click', _toggleCaptions); + _on(plyr.buttons.captions, 'click', _toggleCaptions); // Handle the media finishing - _on(player.media, 'ended', function() { + _on(plyr.media, 'ended', function() { // Clear - if (player.type === 'video') { - player.captionsContainer.innerHTML = ''; + if (plyr.type === 'video') { + plyr.captionsContainer.innerHTML = ''; } // Reset UI @@ -1813,29 +2063,29 @@ }); // Check for buffer progress - _on(player.media, 'progress playing', _updateProgress); + _on(plyr.media, 'progress playing', _updateProgress); // Handle native mute - _on(player.media, 'volumechange', _updateVolume); + _on(plyr.media, 'volumechange', _updateVolume); // Handle native play/pause - _on(player.media, 'play pause', _checkPlaying); + _on(plyr.media, 'play pause', _checkPlaying); // Loading - _on(player.media, 'waiting canplay seeked', _checkLoading); + _on(plyr.media, 'waiting canplay seeked', _checkLoading); // Click video - if (player.type === 'video' && config.click) { - _on(player.videoContainer, 'click', function() { - if (player.media.paused) { - _triggerEvent(player.buttons.play, 'click'); + if (plyr.type === 'video' && config.click) { + _on(plyr.videoContainer, 'click', function() { + if (plyr.media.paused) { + _triggerEvent(plyr.buttons.play, 'click'); } - else if (player.media.ended) { + else if (plyr.media.ended) { _seek(); - _triggerEvent(player.buttons.play, 'click'); + _triggerEvent(plyr.buttons.play, 'click'); } else { - _triggerEvent(player.buttons.pause, 'click'); + _triggerEvent(plyr.buttons.pause, 'click'); } }); } @@ -1846,47 +2096,47 @@ // http://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory function _destroy() { // Bail if the element is not initialized - if (!player.init) { + if (!plyr.init) { return null; } // Reset container classname - player.container.setAttribute('class', config.selectors.container.replace('.', '')); + plyr.container.setAttribute('class', _getClassname(config.selectors.container)); // Remove init flag - player.init = false; + plyr.init = false; // Remove controls _remove(_getElement(config.selectors.controls)); // YouTube - if (player.type === 'youtube') { - player.embed.destroy(); + if (plyr.type === 'youtube') { + plyr.embed.destroy(); return; } // If video, we need to remove some more - if (player.type === 'video') { + if (plyr.type === 'video') { // Remove captions _remove(_getElement(config.selectors.captions)); // Remove video wrapper - _unwrap(player.videoContainer); + _unwrap(plyr.videoContainer); } // Restore native video controls - player.media.setAttribute('controls', ''); + plyr.media.setAttribute('controls', ''); // Clone the media element to remove listeners // http://stackoverflow.com/questions/19469881/javascript-remove-all-event-listeners-of-specific-type - var clone = player.media.cloneNode(true); - player.media.parentNode.replaceChild(clone, player.media); + var clone = plyr.media.cloneNode(true); + plyr.media.parentNode.replaceChild(clone, plyr.media); } // Setup a player function _init() { // Bail if the element is initialized - if (player.init) { + if (plyr.init) { return null; } @@ -1894,40 +2144,52 @@ fullscreen = _fullscreen(); // Sniff out the browser - player.browser = _browserSniff(); + plyr.browser = _browserSniff(); // Get the media element - player.media = player.container.querySelectorAll('audio, video, div')[0]; + plyr.media = plyr.container.querySelectorAll('audio, video, div')[0]; + + // Get original classname + plyr.originalClassName = plyr.container.className; - // Set media type - var tagName = player.media.tagName.toLowerCase(); + // Set media type based on tag or data attribute + // Supported: video, audio, vimeo, youtube + var tagName = plyr.media.tagName.toLowerCase(); if (tagName === 'div') { - player.type = player.media.getAttribute('data-type'); + plyr.type = plyr.media.getAttribute('data-type'); + plyr.embedId = plyr.media.getAttribute('data-video-id'); + + // Clean up + plyr.media.removeAttribute('data-type'); + plyr.media.removeAttribute('data-video-id'); } else { - player.type = tagName; + plyr.type = tagName; + config.crossorigin = (plyr.media.getAttribute('crossorigin') !== null); + config.autoplay = (config.autoplay || (plyr.media.getAttribute('autoplay') !== null)); + config.loop = (config.loop || (plyr.media.getAttribute('loop') !== null)); } // Check for full support - player.supported = api.supported(player.type); + plyr.supported = api.supported(plyr.type); // If no native support, bail - if (!player.supported.basic) { + if (!plyr.supported.basic) { return false; } // Debug info - _log(player.browser.name + ' ' + player.browser.version); + _log(plyr.browser.name + ' ' + plyr.browser.version); // Setup media _setupMedia(); // Setup interface - if (player.type == 'video' || player.type == 'audio') { + if (plyr.type == 'video' || plyr.type == 'audio') { // Bail if no support - if (!player.supported.full) { + if (!plyr.supported.full) { // Successful setup - player.init = true; + plyr.init = true; // Don't inject controls if no full support return; @@ -1946,7 +2208,7 @@ } // Successful setup - player.init = true; + plyr.init = true; } function _setupInterface() { @@ -1961,10 +2223,15 @@ // Captions _setupCaptions(); + // Media updated + _mediaUpdated(); + // Set volume _setVolume(); _updateVolume(); + } + function _mediaUpdated() { // Setup fullscreen _setupFullscreen(); @@ -1976,27 +2243,27 @@ _init(); // If init failed, return an empty object - if (!player.init) { + if (!plyr.init) { return {}; } return { - media: player.media, + media: plyr.media, play: _play, pause: _pause, restart: _seek, rewind: _rewind, forward: _forward, seek: _seek, - source: _parseSource, + source: _updateSource, poster: _updatePoster, setVolume: _setVolume, togglePlay: _togglePlay, toggleMute: _toggleMute, toggleCaptions: _toggleCaptions, toggleFullscreen: _toggleFullscreen, - isFullscreen: function() { return player.isFullscreen || false; }, - support: function(mimeType) { return _supportMime(player, mimeType); }, + isFullscreen: function() { return plyr.isFullscreen || false; }, + support: function(mimeType) { return _supportMime(plyr, mimeType); }, destroy: _destroy, restore: _init }; @@ -2022,6 +2289,7 @@ full = (basic && !oldIE); break; + case 'vimeo': case 'youtube': basic = true; full = (!oldIE && !iPhone); @@ -2039,7 +2307,30 @@ }; // Expose setup function - api.setup = function(options) { + api.setup = function(elements, options) { + // Get the players + var instances = []; + + // Select the elements + // Assume elements is a NodeList by default + if (typeof elements === 'string') { + elements = document.querySelectorAll(elements); + } + // Single HTMLElement passed + else if (elements instanceof HTMLElement) { + elements = [elements]; + } + // No selector passed, possibly options as first argument + else if (!(elements instanceof NodeList) && typeof elements !== 'string') { + // If options are the first argument + if (typeof options === 'undefined' && typeof elements === 'object') { + options = elements; + } + + // Use default selector + elements = document.querySelectorAll(defaults.selectors.container); + } + // Extend the default options with user specified config = _extend(defaults, options); @@ -2049,10 +2340,6 @@ return false; } - // Get the players - var elements = document.querySelectorAll(config.selectors.container), - players = []; - // Create a player instance for each element for (var i = elements.length - 1; i >= 0; i--) { // Get the current element @@ -2073,10 +2360,10 @@ } // Add to return array even if it's already setup - players.push(element.plyr); + instances.push(element.plyr); } - return players; + return instances; }; -}(this.plyr = this.plyr || {}));
\ No newline at end of file +}(this.plyr = this.plyr || {})); diff --git a/src/less/plyr.less b/src/less/plyr.less index a008fd21..c2411ea9 100644 --- a/src/less/plyr.less +++ b/src/less/plyr.less @@ -32,16 +32,18 @@ // Tooltips @tooltip-bg: @controls-bg; -@tooltip-border-color: @off-white; +@tooltip-border-color: fade(@gray-dark, 10%); +@tooltip-border-width: 1px; +@tooltip-shadow: 0 0 5px @tooltip-border-color, 0 0 0 @tooltip-border-width @tooltip-border-color; @tooltip-color: @control-color; @tooltip-padding: @control-spacing; -@tooltip-arrow-size: 5px; +@tooltip-arrow-size: 6px; @tooltip-radius: 3px; // Progress -@progress-bg: rgba(red(@gray), green(@gray), blue(@gray), .2); +@progress-bg: fade(@gray, 20%); @progress-playing-bg: @blue; -@progress-buffered-bg: rgba(red(@gray), green(@gray), blue(@gray), .25); +@progress-buffered-bg: fade(@gray, 25%); @progress-loading-size: 40px; @progress-loading-bg: rgba(0,0,0, .15); @@ -59,14 +61,12 @@ // Animation // --------------------------------------- - @keyframes progress { to { background-position: @progress-loading-size 0; } } // Mixins // ------------------------------- - // Contrast .contrast-control-color(@color: "") when (lightness(@color) >= 65%) { @control-color: @gray-light; @@ -146,7 +146,7 @@ // Styles // ------------------------------- // Base -.player { +.plyr { position: relative; max-width: 100%; min-width: 290px; @@ -175,6 +175,8 @@ &-video-embed { padding-bottom: 56.25%; /* 16:9 */ height: 0; + overflow: hidden; + background: #000; iframe { position: absolute; @@ -183,6 +185,14 @@ width: 100%; height: 100%; border: 0; + user-select: none; + } + + // Vimeo hack + > div { + position: relative; + padding-bottom: 200%; + transform: translateY(-35.95%); } } @@ -219,7 +229,7 @@ font-size: @font-size-captions-large; } - // Player controls + // Playback controls &-controls { .clearfix(); .font-smoothing(); @@ -286,8 +296,8 @@ display: none; } - // Player time - .player-time { + // plyr time + .plyr-time { display: inline-block; vertical-align: middle; margin-left: @control-spacing; @@ -298,7 +308,7 @@ } // Media duration hidden on small screens - .player-time + .player-time { + .plyr-time + .plyr-time { display: none; @media (min-width: @bp-control-split) { @@ -323,43 +333,56 @@ opacity: 0; background: @tooltip-bg; - border: 1px solid @tooltip-border-color; + box-shadow: @tooltip-shadow; border-radius: @tooltip-radius; color: @tooltip-color; font-size: @font-size-small; line-height: 1.5; font-weight: 600; - transform: translate(-50%, (@tooltip-padding * 3)) scale(0); + transform: translate(-50%, (@tooltip-padding * 3)) scale(.8); transform-origin: 50% 100%; transition: transform .2s .1s ease, opacity .2s .1s ease; - // Arrow - &::after { + // Arrows + &::after, + &::before { content: ''; position: absolute; - z-index: 1; + width: 0; + height: 0; top: 100%; left: 50%; - display: block; - width: 10px; - height: 10px; - background: @tooltip-bg; - transform: translate(-50%, -50%) rotate(45deg) translateY(1px); - border: 1px solid @tooltip-border-color; - border-width: 0 1px 1px 0; + transform: translateX(-50%); } + // The border triangle + &::after { + @border-arrow-size: (@tooltip-arrow-size + (@tooltip-border-width * 1)); + bottom: -(@border-arrow-size + @tooltip-border-width); + border-right: @border-arrow-size solid transparent; + border-top: @border-arrow-size solid @tooltip-border-color; + border-left: @border-arrow-size solid transparent; + z-index: 1; + } + // The background triangle + &::before { + bottom: -@tooltip-arrow-size; + border-right: @tooltip-arrow-size solid transparent; + border-top: @tooltip-arrow-size solid @tooltip-bg; + border-left: @tooltip-arrow-size solid transparent; + z-index: 2; + } } - button:hover .player-tooltip, - button.tab-focus:focus .player-tooltip { + button:hover .plyr-tooltip, + button.tab-focus:focus .plyr-tooltip { opacity: 1; transform: translate(-50%, 0) scale(1); } - button:hover .player-tooltip { + button:hover .plyr-tooltip { z-index: 3; } - // Player progress + // Playback progress // <progress> element &-progress { position: absolute; @@ -458,7 +481,7 @@ } // Loading state - &.loading .player-progress-buffer { + &.loading .plyr-progress-buffer { animation: progress 1s linear infinite; background-size: @progress-loading-size @progress-loading-size; background-repeat: repeat-x; @@ -476,11 +499,11 @@ } // States - &-controls [data-player='pause'], - &.playing .player-controls [data-player='play'] { + &-controls [data-plyr='pause'], + &.playing .plyr-controls [data-plyr='play'] { display: none; } - &.playing .player-controls [data-player='pause'] { + &.playing .plyr-controls [data-plyr='pause'] { display: inline-block; } @@ -552,7 +575,7 @@ // It's not supported to change volume using JavaScript: // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html &.ios &-volume, - &.ios [data-player='mute'], + &.ios [data-plyr='mute'], &-audio.ios &-controls-right { display: none; } @@ -563,10 +586,10 @@ // Audio specific styles // Position the progress within the container - &-audio .player-controls { + &-audio .plyr-controls { padding-top: (@control-spacing * 2); } - &-audio .player-progress { + &-audio .plyr-progress { bottom: auto; top: 0; background: @off-white; @@ -588,11 +611,11 @@ video { height: 100%; } - .player-video-wrapper { + .plyr-video-wrapper { height: 100%; width: 100%; } - .player-controls { + .plyr-controls { position: absolute; bottom: 0; left: 0; @@ -601,22 +624,22 @@ // Hide controls when playing in full screen &.fullscreen-hide-controls.playing { - .player-controls { + .plyr-controls { transform: translateY(100%) translateY(@control-spacing / 2); transition: transform .3s .2s ease; } - &.player-hover .player-controls { + &.plyr-hover .plyr-controls { transform: translateY(0); } - .player-captions { + .plyr-captions { bottom: (@control-spacing / 2); transition: bottom .3s .2s ease; } } // Captions - .player-captions, - &.fullscreen-hide-controls.playing.player-hover .player-captions { + .plyr-captions, + &.fullscreen-hide-controls.playing.plyr-hover .plyr-captions { top: auto; bottom: 90px; @@ -628,8 +651,8 @@ // Change icons on state change &.fullscreen-active .icon-exit-fullscreen, - &.muted .player-controls .icon-muted, - &.captions-active .player-controls .icon-captions-on { + &.muted .plyr-controls .icon-muted, + &.captions-active .plyr-controls .icon-captions-on { display: block; & + svg { @@ -638,12 +661,12 @@ } // Some options are hidden by default - [data-player='captions'], - [data-player='fullscreen'] { + [data-plyr='captions'], + [data-plyr='fullscreen'] { display: none; } - &.captions-enabled [data-player='captions'], - &.fullscreen-enabled [data-player='fullscreen'] { + &.captions-enabled [data-plyr='captions'], + &.fullscreen-enabled [data-plyr='fullscreen'] { display: inline-block; } }
\ No newline at end of file diff --git a/src/sass/plyr.scss b/src/sass/plyr.scss index de386cd8..7cefca3a 100644 --- a/src/sass/plyr.scss +++ b/src/sass/plyr.scss @@ -44,15 +44,18 @@ $control-color-hover: null !default; // Tooltips $tooltip-bg: $controls-bg !default; +$tooltip-border-color: transparentize(@gray-dark, .1) !default; +$tooltip-border-width: 1px; +$tooltip-shadow: 0 0 5px $tooltip-border-color, 0 0 0 $tooltip-border-width $tooltip-border-color; $tooltip-color: $control-color !default; $tooltip-padding: $control-spacing !default; -$tooltip-arrow-size: 5px !default; +$tooltip-arrow-size: 6px !default; $tooltip-radius: 3px !default; // Progress -$progress-bg: rgba(red($gray), green($gray), blue($gray), .2) !default; +$progress-bg: transparentize($gray, .2) !default; $progress-playing-bg: $blue !default; -$progress-buffered-bg: rgba(red($gray), green($gray), blue($gray), .25) !default; +$progress-buffered-bg: transparentize($gray, .25) !default; $progress-loading-size: 40px !default; $progress-loading-bg: rgba(0,0,0, .15) !default; @@ -70,7 +73,6 @@ $bp-captions-large: 768px !default; // When captions jump to the larger // Animation // --------------------------------------- - @keyframes progress { to { background-position: $progress-loading-size 0; } } @@ -149,7 +151,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger // Styles // ------------------------------- // Base -.player { +.plyr { position: relative; max-width: 100%; min-width: 290px; @@ -178,6 +180,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger &-video-embed { padding-bottom: 56.25%; /* 16:9 */ height: 0; + overflow: hidden; + background: #000; iframe { position: absolute; @@ -187,6 +191,13 @@ $bp-captions-large: 768px !default; // When captions jump to the larger height: 100%; border: 0; } + + // Vimeo hack + > div { + position: relative; + padding-bottom: 200%; + transform: translateY(-35.95%); + } } // Captions @@ -222,7 +233,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger font-size: $font-size-captions-large; } - // Player controls + // Playback controls &-controls { @include clearfix(); @include font-smoothing(); @@ -290,7 +301,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger } // Time display - .player-time { + .plyr-time { display: inline-block; vertical-align: middle; margin-left: $control-spacing; @@ -301,7 +312,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger } // Media duration hidden on small screens - .player-time + .player-time { + .plyr-time + .plyr-time { display: none; @media (min-width: $bp-control-split) { @@ -326,41 +337,56 @@ $bp-captions-large: 768px !default; // When captions jump to the larger opacity: 0; background: $tooltip-bg; + box-shadow: $tooltip-shadow; border-radius: $tooltip-radius; color: $tooltip-color; font-size: $font-size-small; line-height: 1.5; font-weight: 600; - transform: translate(-50%, ($tooltip-padding * 3)) scale(0); + transform: translate(-50%, ($tooltip-padding * 3)) scale(.8); transform-origin: 50% 100%; transition: transform .2s .1s ease, opacity .2s .1s ease; - &::after { + // Arrows + &::after, + &::before { content: ''; - display: block; position: absolute; - left: 50%; - bottom: -$tooltip-arrow-size; - margin-left: -$tooltip-arrow-size; width: 0; height: 0; - transition: inherit; - border-style: solid; - border-width: $tooltip-arrow-size $tooltip-arrow-size 0 $tooltip-arrow-size; - border-color: $controls-bg transparent transparent; + top: 100%; + left: 50%; + transform: translateX(-50%); + } + // The border triangle + &::after { + $border-arrow-size: ($tooltip-arrow-size + ($tooltip-border-width * 1)); + bottom: -($border-arrow-size + $tooltip-border-width); + border-right: $border-arrow-size solid transparent; + border-top: $border-arrow-size solid $tooltip-border-color; + border-left: $border-arrow-size solid transparent; + z-index: 1; + } + // The background triangle + &::before { + bottom: -$tooltip-arrow-size; + border-right: $tooltip-arrow-size solid transparent; + border-top: $tooltip-arrow-size solid $tooltip-bg; + border-left: $tooltip-arrow-size solid transparent; + z-index: 2; } } - button:hover .player-tooltip, - button:focus .player-tooltip { + button:hover .plyr-tooltip, + button:focus .plyr-tooltip { opacity: 1; transform: translate(-50%, 0) scale(1); } - button:hover .player-tooltip { + button:hover .plyr-tooltip { z-index: 3; } - // Player progress + // Playback progress // <progress> element &-progress { position: absolute; @@ -459,7 +485,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger } // Loading state - &.loading .player-progress-buffer { + &.loading .plyr-progress-buffer { animation: progress 1s linear infinite; background-size: $progress-loading-size $progress-loading-size; background-repeat: repeat-x; @@ -477,11 +503,11 @@ $bp-captions-large: 768px !default; // When captions jump to the larger } // States - &-controls [data-player='pause'], - &.playing .player-controls [data-player='play'] { + &-controls [data-plyr='pause'], + &.playing .plyr-controls [data-plyr='play'] { display: none; } - &.playing .player-controls [data-player='pause'] { + &.playing .plyr-controls [data-plyr='pause'] { display: inline-block; } @@ -553,7 +579,7 @@ $bp-captions-large: 768px !default; // When captions jump to the larger // It's not supported to change volume using JavaScript: // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html &.ios &-volume, - &.ios [data-player='mute'], + &.ios [data-plyr='mute'], &-audio.ios &-controls-right { display: none; } @@ -564,10 +590,10 @@ $bp-captions-large: 768px !default; // When captions jump to the larger // Audio specific styles // Position the progress within the container - &-audio .player-controls { + &-audio .plyr-controls { padding-top: ($control-spacing * 2); } - &-audio .player-progress { + &-audio .plyr-progress { bottom: auto; top: 0; background: $off-white; @@ -589,11 +615,11 @@ $bp-captions-large: 768px !default; // When captions jump to the larger video { height: 100%; } - .player-video-wrapper { + .plyr-video-wrapper { height: 100%; width: 100%; } - .player-controls { + .plyr-controls { position: absolute; bottom: 0; left: 0; @@ -602,22 +628,22 @@ $bp-captions-large: 768px !default; // When captions jump to the larger // Hide controls when playing in full screen &.fullscreen-hide-controls.playing { - .player-controls { + .plyr-controls { transform: translateY(100%) translateY($control-spacing / 2); transition: transform .3s .2s ease; } - &.player-hover .player-controls { + &.plyr-hover .plyr-controls { transform: translateY(0); } - .player-captions { + .plyr-captions { bottom: ($control-spacing / 2); transition: bottom .3s .2s ease; } } // Captions - .player-captions, - &.fullscreen-hide-controls.playing.player-hover .player-captions { + .plyr-captions, + &.fullscreen-hide-controls.playing.plyr-hover .plyr-captions { top: auto; bottom: 90px; @@ -629,8 +655,8 @@ $bp-captions-large: 768px !default; // When captions jump to the larger // Change icons on state change &.fullscreen-active .icon-exit-fullscreen, - &.muted .player-controls .icon-muted, - &.captions-active .player-controls .icon-captions-on { + &.muted .plyr-controls .icon-muted, + &.captions-active .plyr-controls .icon-captions-on { display: block; & + svg { @@ -639,12 +665,12 @@ $bp-captions-large: 768px !default; // When captions jump to the larger } // Some options are hidden by default - [data-player='captions'], - [data-player='fullscreen'] { + [data-plyr='captions'], + [data-plyr='fullscreen'] { display: none; } - &.captions-enabled [data-player='captions'], - &.fullscreen-enabled [data-player='fullscreen'] { + &.captions-enabled [data-plyr='captions'], + &.fullscreen-enabled [data-plyr='fullscreen'] { display: inline-block; } } diff --git a/src/sprite/icon-captions-off.svg b/src/sprite/icon-captions-off.svg index c9bd5b3c..d9c2c444 100644 --- a/src/sprite/icon-captions-off.svg +++ b/src/sprite/icon-captions-off.svg @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> - <path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z" id="Shape" sketch:type="MSShapeGroup"></path> + <title>Captions Off</title> + <g> + <path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z"></path> </g> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-captions-on.svg b/src/sprite/icon-captions-on.svg index 1ed58de9..9053a31c 100644 --- a/src/sprite/icon-captions-on.svg +++ b/src/sprite/icon-captions-on.svg @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> - <path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z" id="Shape" sketch:type="MSShapeGroup"></path> - <rect id="Rectangle-1" sketch:type="MSShapeGroup" x="3" y="11" width="3" height="2"></rect> - <rect id="Rectangle-3" sketch:type="MSShapeGroup" x="12" y="11" width="3" height="2"></rect> - <rect id="Rectangle-2" sketch:type="MSShapeGroup" x="7" y="11" width="4" height="2"></rect> +<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Captions On</title> + <g> + <path d="M1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L1,2 Z M2,14 L2,4 L16,4 L16,14 L2,14 L2,14 Z"></path> + <rect x="3" y="11" width="3" height="2"></rect> + <rect x="12" y="11" width="3" height="2"></rect> + <rect x="7" y="11" width="4" height="2"></rect> </g> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-enter-fullscreen.svg b/src/sprite/icon-enter-fullscreen.svg index 13434bb1..200e44e0 100644 --- a/src/sprite/icon-enter-fullscreen.svg +++ b/src/sprite/icon-enter-fullscreen.svg @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> - <g id="expand" sketch:type="MSLayerGroup" transform="translate(-1.000000, -1.000000)"> - <path d="M7.00325,17.01 L7.00325,13.377 L8.29625,14.694 C8.68825,15.082 9.32125,15.082 9.71325,14.694 C10.10525,14.306 10.10425,13.678 9.71325,13.291 L6.74625,10.291 C6.55825,10.105 6.30425,10 6.03725,10 C6.02625,10 6.01425,10 6.00325,10.001 C5.99225,10.002 5.98025,10 5.96925,10 C5.70325,10 5.44825,10.105 5.26025,10.291 L2.29325,13.291 C1.90225,13.679 1.90225,14.307 2.29325,14.694 C2.68425,15.081 3.31825,15.082 3.71025,14.694 L5.00425,13.377 L5.00425,17.01 C5.00425,17.557 5.44725,18 5.99425,18 L6.01225,18 C6.55925,18 7.00225,17.557 7.00225,17.01 L7.00325,17.01 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(6.003438, 14.000000) rotate(-135.000000) translate(-6.003438, -14.000000) "></path> - <path d="M15.0066876,5.377 L16.2996876,6.694 C16.6916876,7.082 17.3246876,7.082 17.7166876,6.694 C18.1086876,6.306 18.1076876,5.678 17.7166876,5.291 L14.7496876,2.291 C14.5616876,2.105 14.3076876,2 14.0406876,2 C14.0296876,2 14.0176876,2 14.0066876,2.001 C13.9956876,2.002 13.9836876,2 13.9726876,2 C13.7066876,2 13.4516876,2.105 13.2636876,2.291 L10.2966876,5.291 C9.90568756,5.679 9.90568756,6.307 10.2966876,6.694 C10.6876876,7.081 11.3216876,7.082 11.7136876,6.694 L13.0076876,5.377 L13.0076876,9.01 C13.0076876,9.557 13.4506876,10 13.9976876,10 C14.5626876,10 15.0056876,9.557 15.0056876,9.01 L15.0066876,5.377 Z" id="Shape-2" sketch:type="MSShapeGroup" transform="translate(14.006875, 6.000000) rotate(45.000000) translate(-14.006875, -6.000000) "></path> +<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Enter Fullscreen</title> + <g> + <g transform="translate(9.000000, 9.000000) rotate(-180.000000) translate(-9.000000, -9.000000) translate(0.000000, 2.000000)"> + <path d="M7.69999981,6.30000001 C7.00064659,5.62264405 6.3,6.3 6.3,6.3 L2,10.6 L2,6 L0,6 L0,13 C0,13.6 0.4,14 1,14 L8,14 L8,12 L3.4,12 L7.7,7.7 C7.7,7.7 8.39935303,6.97735597 7.69999981,6.30000001 Z"></path> + <path d="M11,14 L11,12 L16,12 L16,2 L2,2 L2,3 L0,3 L0,1 C0,0.4 0.4,0 1,0 L17,0 C17.6,0 18,0.4 18,1 L18,13 C18,13.6 17.6,14 17,14 L11,14 Z"></path> </g> </g> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-exit-fullscreen.svg b/src/sprite/icon-exit-fullscreen.svg index ff4269bc..3c6f31e7 100644 --- a/src/sprite/icon-exit-fullscreen.svg +++ b/src/sprite/icon-exit-fullscreen.svg @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1"> - <g id="collapse" sketch:type="MSLayerGroup" transform="translate(-1.000000, -1.000000)"> - <path d="M15.00325,9.01 L15.00325,5.377 L16.29625,6.694 C16.68825,7.082 17.32125,7.082 17.71325,6.694 C18.10525,6.306 18.10425,5.678 17.71325,5.291 L14.74625,2.291 C14.55825,2.105 14.30425,2 14.03725,2 C14.02625,2 14.01425,2 14.00325,2.001 C13.99225,2.002 13.98025,2 13.96925,2 C13.70325,2 13.44825,2.105 13.26025,2.291 L10.29325,5.291 C9.90225,5.679 9.90225,6.307 10.29325,6.694 C10.68425,7.081 11.31825,7.082 11.71025,6.694 L13.00425,5.377 L13.00425,9.01 C13.00425,9.557 13.44725,10 13.99425,10 L14.01225,10 C14.55925,10 15.00225,9.557 15.00225,9.01 L15.00325,9.01 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(14.003438, 6.000000) rotate(-135.000000) translate(-14.003438, -6.000000) "></path> - <path d="M7.00668756,13.377 L8.29968756,14.694 C8.69168756,15.082 9.32468756,15.082 9.71668756,14.694 C10.1086876,14.306 10.1076876,13.678 9.71668756,13.291 L6.74968756,10.291 C6.56168756,10.105 6.30768756,10 6.04068756,10 C6.02968756,10 6.01768756,10 6.00668756,10.001 C5.99568756,10.002 5.98368756,10 5.97268756,10 C5.70668756,10 5.45168756,10.105 5.26368756,10.291 L2.29668756,13.291 C1.90568756,13.679 1.90568756,14.307 2.29668756,14.694 C2.68768756,15.081 3.32168756,15.082 3.71368756,14.694 L5.00768756,13.377 L5.00768756,17.01 C5.00768756,17.557 5.45068756,18 5.99768756,18 C6.56268756,18 7.00568756,17.557 7.00568756,17.01 L7.00668756,13.377 Z" id="Shape-2" sketch:type="MSShapeGroup" transform="translate(6.006875, 14.000000) rotate(45.000000) translate(-6.006875, -14.000000) "></path> +<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Exit Fullscreen</title> + <g> + <g transform="translate(0.000000, 2.000000)"> + <path d="M7.69999981,6.30000001 C7.00064659,5.62264405 6.3,6.3 6.3,6.3 L2,10.6 L2,6 L0,6 L0,13 C0,13.6 0.4,14 1,14 L8,14 L8,12 L3.4,12 L7.7,7.7 C7.7,7.7 8.39935303,6.97735597 7.69999981,6.30000001 Z"></path> + <path d="M11,14 L11,12 L16,12 L16,2 L2,2 L2,3 L0,3 L0,1 C0,0.4 0.4,0 1,0 L17,0 C17.6,0 18,0.4 18,1 L18,13 C18,13.6 17.6,14 17,14 L11,14 Z"></path> </g> </g> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-fast-forward.svg b/src/sprite/icon-fast-forward.svg index 05b23faa..71d5d138 100755 --- a/src/sprite/icon-fast-forward.svg +++ b/src/sprite/icon-fast-forward.svg @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<path d="M17.569 8.246l-10.569-6.246c-0.552 0-1 0.448-1 1v1.954l-5-2.954c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l5-2.955v1.955c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754zM6 10.722l-4 2.364v-8.172l4 2.364v3.444zM8 13.086v-8.172l6.915 4.086-6.915 4.086z"></path> + <title>Fast Forward</title> + <path d="M17.569 8.246l-10.569-6.246c-0.552 0-1 0.448-1 1v1.954l-5-2.954c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l5-2.955v1.955c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754zM6 10.722l-4 2.364v-8.172l4 2.364v3.444zM8 13.086v-8.172l6.915 4.086-6.915 4.086z"></path> </svg> diff --git a/src/sprite/icon-muted.svg b/src/sprite/icon-muted.svg index 532c513d..6d017d02 100644 --- a/src/sprite/icon-muted.svg +++ b/src/sprite/icon-muted.svg @@ -1,10 +1,9 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> - <g id="sound" sketch:type="MSLayerGroup" transform="translate(0.000000, 2.000000)"> - <path d="M9.214,0 C9.103,0 8.989,0.032 8.88,0.101 L4.832,2.911 C4.749,2.969 4.65,3 4.549,3 L0.996,3 C0.446,3 1.33226763e-15,3.448 1.33226763e-15,4 L1.33226763e-15,10 C1.33226763e-15,10.552 0.446,11 0.996,11 L4.549,11 C4.651,11 4.749,11.031 4.832,11.089 L8.88,13.899 C8.989,13.968 9.103,14 9.214,14 C9.606,14 9.961,13.6 9.961,13.051 L9.961,0.95 C9.961,0.4 9.606,0.001 9.214,0.001 L9.214,0 Z M7.969,10.834 L5.582,9.177 C5.416,9.062 5.218,8.999 5.016,8.999 L2.491,8.999 C2.216,8.999 1.993,8.775 1.993,8.499 L1.993,5.499 C1.993,5.223 2.216,4.999 2.491,4.999 L5.016,4.999 C5.218,4.999 5.416,4.937 5.582,4.821 L7.969,3.164 L7.969,10.833 L7.969,10.834 Z" id="Shape" sketch:type="MSShapeGroup"></path> - <path d="M14.934,6.799 C14.848,5.051 13.42,3.808 12.427,3.15 C11.957,2.838 11.333,3.028 11.102,3.558 L11.064,3.644 C10.876,4.075 11.019,4.583 11.4,4.838 C12.106,5.311 12.986,6.085 13.024,6.903 C13.056,7.579 12.471,8.371 11.361,9.173 C10.963,9.461 10.832,10.012 11.076,10.448 L11.118,10.523 C11.384,10.998 11.984,11.147 12.418,10.835 C14.158,9.584 15.004,8.229 14.934,6.798 L14.934,6.799 Z" id="Shape" sketch:type="MSShapeGroup"></path> - <path d="M17.934,6.799 C17.848,5.051 16.42,3.808 15.427,3.15 C14.957,2.838 14.333,3.028 14.102,3.558 L14.064,3.644 C13.876,4.075 14.019,4.583 14.4,4.838 C15.106,5.311 15.986,6.085 16.024,6.903 C16.056,7.579 15.471,8.371 14.361,9.173 C13.963,9.461 13.832,10.012 14.076,10.448 L14.118,10.523 C14.384,10.998 14.984,11.147 15.418,10.835 C17.158,9.584 18.004,8.229 17.934,6.798 L17.934,6.799 Z" id="Shape-2" sketch:type="MSShapeGroup" transform="translate(15.945467, 6.999165) rotate(-180.000000) translate(-15.945467, -6.999165) "></path> - </g> +<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Muted</title> + <g transform="translate(0.000000, 2.000000)"> + <path d="M9.214,0 C9.103,0 8.989,0.032 8.88,0.101 L4.832,2.911 C4.749,2.969 4.65,3 4.549,3 L0.996,3 C0.446,3 1.33226763e-15,3.448 1.33226763e-15,4 L1.33226763e-15,10 C1.33226763e-15,10.552 0.446,11 0.996,11 L4.549,11 C4.651,11 4.749,11.031 4.832,11.089 L8.88,13.899 C8.989,13.968 9.103,14 9.214,14 C9.606,14 9.961,13.6 9.961,13.051 L9.961,0.95 C9.961,0.4 9.606,0.001 9.214,0.001 L9.214,0 Z M7.969,10.834 L5.582,9.177 C5.416,9.062 5.218,8.999 5.016,8.999 L2.491,8.999 C2.216,8.999 1.993,8.775 1.993,8.499 L1.993,5.499 C1.993,5.223 2.216,4.999 2.491,4.999 L5.016,4.999 C5.218,4.999 5.416,4.937 5.582,4.821 L7.969,3.164 L7.969,10.833 L7.969,10.834 Z"></path> + <path d="M14.934,6.799 C14.848,5.051 13.42,3.808 12.427,3.15 C11.957,2.838 11.333,3.028 11.102,3.558 L11.064,3.644 C10.876,4.075 11.019,4.583 11.4,4.838 C12.106,5.311 12.986,6.085 13.024,6.903 C13.056,7.579 12.471,8.371 11.361,9.173 C10.963,9.461 10.832,10.012 11.076,10.448 L11.118,10.523 C11.384,10.998 11.984,11.147 12.418,10.835 C14.158,9.584 15.004,8.229 14.934,6.798 L14.934,6.799 Z"></path> + <path d="M17.934,6.799 C17.848,5.051 16.42,3.808 15.427,3.15 C14.957,2.838 14.333,3.028 14.102,3.558 L14.064,3.644 C13.876,4.075 14.019,4.583 14.4,4.838 C15.106,5.311 15.986,6.085 16.024,6.903 C16.056,7.579 15.471,8.371 14.361,9.173 C13.963,9.461 13.832,10.012 14.076,10.448 L14.118,10.523 C14.384,10.998 14.984,11.147 15.418,10.835 C17.158,9.584 18.004,8.229 17.934,6.798 L17.934,6.799 Z" transform="translate(15.945467, 6.999165) rotate(-180.000000) translate(-15.945467, -6.999165) "></path> </g> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-pause.svg b/src/sprite/icon-pause.svg index ee25646d..b4ba82e2 100644 --- a/src/sprite/icon-pause.svg +++ b/src/sprite/icon-pause.svg @@ -1,10 +1,8 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> - <g id="pause" sketch:type="MSLayerGroup" transform="translate(2.000000, 2.000000)"> - <path d="M0,2 L0,12 C5.24848613e-17,14 2,14 2,14 L4,14 C4,14 6,14 6,12 C6,11.786438 6,11.572876 6,11 L6,2 C6,3.17446247e-09 4,0 4,0 L2,0 C2,0 0,0 0,2 Z M2,2 L4,2 L4,12 L2,12 L2,2 Z" id="Path-1" sketch:type="MSShapeGroup"></path> - <path d="M8,2 L8,12 C8,14 10,14 10,14 L12,14 C12,14 14,14 14,12 C14,11.786438 14,11.572876 14,11 L14,2 C14,3.17446247e-09 12,0 12,0 L10,0 C10,0 8,0 8,2 Z M10,2 L12,2 L12,12 L10,12 L10,2 Z" id="Path-2" sketch:type="MSShapeGroup"></path> - </g> +<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Pause</title> + <g transform="translate(2.000000, 2.000000)"> + <path d="M0,2 L0,12 C5.24848613e-17,14 2,14 2,14 L4,14 C4,14 6,14 6,12 C6,11.786438 6,11.572876 6,11 L6,2 C6,3.17446247e-09 4,0 4,0 L2,0 C2,0 0,0 0,2 Z M2,2 L4,2 L4,12 L2,12 L2,2 Z"></path> + <path d="M8,2 L8,12 C8,14 10,14 10,14 L12,14 C12,14 14,14 14,12 C14,11.786438 14,11.572876 14,11 L14,2 C14,3.17446247e-09 12,0 12,0 L10,0 C10,0 8,0 8,2 Z M10,2 L12,2 L12,12 L10,12 L10,2 Z"></path> </g> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-play.svg b/src/sprite/icon-play.svg index f0057b32..f564b80f 100755 --- a/src/sprite/icon-play.svg +++ b/src/sprite/icon-play.svg @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<path d="M5 4.914l6.915 4.086-6.915 4.086v-8.172zM4 2c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754l-10.569-6.246z"></path> + <title>Play</title> + <path d="M5 4.914l6.915 4.086-6.915 4.086v-8.172zM4 2c-0.552 0-1 0.448-1 1v12c0 0.552 0.448 1 1 1l10.569-6.246c0.267-0.158 0.431-0.444 0.431-0.754s-0.164-0.597-0.431-0.754l-10.569-6.246z"></path> </svg> diff --git a/src/sprite/icon-restart.svg b/src/sprite/icon-restart.svg index 43645a5c..1e393763 100644 --- a/src/sprite/icon-restart.svg +++ b/src/sprite/icon-restart.svg @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> - <path d="M17,2 C16.448,2 16,2.448 16,3 L16,7.318 L7,2 C6.448,2 6,2.448 6,3 L6,4.954 L1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L6,13.045 L6,15 C6,15.552 6.448,16 7,16 L16,10.682 L16,15 C16,15.552 16.448,16 17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L17,2 Z M6,10.722 L2,13.086 L2,4.914 L6,7.278 L6,10.722 L6,10.722 Z M8,13.086 L8,4.914 L14.915,9 L8,13.086 L8,13.086 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(9.000000, 9.000000) scale(-1, 1) translate(-9.000000, -9.000000) "></path> - </g> +<svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>Restart</title> + <path d="M17,2 C16.448,2 16,2.448 16,3 L16,7.318 L7,2 C6.448,2 6,2.448 6,3 L6,4.954 L1,2 C0.448,2 0,2.448 0,3 L0,15 C0,15.552 0.448,16 1,16 L6,13.045 L6,15 C6,15.552 6.448,16 7,16 L16,10.682 L16,15 C16,15.552 16.448,16 17,16 C17.552,16 18,15.552 18,15 L18,3 C18,2.448 17.552,2 17,2 L17,2 Z M6,10.722 L2,13.086 L2,4.914 L6,7.278 L6,10.722 L6,10.722 Z M8,13.086 L8,4.914 L14.915,9 L8,13.086 L8,13.086 Z" transform="translate(9.000000, 9.000000) scale(-1, 1) translate(-9.000000, -9.000000) "></path> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-rewind.svg b/src/sprite/icon-rewind.svg index 5f122c86..b7beaa34 100644 --- a/src/sprite/icon-rewind.svg +++ b/src/sprite/icon-rewind.svg @@ -1,7 +1,5 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg viewBox="0 0 18 21" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"> - <defs></defs> - <g id="Page-1" stroke="none" stroke-width="1" sketch:type="MSPage"> - <path d="M17.569,9.246 L7,3 C6.448,3 6,3.448 6,4 L6,5.954 L1,3 C0.448,3 0,3.448 0,4 L0,16 C0,16.552 0.448,17 1,17 L6,14.045 L6,16 C6,16.552 6.448,17 7,17 L17.569,10.754 C17.836,10.596 18,10.31 18,10 C18,9.69 17.836,9.403 17.569,9.246 L17.569,9.246 Z M6,11.722 L2,14.086 L2,5.914 L6,8.278 L6,11.722 L6,11.722 Z M8,14.086 L8,5.914 L14.915,10 L8,14.086 L8,14.086 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(9.000000, 10.000000) rotate(-180.000000) translate(-9.000000, -10.000000) "></path> - </g> + <title>Rewind</title> + <path d="M17.569,9.246 L7,3 C6.448,3 6,3.448 6,4 L6,5.954 L1,3 C0.448,3 0,3.448 0,4 L0,16 C0,16.552 0.448,17 1,17 L6,14.045 L6,16 C6,16.552 6.448,17 7,17 L17.569,10.754 C17.836,10.596 18,10.31 18,10 C18,9.69 17.836,9.403 17.569,9.246 L17.569,9.246 Z M6,11.722 L2,14.086 L2,5.914 L6,8.278 L6,11.722 L6,11.722 Z M8,14.086 L8,5.914 L14.915,10 L8,14.086 L8,14.086 Z" transform="translate(9.000000, 10.000000) rotate(-180.000000) translate(-9.000000, -10.000000) "></path> </svg>
\ No newline at end of file diff --git a/src/sprite/icon-volume.svg b/src/sprite/icon-volume.svg index edcc8867..27d6d809 100755 --- a/src/sprite/icon-volume.svg +++ b/src/sprite/icon-volume.svg @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <svg viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<path d="M10.214 2c-0.111 0-0.225 0.032-0.334 0.101l-4.048 2.81c-0.083 0.058-0.182 0.089-0.283 0.089h-3.553c-0.55 0-0.996 0.448-0.996 1v6c0 0.552 0.446 1 0.996 1h3.553c0.102 0 0.2 0.031 0.283 0.089l4.048 2.81c0.109 0.069 0.223 0.101 0.334 0.101 0.392 0 0.747-0.4 0.747-0.949v-12.101c0-0.55-0.355-0.949-0.747-0.949zM8.969 12.834l-2.387-1.657c-0.166-0.115-0.364-0.178-0.566-0.178h-2.525c-0.275 0-0.498-0.224-0.498-0.5v-3c0-0.276 0.223-0.5 0.498-0.5h2.525c0.202 0 0.4-0.062 0.566-0.178l2.387-1.657v7.669z"></path> -<path d="M16.934 8.799c-0.086-1.748-1.514-2.991-2.507-3.649-0.47-0.312-1.094-0.122-1.325 0.408l-0.038 0.086c-0.188 0.431-0.045 0.939 0.336 1.194 0.706 0.473 1.586 1.247 1.624 2.065 0.032 0.676-0.553 1.468-1.663 2.27-0.398 0.288-0.529 0.839-0.285 1.275l0.042 0.075c0.266 0.475 0.866 0.624 1.3 0.312 1.74-1.251 2.586-2.606 2.516-4.037z"></path> + <title>Volume</title> + <path d="M10.214 2c-0.111 0-0.225 0.032-0.334 0.101l-4.048 2.81c-0.083 0.058-0.182 0.089-0.283 0.089h-3.553c-0.55 0-0.996 0.448-0.996 1v6c0 0.552 0.446 1 0.996 1h3.553c0.102 0 0.2 0.031 0.283 0.089l4.048 2.81c0.109 0.069 0.223 0.101 0.334 0.101 0.392 0 0.747-0.4 0.747-0.949v-12.101c0-0.55-0.355-0.949-0.747-0.949zM8.969 12.834l-2.387-1.657c-0.166-0.115-0.364-0.178-0.566-0.178h-2.525c-0.275 0-0.498-0.224-0.498-0.5v-3c0-0.276 0.223-0.5 0.498-0.5h2.525c0.202 0 0.4-0.062 0.566-0.178l2.387-1.657v7.669z"></path> + <path d="M16.934 8.799c-0.086-1.748-1.514-2.991-2.507-3.649-0.47-0.312-1.094-0.122-1.325 0.408l-0.038 0.086c-0.188 0.431-0.045 0.939 0.336 1.194 0.706 0.473 1.586 1.247 1.624 2.065 0.032 0.676-0.553 1.468-1.663 2.27-0.398 0.288-0.529 0.839-0.285 1.275l0.042 0.075c0.266 0.475 0.866 0.624 1.3 0.312 1.74-1.251 2.586-2.606 2.516-4.037z"></path> </svg> |