1(function(){ 2'use strict'; 3var videojs=null; 4if(typeof window.videojs==='undefined'&&typeof require==='function'){ 5videojs=require('video.js'); 6}else{ 7videojs=window.videojs; 8} 9(function(window, videojs){ 10var videoJsResolutionSwitcher, 11defaults={ 12ui: true 13}; 14var MenuItem=videojs.getComponent('MenuItem'); 15var ResolutionMenuItem=videojs.extend(MenuItem, { 16constructor: function(player, options){ 17options.selectable=true; 18MenuItem.call(this, player, options); 19this.src=options.src; 20player.on('resolutionchange', videojs.bind(this, this.update)); 21}}); 22ResolutionMenuItem.prototype.handleClick=function(event){ 23MenuItem.prototype.handleClick.call(this,event); 24this.player_.currentResolution(this.options_.label); 25}; 26ResolutionMenuItem.prototype.update=function(){ 27if(!this.player_){ 28return; 29} 30var selection=this.player_.currentResolution(); 31this.selected(this.options_.label===selection.label); 32}; 33MenuItem.registerComponent('ResolutionMenuItem', ResolutionMenuItem); 34var MenuButton=videojs.getComponent('MenuButton'); 35var ResolutionMenuButton=videojs.extend(MenuButton, { 36constructor: function(player, options){ 37this.label=document.createElement('span'); 38options.label='Quality'; 39MenuButton.call(this, player, options); 40this.el().setAttribute('aria-label','Quality'); 41this.controlText('Quality'); 42if(options.dynamicLabel){ 43videojs.dom.addClass(this.label, 'vjs-resolution-button-label'); 44this.el().children[0].appendChild(this.label); 45}else{ 46var staticLabel=document.createElement('span'); 47videojs.addClass(staticLabel, 'vjs-menu-icon'); 48this.el().children[0].appendChild(staticLabel); 49} 50player.on('updateSources', videojs.bind(this, this.update)); 51player.on('resolutionchange', videojs.bind(this, this.updateLabel)); 52}, 53update: function(){ 54if(!this.player_){ 55return; 56} 57this.sources=this.player_.getGroupedSrc(); 58this.currentSelection=this.player_.currentResolution(); 59this.label.innerHTML=this.currentSelection ? this.currentSelection.label:''; 60return MenuButton.prototype.update.call(this); 61}, 62updateLabel: function(){ 63if(!this.player_){ 64return; 65} 66this.currentSelection=this.player_.currentResolution(); 67this.label.innerHTML=this.currentSelection ? this.currentSelection.label:''; 68}}); 69ResolutionMenuButton.prototype.createItems=function(){ 70var menuItems=[]; 71var labels=(this.sources&&this.sources.label)||{}; 72for (var key in labels){ 73if(labels.hasOwnProperty(key)){ 74menuItems.push(new ResolutionMenuItem( 75this.player_, 76{
77label: key, 78src: labels[key], 79selected: key===(this.currentSelection ? this.currentSelection.label:false) 80}) 81); 82}} 83return menuItems; 84}; 85ResolutionMenuButton.prototype.buildCSSClass=function(){ 86return MenuButton.prototype.buildCSSClass.call(this) + ' vjs-resolution-button'; 87}; 88MenuButton.registerComponent('ResolutionMenuButton', ResolutionMenuButton); 89videoJsResolutionSwitcher=function(options){ 90var settings=videojs.mergeOptions(defaults, options), 91player=this, 92groupedSrc={}, 93currentSources={}, 94currentResolutionState={}; 95player.updateSrc=function(src){ 96if(!src){ return player.src(); } 97src=src.filter(function(source){ 98try { 99return(player.canPlayType(source.type)!==''); 100} catch (e){ 101return true; 102}}); 103this.currentSources=src.sort(compareResolutions); 104this.groupedSrc=bucketSources(this.currentSources); 105var chosen=chooseSrc(this.groupedSrc, this.currentSources, player.currentDimension('width')); 106this.currentResolutionState={ 107label: chosen.label, 108sources: chosen.sources 109}; 110player.trigger('updateSources'); 111player.setSourcesSanitized(chosen.sources, chosen.label); 112player.trigger('resolutionchange'); 113return player; 114}; 115player.addSrc=function(src){ 116if(!src){ return player.src(); } 117var source_list=this.currentSources; 118if(!Array.isArray(source_list)){ 119source_list=[src]; 120}else{ 121source_list.push(src); 122} 123return player.updateSrc(source_list); 124}; 125player.currentResolution=function(label, customSourcePicker){ 126if(label==null){ return this.currentResolutionState; } 127if(!this.groupedSrc||!this.groupedSrc.label||!this.groupedSrc.label[label]){ 128return; 129} 130var sources=this.groupedSrc.label[label]; 131var currentTime=player.currentTime(); 132var isPaused=player.paused(); 133if(!isPaused&&this.player_.options_.bigPlayButton){ 134this.player_.bigPlayButton.hide(); 135} 136var handleSeekEvent='loadeddata'; 137if(this.player_.techName_!=='Youtube'&&this.player_.preload()==='none'&&this.player_.techName_!=='Flash'){ 138handleSeekEvent='timeupdate'; 139} 140player 141.setSourcesSanitized(sources, label, customSourcePicker||settings.customSourcePicker) 142.one(handleSeekEvent, function(){ 143player.currentTime(currentTime); 144if(!isPaused){ 145player.play(); 146} 147player.handleTechSeeked_(); 148player.trigger('resolutionchange'); 149}); 150return player; 151}; 152player.getGroupedSrc=function(){ 153return this.groupedSrc; 154}; 155player.setSourcesSanitized=function(sources, label, customSourcePicker){ 156this.currentResolutionState={ 157label: label, 158sources: sources 159}; 160if(typeof customSourcePicker==='function'){ 161return customSourcePicker(player, sources, label); 162} 163player.src(sources.map(function(src){ 164return {src: src.src, type: src.type, res: src.res};})); 165return player; 166}; 167function compareResolutions(a, b){ 168if(!a.res||!b.res){ return 0; } 169return (+b.res)-(+a.res); 170} 171function bucketSources(src){ 172var resolutions={ 173label: {}, 174res: {}, 175type: {}}; 176src.map(function(source){ 177initResolutionKey(resolutions, 'label', source); 178initResolutionKey(resolutions, 'res', source); 179initResolutionKey(resolutions, 'type', source); 180appendSourceToKey(resolutions, 'label', source); 181appendSourceToKey(resolutions, 'res', source); 182appendSourceToKey(resolutions, 'type', source); 183}); 184return resolutions; 185} 186function initResolutionKey(resolutions, key, source){ 187if(resolutions[key][source[key]]==null){ 188resolutions[key][source[key]]=[]; 189}} 190function appendSourceToKey(resolutions, key, source){ 191resolutions[key][source[key]].push(source); 192} 193function chooseSrc(groupedSrc, src, player_width){ 194var last_index=src.length - 1, 195selectedRes=src[last_index].res, 196selectedLabel=src[last_index].label, 197i; 198for (i in src){ 199if(player_width > src[i].res){ 200selectedRes=src[i].res; 201selectedLabel=src[i].label; 202break; 203}} 204return {res: selectedRes, label: selectedLabel, sources: groupedSrc.res[selectedRes]};} 205function initResolutionForYt(player){ 206var _yts={ 207highres: {res: 1080, label: '1080', yt: 'highres'}, 208hd1080: {res: 1080, label: '1080', yt: 'hd1080'}, 209hd720: {res: 720, label: '720', yt: 'hd720'}, 210large: {res: 480, label: '480', yt: 'large'}, 211medium: {res: 360, label: '360', yt: 'medium'}, 212small: {res: 240, label: '240', yt: 'small'}, 213tiny: {res: 144, label: '144', yt: 'tiny'}, 214auto: {res: 0, label: 'auto', yt: 'auto'}}; 215var _customSourcePicker=function(_player, _sources, _label){ 216player.tech_.ytPlayer.setPlaybackQuality(_sources[0]._yt); 217player.trigger('updateSources'); 218return player; 219}; 220settings.customSourcePicker=_customSourcePicker; 221player.tech_.ytPlayer.setPlaybackQuality('auto'); 222player.tech_.ytPlayer.addEventListener('onPlaybackQualityChange', function(event){ 223for(var res in _yts){ 224if(res.yt===event.data){ 225player.currentResolution(res.label, _customSourcePicker); 226return; 227}} 228}); 229player.one('play', function(){ 230var qualities=player.tech_.ytPlayer.getAvailableQualityLevels(); 231var _sources=[]; 232qualities.map(function(q){ 233_sources.push({ 234src: player.src().src, 235type: player.src().type, 236label: _yts[q].label, 237res: _yts[q].res, 238_yt: _yts[q].yt 239}); 240}); 241player.groupedSrc=bucketSources(_sources); 242var chosen={label: 'auto', res: 0, sources: player.groupedSrc.label.auto}; 243this.currentResolutionState={ 244label: chosen.label, 245sources: chosen.sources 246}; 247player.trigger('updateSources'); 248player.setSourcesSanitized(chosen.sources, chosen.label, _customSourcePicker); 249}); 250} 251player.ready(function(){ 252if(settings.ui){ 253var menuButton=new ResolutionMenuButton(player, settings); 254player.controlBar.resolutionSwitcher=player.controlBar.el_.insertBefore(menuButton.el_, player.controlBar.getChild('fullscreenToggle').el_); 255player.controlBar.resolutionSwitcher.dispose=function(){ 256this.parentNode.removeChild(this); 257};} 258if(player.options_.sources.length > 1){ 259player.updateSrc(player.options_.sources); 260} 261if(player.techName_==='Youtube'){ 262initResolutionForYt(player); 263}}); 264}; 265videojs.registerPlugin('videoJsResolutionSwitcher', videoJsResolutionSwitcher); 266})(window, videojs); 267})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.