1
0
mirror of https://github.com/videojs/video.js.git synced 2025-04-11 11:42:08 +02:00

Added a menu button class as a super class to the track buttons and a volume button

This commit is contained in:
Steve Heffernan 2013-04-30 19:00:14 -07:00
parent 9c6c384704
commit 99373ce4b6

View File

@ -6,13 +6,12 @@
* @param {Object=} options
* @constructor
*/
vjs.Menu = vjs.Component.extend({
/** @constructor */
init: function(player, options){
vjs.Component.call(this, player, options);
}
});
vjs.Menu = vjs.Component.extend();
/**
* Add a menu item to the menu
* @param {Object|String} component Component or component type to add
*/
vjs.Menu.prototype.addItem = function(component){
this.addChild(component);
component.on('click', vjs.bind(this, function(){
@ -20,6 +19,7 @@ vjs.Menu.prototype.addItem = function(component){
}));
};
/** @inheritDoc */
vjs.Menu.prototype.createEl = function(){
return vjs.Component.prototype.createEl.call(this, 'ul', {
className: 'vjs-menu'
@ -36,16 +36,11 @@ vjs.MenuItem = vjs.Button.extend({
/** @constructor */
init: function(player, options){
vjs.Button.call(this, player, options);
if (options['selected']) {
this.addClass('vjs-selected');
this.el_.setAttribute('aria-selected',true);
} else {
this.el_.setAttribute('aria-selected',false);
}
this.selected(options['selected']);
}
});
/** @inheritDoc */
vjs.MenuItem.prototype.createEl = function(type, props){
return vjs.Button.prototype.createEl.call(this, 'li', vjs.obj.merge({
className: 'vjs-menu-item',
@ -53,10 +48,15 @@ vjs.MenuItem.prototype.createEl = function(type, props){
}, props));
};
/** @inheritDoc */
vjs.MenuItem.prototype.onClick = function(){
this.selected(true);
};
/**
* Set this menu item as selected or not
* @param {Boolean} selected
*/
vjs.MenuItem.prototype.selected = function(selected){
if (selected) {
this.addClass('vjs-selected');
@ -65,4 +65,127 @@ vjs.MenuItem.prototype.selected = function(selected){
this.removeClass('vjs-selected');
this.el_.setAttribute('aria-selected',false);
}
};
};
/**
* A button class with a popup menu
* @param {vjs.Player|Object} player
* @param {Object=} options
* @constructor
*/
vjs.MenuButton = vjs.Button.extend({
/** @constructor */
init: function(player, options){
vjs.Button.call(this, player, options);
this.menu = this.createMenu();
// Add list to element
this.addChild(this.menu);
// Automatically hide empty menu buttons
if (this.items && this.items.length === 0) {
this.hide();
}
this.on('keyup', this.onKeyPress);
this.el_.setAttribute('aria-haspopup', true);
this.el_.setAttribute('role', 'button');
}
});
/**
* Track the state of the menu button
* @type {Boolean}
*/
vjs.MenuButton.prototype.buttonPressed_ = false;
vjs.MenuButton.prototype.createMenu = function(){
var menu = new vjs.Menu(this.player_);
// Add a title list item to the top
if (this.options().title) {
menu.el().appendChild(vjs.createEl('li', {
className: 'vjs-menu-title',
innerHTML: vjs.capitalize(this.kind_),
tabindex: -1
}));
}
this.items = this.createItems();
// Add menu items to the menu
for (var i = 0; i < this.items.length; i++) {
menu.addItem(this.items[i]);
}
return menu;
};
/**
* Create the list of menu items. Specific to each subclass.
*/
vjs.MenuButton.prototype.createItems = function(){};
/** @inheritDoc */
vjs.MenuButton.prototype.buildCSSClass = function(){
return this.className + ' vjs-menu-button ' + vjs.Button.prototype.buildCSSClass.call(this);
};
// Focus - Add keyboard functionality to element
// This function is not needed anymore. Instead, the keyboard functionality is handled by
// treating the button as triggering a submenu. When the button is pressed, the submenu
// appears. Pressing the button again makes the submenu disappear.
vjs.MenuButton.prototype.onFocus = function(){};
// Can't turn off list display that we turned on with focus, because list would go away.
vjs.MenuButton.prototype.onBlur = function(){};
vjs.MenuButton.prototype.onClick = function(){
// When you click the button it adds focus, which will show the menu indefinitely.
// So we'll remove focus when the mouse leaves the button.
// Focus is needed for tab navigation.
this.one('mouseout', vjs.bind(this, function(){
this.menu.unlockShowing();
this.el_.blur();
}));
if (this.buttonPressed_){
this.unpressButton();
} else {
this.pressButton();
}
};
vjs.MenuButton.prototype.onKeyPress = function(event){
event.preventDefault();
// Check for space bar (32) or enter (13) keys
if (event.which == 32 || event.which == 13) {
if (this.buttonPressed_){
this.unpressButton();
} else {
this.pressButton();
}
// Check for escape (27) key
} else if (event.which == 27){
if (this.buttonPressed_){
this.unpressButton();
}
}
};
vjs.MenuButton.prototype.pressButton = function(){
this.buttonPressed_ = true;
this.menu.lockShowing();
this.el_.setAttribute('aria-pressed', true);
if (this.items && this.items.length > 0) {
this.items[0].el().focus(); // set the focus to the title of the submenu
}
};
vjs.MenuButton.prototype.unpressButton = function(){
this.buttonPressed_ = false;
this.menu.unlockShowing();
this.el_.setAttribute('aria-pressed', false);
};