1
0
mirror of https://github.com/videojs/video.js.git synced 2025-03-05 15:16:06 +02:00

feat: videojs.getTech works with TitleCase or camelCase names (#4010)

* Fixes #3986 
* update `techOptions` to look for `TitleCase`/`camelCase` user tech options
* remove deprecated usage of Tech as Component
* add a unit test to verify that registerTech works
* change defaultTech_ to defaultTechOrder_
This commit is contained in:
Brandon Casey 2017-02-02 14:34:33 -05:00 committed by GitHub
parent fcb5aa8383
commit a8f2e43274
4 changed files with 56 additions and 23 deletions

View File

@ -806,14 +806,17 @@ class Player extends Component {
this.unloadTech_();
}
const titleTechName = toTitleCase(techName);
const camelTechName = techName.charAt(0).toLowerCase() + techName.slice(1);
// get rid of the HTML5 video tag as soon as we are using another tech
if (techName !== 'Html5' && this.tag) {
if (titleTechName !== 'Html5' && this.tag) {
Tech.getTech('Html5').disposeMediaElement(this.tag);
this.tag.player = null;
this.tag = null;
}
this.techName_ = techName;
this.techName_ = titleTechName;
// Turn off API access because we're loading a new tech that might load asynchronously
this.isReady_ = false;
@ -823,7 +826,7 @@ class Player extends Component {
source,
'nativeControlsForTouch': this.options_.nativeControlsForTouch,
'playerId': this.id(),
'techId': `${this.id()}_${techName}_api`,
'techId': `${this.id()}_${titleTechName}_api`,
'autoplay': this.options_.autoplay,
'preload': this.options_.preload,
'loop': this.options_.loop,
@ -840,6 +843,8 @@ class Player extends Component {
techOptions[props.getterName] = this[props.privateName];
});
assign(techOptions, this.options_[titleTechName]);
assign(techOptions, this.options_[camelTechName]);
assign(techOptions, this.options_[techName.toLowerCase()]);
if (this.tag) {
@ -851,14 +856,13 @@ class Player extends Component {
}
// Initialize tech instance
let TechComponent = Tech.getTech(techName);
const TechClass = Tech.getTech(techName);
// Support old behavior of techs being registered as components.
// Remove once that deprecated behavior is removed.
if (!TechComponent) {
TechComponent = Component.getComponent(techName);
if (!TechClass) {
throw new Error(`No Tech named '${titleTechName}' exists! '${titleTechName}' should be registered using videojs.registerTech()'`);
}
this.tech_ = new TechComponent(techOptions);
this.tech_ = new TechClass(techOptions);
// player.triggerReady is always async, so don't need this to be async
this.tech_.ready(Fn.bind(this, this.handleTechReady_), true);
@ -895,7 +899,7 @@ class Player extends Component {
// Add the tech element in the DOM if it was not already there
// Make sure to not insert the original video element if using Html5
if (this.tech_.el().parentNode !== this.el() && (techName !== 'Html5' || !this.tag)) {
if (this.tech_.el().parentNode !== this.el() && (titleTechName !== 'Html5' || !this.tag)) {
Dom.prependTo(this.tech_.el(), this.el());
}
@ -2102,7 +2106,7 @@ class Player extends Component {
// Loop through each playback technology in the options order
for (let i = 0, j = this.options_.techOrder; i < j.length; i++) {
const techName = toTitleCase(j[i]);
const techName = j[i];
let tech = Tech.getTech(techName);
// Support old behavior of techs being registered as components.
@ -2146,12 +2150,8 @@ class Player extends Component {
// current platform
const techs =
this.options_.techOrder
.map(toTitleCase)
.map((techName) => {
// `Component.getComponent(...)` is for support of old behavior of techs
// being registered as components.
// Remove once that deprecated behavior is removed.
return [techName, Tech.getTech(techName) || Component.getComponent(techName)];
return [techName, Tech.getTech(techName)];
})
.filter(([techName, tech]) => {
// Check if the current tech is defined before continuing
@ -2356,7 +2356,7 @@ class Player extends Component {
* and calls `reset` on the tech`.
*/
reset() {
this.loadTech_(toTitleCase(this.options_.techOrder[0]), null);
this.loadTech_(this.options_.techOrder[0], null);
this.techCall_('reset');
}
@ -3254,7 +3254,7 @@ const navigator = window.navigator;
*/
Player.prototype.options_ = {
// Default order of fallback technology
techOrder: Tech.defaultTechs_,
techOrder: Tech.defaultTechOrder_,
html5: {},
flash: {},

View File

@ -13,6 +13,7 @@ import window from 'global/window';
import document from 'global/document';
import {isPlain} from '../utils/obj';
import * as TRACK_TYPES from '../tracks/track-types';
import toTitleCase from '../utils/to-title-case';
/**
* An Object containing a structure like: `{src: 'url', type: 'mimetype'}` or string
@ -806,10 +807,12 @@ class Tech extends Component {
throw new Error('Techs must have a static canPlaySource method on them');
}
name = toTitleCase(name);
Tech.techs_[name] = tech;
if (name !== 'Tech') {
// camel case the techName for use in techOrder
Tech.defaultTechs_.push(name.charAt(0).toLowerCase() + name.slice(1));
Tech.defaultTechOrder_.push(name);
}
return tech;
}
@ -818,12 +821,18 @@ class Tech extends Component {
* Get a `Tech` from the shared list by name.
*
* @param {string} name
* Name of the component to get
* `camelCase` or `TitleCase` name of the Tech to get
*
* @return {Tech|undefined}
* The `Tech` or undefined if there was no tech with the name requsted.
*/
static getTech(name) {
if (!name) {
return;
}
name = toTitleCase(name);
if (Tech.techs_ && Tech.techs_[name]) {
return Tech.techs_[name];
}
@ -1185,6 +1194,6 @@ Tech.registerTech('Tech', Tech);
*
* @private
*/
Tech.defaultTechs_ = [];
Tech.defaultTechOrder_ = [];
export default Tech;

View File

@ -1272,7 +1272,7 @@ QUnit.test('player#reset loads the Html5 tech and then techCalls reset', functio
Player.prototype.reset.call(testPlayer);
assert.equal(loadedTech, 'Html5', 'we loaded the html5 tech');
assert.equal(loadedTech, 'html5', 'we loaded the html5 tech');
assert.equal(loadedSource, null, 'with a null source');
assert.equal(techCallMethod, 'reset', 'we then reset the tech');
});
@ -1297,7 +1297,7 @@ QUnit.test('player#reset loads the first item in the techOrder and then techCall
Player.prototype.reset.call(testPlayer);
assert.equal(loadedTech, 'Flash', 'we loaded the Flash tech');
assert.equal(loadedTech, 'flash', 'we loaded the Flash tech');
assert.equal(loadedSource, null, 'with a null source');
assert.equal(techCallMethod, 'reset', 'we then reset the tech');
});
@ -1478,6 +1478,9 @@ QUnit.test('techCall runs through middleware if allowedSetter', function(assert)
});
QUnit.test('src selects tech based on middleware', function(assert) {
const oldTechs = Tech.techs_;
const oldDefaultTechOrder = Tech.defaultTechOrder_;
class FooTech extends Html5 {}
class BarTech extends Html5 {}
@ -1538,6 +1541,10 @@ QUnit.test('src selects tech based on middleware', function(assert) {
player.dispose();
delete Tech.techs_.FooTech;
delete Tech.techs_.BarTech;
Tech.defaultTechOrder_ = oldDefaultTechOrder;
Tech.techs_ = oldTechs;
});
QUnit.test('options: plugins', function(assert) {

View File

@ -27,6 +27,23 @@ QUnit.module('Media Tech', {
}
});
QUnit.test('Tech.registerTech and Tech.getTech', function(assert) {
const MyTech = extendFn(Tech);
const oldTechs = Tech.techs_;
const oldDefaultTechOrder = Tech.defaultTechOrder_;
Tech.registerTech('MyTech', MyTech);
assert.ok(Tech.techs_.MyTech, 'Tech is stored in the global list');
assert.notEqual(Tech.defaultTechOrder_.indexOf('MyTech'), -1, 'Tech is stored in the defaultTechOrder array');
assert.strictEqual(Tech.getTech('myTech'), MyTech, 'can get a tech using `camelCase` name');
assert.strictEqual(Tech.getTech('MyTech'), MyTech, 'can get a tech using `titleCase` name');
// reset techs and defaultTechOrder
Tech.techs_ = oldTechs;
Tech.defaultTechOrder_ = oldDefaultTechOrder;
});
QUnit.test('should synthesize timeupdate events by default', function(assert) {
let timeupdates = 0;
const tech = new Tech();