mirror of
https://github.com/iv-org/videojs-quality-selector.git
synced 2025-07-20 13:48:47 -04:00
Initial implementation
This commit is contained in:
parent
f261cc04a2
commit
156e5923c7
14 changed files with 413 additions and 9 deletions
|
@ -1,3 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {};
|
46
src/js/components/QualityOption.js
Normal file
46
src/js/components/QualityOption.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('underscore'),
|
||||
events = require('../events');
|
||||
|
||||
module.exports = function(videojs) {
|
||||
var MenuItem = videojs.getComponent('MenuItem');
|
||||
|
||||
/**
|
||||
* A MenuItem to represent a video resolution
|
||||
*
|
||||
* @class QualityOption
|
||||
* @extends videojs.MenuItem
|
||||
*/
|
||||
return videojs.extend(MenuItem, {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor: function(player, options) {
|
||||
var source = options.source;
|
||||
|
||||
if (!_.isObject(source)) {
|
||||
throw new Error('was not provided a "source" object, but rather: ' + (typeof source));
|
||||
}
|
||||
|
||||
options = _.extend({
|
||||
selectable: true,
|
||||
label: source.label,
|
||||
}, options);
|
||||
|
||||
MenuItem.call(this, player, options);
|
||||
|
||||
this.source = source;
|
||||
},
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
handleClick: function(event) {
|
||||
MenuItem.prototype.handleClick.call(this, event);
|
||||
this.player().trigger(events.QUALITY_SELECTED, this.source);
|
||||
},
|
||||
|
||||
});
|
||||
};
|
80
src/js/components/QualitySelector.js
Normal file
80
src/js/components/QualitySelector.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('underscore'),
|
||||
events = require('../events'),
|
||||
qualityOptionFactory = require('./QualityOption');
|
||||
|
||||
module.exports = function(videojs) {
|
||||
var MenuButton = videojs.getComponent('MenuButton'),
|
||||
QualityOption = qualityOptionFactory(videojs),
|
||||
QualitySelector;
|
||||
|
||||
/**
|
||||
* A component for changing video resolutions
|
||||
*
|
||||
* @class QualitySelector
|
||||
* @extends videojs.Button
|
||||
*/
|
||||
QualitySelector = videojs.extend(MenuButton, {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
constructor: function(player, options) {
|
||||
MenuButton.call(this, player, options);
|
||||
|
||||
this.selectedSource = options.selectedSource || player.currentSource();
|
||||
|
||||
player.on(events.QUALITY_SELECTED, function(event, source) {
|
||||
this.setSelectedSource(source);
|
||||
}.bind(this));
|
||||
|
||||
// Since it's possible for the player to get a source before the selector is
|
||||
// created, make sure to update once we get a "ready" signal.
|
||||
player.one('ready', function() {
|
||||
this.update();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the source that is selected in the menu
|
||||
*
|
||||
* @param source {object} player source to display as selected
|
||||
*/
|
||||
setSelectedSource: function(source) {
|
||||
this.selectedSource = source;
|
||||
this.update();
|
||||
},
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
createItems: function() {
|
||||
var player = this.player(),
|
||||
sources = player.currentSources();
|
||||
|
||||
if (!sources || sources.length < 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return _.map(sources, function(source) {
|
||||
return new QualityOption(player, {
|
||||
source: source,
|
||||
selected: this.selectedSource ? source.src === this.selectedSource.src : false,
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
buildWrapperCSSClass: function() {
|
||||
return 'vjs-quality-selector ' + MenuButton.prototype.buildWrapperCSSClass.call(this);
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
videojs.registerComponent('QualitySelector', QualitySelector);
|
||||
|
||||
return QualitySelector;
|
||||
};
|
7
src/js/events.js
Normal file
7
src/js/events.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
|
||||
QUALITY_SELECTED: 'qualitySelected',
|
||||
|
||||
};
|
14
src/js/index.js
Normal file
14
src/js/index.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
var events = require('./events'),
|
||||
qualitySelectorFactory = require('./components/QualitySelector'),
|
||||
sourceInterceptorFactory = require('./middleware/SourceInterceptor');
|
||||
|
||||
module.exports = function(videojs) {
|
||||
videojs = videojs || window.videojs;
|
||||
|
||||
qualitySelectorFactory(videojs);
|
||||
sourceInterceptorFactory(videojs);
|
||||
};
|
||||
|
||||
module.exports.EVENTS = events;
|
72
src/js/middleware/SourceInterceptor.js
Normal file
72
src/js/middleware/SourceInterceptor.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('underscore'),
|
||||
events = require('../events'),
|
||||
QUALITY_CHANGE_CLASS = 'vjs-quality-changing';
|
||||
|
||||
module.exports = function(videojs) {
|
||||
|
||||
videojs.use('*', function(player) {
|
||||
|
||||
player.on(events.QUALITY_SELECTED, function(event, newSource) {
|
||||
var sources = player.currentSources(),
|
||||
currentTime = player.currentTime(),
|
||||
isPaused = player.paused(),
|
||||
selectedSource;
|
||||
|
||||
player.addClass(QUALITY_CHANGE_CLASS);
|
||||
|
||||
// Find and set the new selected source
|
||||
// Note: See `setSource` for the reason behind using both 'isDefault'
|
||||
// and 'isdefault'
|
||||
sources = _.map(sources, _.partial(_.omit, _, [ 'isDefault', 'isdefault' ]));
|
||||
selectedSource = _.findWhere(sources, { src: newSource.src });
|
||||
// Note: `_.findWhere` returns a reference to an object. Thus the
|
||||
// following updates the original object in `sources`.
|
||||
selectedSource.isDefault = true;
|
||||
|
||||
player.src(sources);
|
||||
|
||||
player.one('loadeddata', function() {
|
||||
player.removeClass(QUALITY_CHANGE_CLASS);
|
||||
player.currentTime(currentTime);
|
||||
if (!isPaused) {
|
||||
player.play();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
setSource: function(autoSelectedSource, next) {
|
||||
var sources = player.currentSources(),
|
||||
defaultSource, selectedSource,
|
||||
qualitySelector;
|
||||
|
||||
defaultSource = _.find(sources, function(source) {
|
||||
// While the simplest check would be `!!source.isDefault`, remember that
|
||||
// the sources can come from a `<source>` tag. Therefore, the lowercase
|
||||
// form, `isdefault`, needs to be checked.
|
||||
return source.isDefault === true
|
||||
|| source.isDefault === 'true'
|
||||
|| source.isdefault === true
|
||||
|| source.isdefault === 'true';
|
||||
});
|
||||
|
||||
selectedSource = defaultSource || autoSelectedSource;
|
||||
|
||||
// Update the quality selector with the new source
|
||||
qualitySelector = player.controlBar.getChild('qualitySelector');
|
||||
if (qualitySelector) {
|
||||
qualitySelector.update();
|
||||
}
|
||||
|
||||
// Pass along selected source
|
||||
next(null, selectedSource);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
};
|
3
src/js/standalone.js
Normal file
3
src/js/standalone.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
require('./index')();
|
28
src/sass/quality-selector.scss
Normal file
28
src/sass/quality-selector.scss
Normal file
|
@ -0,0 +1,28 @@
|
|||
.vjs-quality-selector {
|
||||
.vjs-menu-button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.vjs-icon-placeholder {
|
||||
// From video.js font: https://github.com/videojs/font
|
||||
font-family: 'VideoJS';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
&:before {
|
||||
content: '\f110';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vjs-quality-changing {
|
||||
.vjs-big-play-button {
|
||||
display: none;
|
||||
}
|
||||
.vjs-control-bar {
|
||||
display: flex;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue