// Using John Resig's Class implementation http://ejohn.org/blog/simple-javascript-inheritance/ // (function(){var initializing=false, fnTest=/xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; _V_.Class = function(){}; _V_.Class.extend = function(prop) { var _super = this.prototype; initializing = true; var prototype = new this(); initializing = false; for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } function Class() { if ( !initializing && this.init ) this.init.apply(this, arguments); } Class.prototype = prototype; Class.constructor = Class; Class.extend = arguments.callee; return Class;};})(); (function(){ var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; _V_.Class = function(){}; _V_.Class.extend = function(prop) { var _super = this.prototype; initializing = true; var prototype = new this(); initializing = false; for (var name in prop) { prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn){ return function() { var tmp = this._super; this._super = _super[name]; var ret = fn.apply(this, arguments); this._super = tmp; return ret; }; })(name, prop[name]) : prop[name]; } function Class() { if ( !initializing && this.init ) { return this.init.apply(this, arguments); // Attempting to recreate accessing function form of class. } else if (!initializing) { return arguments.callee.prototype.init() } } Class.prototype = prototype; Class.constructor = Class; Class.extend = arguments.callee; return Class; }; })(); /* Player Component- Base class for all UI objects ================================================================================ */ _V_.Component = _V_.Class.extend({ init: function(player, options){ this.player = player; // Allow for overridding default component options options = this.options = _V_.merge(this.options || {}, options); // Create element if one wasn't provided in options if (options.el) { this.el = options.el; } else { this.el = this.createElement(); } // Add any components in options this.initComponents(); }, destroy: function(){}, createElement: function(type, attrs){ return _V_.createElement(type || "div", attrs); }, buildCSSClass: function(){ // Child classes can include a function that does: // return "CLASS NAME" + this._super(); return ""; }, initComponents: function(){ var options = this.options; if (options && options.components) { // Loop through components and add them to the player this.eachProp(options.components, function(name, opts){ // Allow waiting to add components until a specific event is called var tempAdd = this.proxy(function(){ this.addComponent(name, opts); }); if (opts.loadEvent) { this.one(opts.loadEvent, tempAdd) } else { tempAdd(); } }); } }, // Add child components to this component. // Will generate a new child component and then append child component's element to this component's element. // Takes either the name of the UI component class, or an object that contains a name, UI Class, and options. addComponent: function(name, options){ var componentClass, component; // Make sure options is at least an empty object to protect against errors options = options || {}; // Assume name of set is a lowercased name of the UI Class (PlayButton, etc.) componentClass = options.componentClass || _V_.capitalize(name); // Create a new object & element for this controls set // If there's no .player, this is a player component = new _V_[componentClass](this.player || this, options); // Add the UI object's element to the container div (box) this.el.appendChild(component.el); // Set property name on player. Could cause conflicts with other prop names, but it's worth making refs easy. this[name] = component; }, /* Display ================================================================================ */ show: function(){ this.el.style.display = "block"; }, hide: function(){ this.el.style.display = "none"; }, fadeIn: function(){ this.removeClass("vjs-fade-out"); this.addClass("vjs-fade-in"); }, fadeOut: function(){ this.removeClass("vjs-fade-in"); this.addClass("vjs-fade-out"); }, addClass: function(classToAdd){ _V_.addClass(this.el, classToAdd); }, removeClass: function(classToRemove){ _V_.removeClass(this.el, classToRemove); }, /* Events ================================================================================ */ addEvent: function(type, fn){ return _V_.addEvent(this.el, type, _V_.proxy(this, fn)); }, removeEvent: function(type, fn){ return _V_.removeEvent(this.el, type, fn); }, triggerEvent: function(type, e){ return _V_.triggerEvent(this.el, type, e); }, one: function(type, fn) { _V_.one(this.el, type, _V_.proxy(this, fn)); }, /* Ready - Trigger functions when component is ready ================================================================================ */ ready: function(fn){ if (!fn) return this; if (this.isReady) { fn.call(this); } else { if (this.readyQueue === undefined) { this.readyQueue = []; } this.readyQueue.push(fn); } return this; }, triggerReady: function(){ this.isReady = true; if (this.readyQueue && this.readyQueue.length > 0) { // Call all functions in ready queue this.each(this.readyQueue, function(fn){ fn.call(this); }); // Reset Ready Queue this.readyQueue = []; // Allow for using event listeners also, in case you want to do something everytime a source is ready. this.triggerEvent("ready"); } }, /* Utility ================================================================================ */ each: function(arr, fn){ _V_.each.call(this, arr, fn); }, eachProp: function(obj, fn){ _V_.eachProp.call(this, obj, fn); }, extend: function(obj){ _V_.merge(this, obj) }, // More easily attach 'this' to functions proxy: function(fn){ return _V_.proxy(this, fn); } });