1
0
mirror of https://github.com/videojs/video.js.git synced 2025-01-25 11:13:52 +02:00

Changed to vjs.obj.function naming for object related functions.

Updated mergeOptions to just options.
This commit is contained in:
Steve Heffernan 2013-01-25 17:36:40 -08:00
parent c7d3b9ebf9
commit dc18f475f8
13 changed files with 146 additions and 92 deletions

View File

@ -39,7 +39,7 @@ module.exports = function(grunt) {
minified: ['test/minified.html']
},
watch: {
files: [ "src/**/*.js" ],
files: [ "src/**/*.js", "test/unit/*.js" ],
tasks: "dev"
}
// Copy is broken. Waiting for an update to use.
@ -133,6 +133,7 @@ module.exports = function(grunt) {
// + ' --formatting=pretty_print'
+ ' --js_output_file=' + dest
+ ' --create_source_map ' + dest + '.map --source_map_format=V3'
+ ' --jscomp_warning=checkTypes --warning_level=VERBOSE';
+ ' --output_wrapper "(function() {%output%})();//@ sourceMappingURL=video.js.map"';
files.forEach(function(file){

View File

@ -17,8 +17,11 @@ goog.require('vjs.dom');
vjs.Component = function(player, options, ready){
this.player_ = player;
// // Allow for overridding default component options
options = this.options_ = this.mergeOptions(this.options_, options);
// Make a copy of prototype.options_ to protect against overriding global defaults
this.options_ = vjs.obj.copy(this.options_);
// Updated options with supplied options
options = this.options(options);
// Get ID from options, element, or create using player ID and unique ID
this.id_ = options['id'] || ((options['el'] && options['el']['id']) ? options['el']['id'] : player.id() + '_component_' + vjs.guid++ );
@ -95,20 +98,20 @@ vjs.Component.prototype.options_;
/**
* Deep merge of options objects
* Whenever a property is an object on both options objects
* the two properties will be merged using mergeOptions
* the two properties will be merged using vjs.obj.deepMerge.
*
* This is used for merging options for child components. We
* want it to be easy to override individual options on a child
* component without having to rewrite all the other default options.
*
* parentDefaultOptions = {
* Parent.prototype.options_ = {
* children: {
* 'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
* 'childTwo': {},
* 'childThree': {}
* }
* }
* parentOptionsFromInit = {
* newOptions = {
* children: {
* 'childOne': { 'foo': 'baz', 'abc': '123' }
* 'childTwo': null,
@ -116,7 +119,7 @@ vjs.Component.prototype.options_;
* }
* }
*
* this.mergeOptions(parentDefaultOptions, parentOptionsFromInit);
* this.options(newOptions);
*
* RESULT
*
@ -129,41 +132,13 @@ vjs.Component.prototype.options_;
* }
* }
*
*
* @param {Object} obj1 Object whose values will be overwritten
* @param {Object} obj2 Object whose values will overwrite
* @param {Object} obj Object whose values will be overwritten
* @return {Object} NEW merged object. Does not return obj1.
*/
vjs.Component.prototype.mergeOptions = function(obj1, obj2){
var retObj, toString, hasOwnProp, propName, objDef, val1, val2;
vjs.Component.prototype.options = function(obj){
if (obj === undefined) return this.options_;
hasOwnProp = Object.prototype.hasOwnProperty;
toString = Object.prototype.toString;
objDef = '[object Object]';
obj1 = obj1 || {};
retObj = {};
// Make a copy of obj1 so we don't affect the original options
vjs.eachProp(obj1, function(name, val){
retObj[name] = val;
});
if (!obj2) { return retObj; }
for (propName in obj2){
if (hasOwnProp.call(obj2, propName)) {
val1 = retObj[propName];
val2 = obj2[propName];
if (toString.call(val1) === objDef && toString.call(val2) === objDef) {
retObj[propName] = this.mergeOptions(val1, val2);
} else {
retObj[propName] = obj2[propName];
}
}
}
return retObj;
return this.options_ = vjs.obj.deepMerge(this.options_, obj);
};
/**
@ -363,7 +338,7 @@ vjs.Component.prototype.initChildren = function(){
var self = this;
// Loop through components and add them to the player
vjs.eachProp(options['children'], function(name, opts){
vjs.obj.each(options['children'], function(name, opts){
// Allow for disabling default components
// e.g. vjs.options['children']['posterImage'] = false

6
src/js/controls.js vendored
View File

@ -96,7 +96,7 @@ goog.inherits(vjs.Button, vjs.Control);
vjs.Button.prototype.createEl = function(type, props){
// Add standard Aria and Tabindex info
props = vjs.merge({
props = vjs.obj.merge({
className: this.buildCSSClass(),
innerHTML: '<div><span class="vjs-control-text">' + (this.buttonText || 'Need Text') + '</span></div>',
role: 'button',
@ -486,7 +486,7 @@ vjs.Slider = function(player, options){
goog.inherits(vjs.Slider, vjs.Component);
vjs.Slider.prototype.createEl = function(type, props) {
props = vjs.merge({
props = vjs.obj.merge({
role: 'slider',
'aria-valuenow': 0,
'aria-valuemin': 0,
@ -983,7 +983,7 @@ vjs.MenuItem = function(player, options){
goog.inherits(vjs.MenuItem, vjs.Button);
vjs.MenuItem.prototype.createEl = function(type, props){
return goog.base(this, 'createEl', 'li', vjs.merge({
return goog.base(this, 'createEl', 'li', vjs.obj.merge({
className: 'vjs-menu-item',
innerHTML: this.options_['label']
}, props));

View File

@ -1,3 +1,9 @@
/**
* @fileoverview Add JSON support
* @suppress {undefinedVars}
* (Compiler doesn't like JSON not being declared)
*/
goog.provide('vjs.JSON');
/**

View File

@ -1,4 +1,5 @@
goog.provide('vjs.dom');
goog.provide('vjs.obj');
goog.require('vjs');
@ -35,6 +36,14 @@ vjs.capitalize = function(string){
return string.charAt(0).toUpperCase() + string.slice(1);
};
/**
* Object functions container
* @type {Object}
*/
vjs.obj = {};
vjs.obj.toString = Object.prototype.toString;
vjs.obj.hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Loop through each property in an object and call a function
* whose arguments are (key,value)
@ -42,33 +51,71 @@ vjs.capitalize = function(string){
* @param {Function} fn Function to be called on each property.
* @this {*}
*/
vjs.eachProp = function(obj, fn){
if (!obj) { return; }
for (var name in obj) {
if (obj.hasOwnProperty(name)) {
fn.call(this, name, obj[name]);
vjs.obj.each = function(obj, fn){
for (var key in obj) {
if (vjs.obj.hasOwnProperty.call(obj, key)) {
fn.call(this, key, obj[key]);
}
}
};
/**
* Merge two objects together and return the original.
* @param {[type]} obj1 [description]
* @param {[type]} obj2 [description]
* @param {[type]} safe [description]
* @return {[type]}
* @param {Object} obj1
* @param {Object} obj2
* @return {Object}
*/
vjs.merge = function(obj1, obj2){
// Make sure second object exists
vjs.obj.merge = function(obj1, obj2){
if (!obj2) { return obj1; }
for (var propName in obj2){
if (obj2.hasOwnProperty(propName)) { obj1[propName] = obj2[propName]; }
for (var key in obj2){
if (vjs.obj.hasOwnProperty.call(obj2, key)) {
obj1[key] = obj2[key];
}
}
return obj1;
};
/**
* Merge two objects, and merge any properties that are objects
* instead of just overwriting one. Uses to merge options hashes
* where deeper default settings are important.
* @param {Object} obj1 Object to override
* @param {Object} obj2 Overriding object
* @return {Object} New object. Obj1 and Obj2 will be untouched.
*/
vjs.obj.deepMerge = function(obj1, obj2){
var key, val1, val2, objDef;
objDef = '[object Object]';
// Make a copy of obj1 so we're not ovewriting original values.
// like prototype.options_ and all sub options objects
obj1 = vjs.obj.copy(obj1);
for (key in obj2){
if (vjs.obj.hasOwnProperty.call(obj2, key)) {
val1 = obj1[key];
val2 = obj2[key];
// Check if both properties are pure objects and do a deep merge if so
if (vjs.obj.toString.call(val1) === objDef && vjs.obj.toString.call(val2) === objDef) {
obj1[key] = vjs.obj.deepMerge(val1, val2);
} else {
obj1[key] = obj2[key];
}
}
}
return obj1;
};
/**
* Make a copy of the supplied object
* @param {Object} obj Object to copy
* @return {Object} Copy of object
*/
vjs.obj.copy = function(obj){
return vjs.obj.merge({}, obj);
};
/**
* Bind (a.k.a proxy or Context). A simple method for changing the context of a function
It also stores a unique id on the function so it can be easily removed from events

View File

@ -35,7 +35,7 @@ vjs.Flash = function(player, options, ready){
playerOptions = player.options_,
// Merge default flashvars with ones passed in to init
flashVars = vjs.merge({
flashVars = vjs.obj.merge({
// SWF Callback Functions
'readyFunction': 'videojs.Flash.onReady',
@ -51,13 +51,13 @@ vjs.Flash = function(player, options, ready){
}, options['flashVars']),
// Merge default parames with ones passed in
params = vjs.merge({
params = vjs.obj.merge({
'wmode': 'opaque', // Opaque is needed to overlay controls, but can affect playback performance
'bgcolor': '#000000' // Using bgcolor prevents a white flash when the object is loading
}, options['params']),
// Merge default attributes with ones passed in
attributes = vjs.merge({
attributes = vjs.obj.merge({
'id': objId,
'name': objId, // Both ID and Name needed or swf to identifty itself
'class': 'vjs-tech'
@ -285,16 +285,19 @@ var createGetter = function(attr){
api[attr] = function(){ return this.el_.vjs_getProperty(attr); };
};
// Create getter and setters for all read/write attributes
for (var i = 0; i < readWrite.length; i++) {
createGetter(readWrite[i]);
createSetter(readWrite[i]);
}
(function(){
var i;
// Create getter and setters for all read/write attributes
for (i = 0; i < readWrite.length; i++) {
createGetter(readWrite[i]);
createSetter(readWrite[i]);
}
// Create getters for read-only attributes
for (var i = 0; i < readOnly.length; i++) {
createGetter(readOnly[i]);
}
// Create getters for read-only attributes
for (i = 0; i < readOnly.length; i++) {
createGetter(readOnly[i]);
}
})();
/* Flash Support Testing -------------------------------------------------------- */
@ -434,13 +437,13 @@ vjs.Flash.getEmbedCode = function(swf, flashVars, params, attributes){
// Convert flash vars to string
if (flashVars) {
vjs.eachProp(flashVars, function(key, val){
vjs.obj.each(flashVars, function(key, val){
flashVarsString += (key + '=' + val + '&amp;');
});
}
// Add swf, flashVars, and other default params
params = vjs.merge({
params = vjs.obj.merge({
'movie': swf,
'flashvars': flashVarsString,
'allowScriptAccess': 'always', // Required to talk to swf
@ -448,11 +451,11 @@ vjs.Flash.getEmbedCode = function(swf, flashVars, params, attributes){
}, params);
// Create param tags string
vjs.eachProp(params, function(key, val){
vjs.obj.each(params, function(key, val){
paramsString += '<param name="'+key+'" value="'+val+'" />';
});
attributes = vjs.merge({
attributes = vjs.obj.merge({
// Add swf to attributes (need both for IE and Others to work)
'data': swf,
@ -463,7 +466,7 @@ vjs.Flash.getEmbedCode = function(swf, flashVars, params, attributes){
}, attributes);
// Create Attributes string
vjs.eachProp(attributes, function(key, val){
vjs.obj.each(attributes, function(key, val){
attrsString += (key + '="' + val + '" ');
});

View File

@ -17,7 +17,7 @@ vjs.Player = function(tag, options, ready){
// which overrides globally set options.
// This latter part coincides with the load order
// (tag must exist before Player)
options = this.mergeOptions(this.getTagSettings(tag), options);
options = vjs.obj.merge(this.getTagSettings(tag), options);
// Cache for video property values.
this.cache_ = {};
@ -93,7 +93,7 @@ vjs.Player.prototype.getTagSettings = function(tag){
'tracks': []
};
vjs.merge(options, vjs.getAttributeValues(tag));
vjs.obj.merge(options, vjs.getAttributeValues(tag));
// Get tag children settings
if (tag.hasChildNodes()) {
@ -216,7 +216,7 @@ vjs.Player.prototype.loadTech = function(techName, source){
};
// Grab tech-specific options from player options and add source and parent element to use.
var techOptions = vjs.merge({ source: source, parentEl: this.el_ }, this.options_[techName.toLowerCase()]);
var techOptions = vjs.obj.merge({ source: source, parentEl: this.el_ }, this.options_[techName.toLowerCase()]);
if (source) {
if (source.src == this.cache_.src && this.cache_.currentTime > 0) {
@ -832,7 +832,7 @@ vjs.Player.prototype.poster_;
/**
* Get or set the poster image source url.
* @param {String} src Poster image source URL
* @return {String=} Poster image source URL or null
* @return {String} Poster image source URL or null
*/
vjs.Player.prototype.poster = function(src){
if (src !== undefined) {

View File

@ -1012,7 +1012,7 @@ vjs.ChaptersTrackMenuItem.prototype.update = function(){
};
// Add Buttons to controlBar
vjs.merge(vjs.ControlBar.prototype.options_['children'], {
vjs.obj.merge(vjs.ControlBar.prototype.options_['children'], {
'subtitlesButton': {},
'captionsButton': {},
'chaptersButton': {}

View File

@ -37,24 +37,25 @@ test('should init child coponents from options', function(){
});
test('should do a deep merge of child options', function(){
var compDefaultOptions = {
'children': {
// Create a default option for component
vjs.Component.prototype.options_ = {
'example': {
'childOne': { 'foo': 'bar', 'asdf': 'fdsa' },
'childTwo': {},
'childThree': {}
}
}
var compInitOptions = {
'children': {
var comp = new vjs.Component(getFakePlayer(), {
'example': {
'childOne': { 'foo': 'baz', 'abc': '123' },
'childThree': null,
'childFour': {}
}
}
});
var mergedOptions = vjs.Component.prototype.mergeOptions(compDefaultOptions, compInitOptions);
var children = mergedOptions['children'];
var mergedOptions = comp.options();
var children = mergedOptions['example'];
ok(children['childOne']['foo'] === 'baz', 'value three levels deep overridden');
ok(children['childOne']['asdf'] === 'fdsa', 'value three levels deep maintained');
@ -62,6 +63,11 @@ test('should do a deep merge of child options', function(){
ok(children['childTwo'], 'object two levels deep maintained');
ok(children['childThree'] === null, 'object two levels deep removed');
ok(children['childFour'], 'object two levels deep added');
ok(vjs.Component.prototype.options_['example']['childOne']['foo'] === 'bar', 'prototype options were not overridden');
// Reset default component options to none
vjs.Component.prototype.options_ = null;
});
test('should dispose of component and children', function(){

View File

@ -5,7 +5,7 @@ test('should create a video tag and have access children in old IE', function(){
fixture.innerHTML += "<video id='test_vid_id'><source type='video/mp4'></video>";
vid = document.getElementById('test_vid_id');
var vid = document.getElementById('test_vid_id');
ok(vid.childNodes.length === 1);
ok(vid.childNodes[0].getAttribute('type') === 'video/mp4');

View File

@ -22,13 +22,25 @@ test('should loop through each property on an object', function(){
}
// Add 3 to each value
vjs.eachProp(asdf, function(key, value){
vjs.obj.each(asdf, function(key, value){
asdf[key] = value + 3;
});
deepEqual(asdf,{a:4,b:5,'c':6})
});
test('should copy an object', function(){
var asdf = {
a: 1,
b: 2,
'c': 3
}
var fdsa = vjs.obj.copy(asdf);
deepEqual(asdf,fdsa)
});
test('should add context to a function', function(){
var newContext = { test: 'obj'};
var asdf = function(){

View File

@ -1,6 +1,9 @@
// Fake a media playback tech controller so that player tests
// Fake a media playback tech controller so that player tests
// can run without HTML5 or Flash, of which PhantomJS supports neither.
/**
* @constructor
*/
vjs.MediaFaker = function(player, options, onReady){
goog.base(this, player, options, onReady);
@ -30,4 +33,4 @@ vjs.MediaFaker.prototype.volume = function(){ return 0; };
goog.exportSymbol('videojs.MediaFaker', vjs.MediaFaker);
goog.exportProperty(vjs.MediaFaker, 'isSupported', vjs.MediaFaker.isSupported);
goog.exportProperty(vjs.MediaFaker, 'canPlaySource', vjs.MediaFaker.canPlaySource);
goog.exportProperty(vjs.MediaFaker, 'canPlaySource', vjs.MediaFaker.canPlaySource);

View File

@ -8,12 +8,13 @@ var PlayerTest = {
return videoTag;
},
makePlayer: function(playerOptions){
var player;
var videoTag = PlayerTest.makeTag();
var fixture = document.getElementById('qunit-fixture');
fixture.appendChild(videoTag);
var opts = vjs.merge({
var opts = vjs.obj.merge({
'techOrder': ['mediaFaker']
}, playerOptions);