1
0
mirror of https://github.com/videojs/video.js.git synced 2025-03-29 22:07:10 +02:00

@heff added and `extends` function for external subclassing. closes #2078

This commit is contained in:
heff 2015-04-28 11:50:09 -07:00
parent 94f33c8d43
commit f19d13b9bb
5 changed files with 101 additions and 5 deletions

View File

@ -14,6 +14,7 @@ CHANGELOG
* @dconnolly replaced JSON.parse with a safe non-eval JSON parse ([view](https://github.com/videojs/video.js/pull/2077))
* @mmcc added a new default skin, switched to SASS, modified the html ([view](https://github.com/videojs/video.js/pull/1999))
* @gkatsev removed event.isDefaultPrevented in favor of event.defaultPrevented ([view](https://github.com/videojs/video.js/pull/2081))
* @heff added and `extends` function for external subclassing ([view](https://github.com/videojs/video.js/pull/2078))
--------------------

View File

@ -24,6 +24,7 @@
"dependencies": {
"global": "^4.3.0",
"safe-json-parse": "^4.0.0",
"inherits": "^2.0.1",
"videojs-swf": "4.5.4",
"vtt.js": "git+https://github.com/gkatsev/vtt.js.git#shim-build"
},

71
src/js/extends.js Normal file
View File

@ -0,0 +1,71 @@
import * as Lib from './lib';
/**
* A combination of node inherits and babel's inherits (after transpile).
* Both work the same but node adds `super_` to the subClass
* and Bable adds the superClass as __proto__. Both seem useful.
*/
const _inherits = function (subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) {
// node
subClass.super_ = superClass;
}
};
/**
* Function for subclassing using the same inheritance that
* videojs uses internally
*
* ```
* var Button = videojs.getComponent('Button');
*
* var MyButton = videojs.extends(Button, {
* constructor: function(player, options) {
* Button.call(this, player, options);
* },
*
* onClick: function() {
* // doSomething
* }
* });
* ```
*/
const extendsFn = function(superClass, subClassMethods={}) {
let subClass = function() {
superClass.apply(this, arguments);
};
let methods = {};
if (subClassMethods.constructor !== Object.prototype.constructor) {
subClass = subClassMethods.constructor;
methods = subClassMethods;
} else if (typeof subClassMethods === 'function') {
subClass = subClassMethods;
}
_inherits(subClass, superClass);
// Extend subObj's prototype with functions and other properties from props
for (var name in methods) {
if (methods.hasOwnProperty(name)) {
subClass.prototype[name] = methods[name];
}
}
return subClass;
};
export default extendsFn;

View File

@ -15,7 +15,8 @@ import * as setup from './setup';
import Component from './component';
import * as Lib from './lib';
import * as Util from './util.js';
import Player from './player';
import extendsFn from './extends.js';
if (typeof HTMLVideoElement === 'undefined') {
document.createElement('video');
@ -36,9 +37,10 @@ videojs.TOUCH_ENABLED = Lib.TOUCH_ENABLED;
videojs.util = Util;
// Probably want to keep this one for 5.0?
import Player from './player';
videojs.players = Player.players;
videojs.extends = extendsFn;
// REMOVING: We probably should not include this in 5.0 thought it would make it
// more backwards compatible
// // Expose but deprecate the window[componentName] method for accessing components
@ -55,6 +57,4 @@ videojs.players = Player.players;
// Lib.obj.merge(module.exports[name], component);
// });
export default videojs;

View File

@ -255,4 +255,27 @@ function testHelperMakeTag(){
return videoTag;
}
})();
test('should extend Component', function(){
var Component = videojs.getComponent('Component');
var MyComponent = videojs.extends(Component, {
constructor: function() {
this.bar = true;
},
foo: function() {
return true;
}
});
var myComponent = new MyComponent();
ok(myComponent instanceof Component, 'creates an instance of Component');
ok(myComponent instanceof MyComponent, 'creates an instance of MyComponent');
ok(myComponent.bar, 'the constructor function is used');
ok(myComponent.foo(), 'instance methods are applied');
var NoMethods = videojs.extends(Component);
var noMethods = new NoMethods({});
ok(noMethods.on, 'should extend component with no methods or constructor');
});
})();