Skip to content

Commit

Permalink
@OwenEdwards Fixed volume menu keyboard access. closes #3034
Browse files Browse the repository at this point in the history
  • Loading branch information
OwenEdwards authored and gkatsev committed Jan 26, 2016
1 parent e05931d commit 0ffb27a
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CHANGELOG
## HEAD (Unreleased)
* @OwenEdwards added ClickableComponent. Fixed keyboard operation of buttons ([view](https://github.com/videojs/video.js/pull/3032))
* @OwenEdwards Fixed menu keyboard access and ARIA labeling for screen readers ([view](https://github.com/videojs/video.js/pull/3033))
* @OwenEdwards Fixed volume menu keyboard access ([view](https://github.com/videojs/video.js/pull/3034))

--------------------

Expand Down
4 changes: 4 additions & 0 deletions src/css/components/_volume.scss
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,16 @@
}

.vjs-volume-menu-button-vertical:hover .vjs-menu-content,
.vjs-volume-menu-button-vertical:focus .vjs-menu-content,
.vjs-volume-menu-button-vertical.vjs-slider-active .vjs-menu-content,
.vjs-volume-menu-button-vertical .vjs-lock-showing .vjs-menu-content {
height: 8em;
width: 2.9em;
}

.vjs-volume-menu-button-horizontal:hover .vjs-menu-content,
.vjs-volume-menu-button-horizontal:focus .vjs-menu-content,
.vjs-volume-menu-button-horizontal .vjs-slider-active .vjs-menu-content,
.vjs-volume-menu-button-horizontal .vjs-lock-showing .vjs-menu-content {
height: 2.9em;
width: 8em;
Expand Down
32 changes: 20 additions & 12 deletions src/js/control-bar/volume-menu-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
*/
import * as Fn from '../utils/fn.js';
import Component from '../component.js';
import Menu from '../menu/menu.js';
import MenuButton from '../menu/menu-button.js';
import Popup from '../popup/popup.js';
import PopupButton from '../popup/popup-button.js';
import MuteToggle from './mute-toggle.js';
import VolumeBar from './volume-control/volume-bar.js';
import document from 'global/document';

/**
* Button for volume menu
* Button for volume popup
*
* @param {Player|Object} player
* @param {Object=} options
* @extends MenuButton
* @extends PopupButton
* @class VolumeMenuButton
*/
class VolumeMenuButton extends MenuButton {
class VolumeMenuButton extends PopupButton {

constructor(player, options={}){
// Default to inline
Expand Down Expand Up @@ -66,6 +66,14 @@ class VolumeMenuButton extends MenuButton {
this.on(this.volumeBar, ['sliderinactive', 'blur'], function(){
this.removeClass('vjs-slider-active');
});

this.on(this.volumeBar, ['focus'], function(){
this.addClass('vjs-lock-showing');
});

this.on(this.volumeBar, ['blur'], function(){
this.removeClass('vjs-lock-showing');
});
}

/**
Expand All @@ -88,27 +96,27 @@ class VolumeMenuButton extends MenuButton {
/**
* Allow sub components to stack CSS class names
*
* @return {Menu} The volume menu button
* @method createMenu
* @return {Popup} The volume popup button
* @method createPopup
*/
createMenu() {
let menu = new Menu(this.player_, {
createPopup() {
let popup = new Popup(this.player_, {
contentElType: 'div'
});

let vb = new VolumeBar(this.player_, this.options_.volumeBar);

menu.addChild(vb);
popup.addChild(vb);

this.volumeBar = vb;

this.attachVolumeBarEvents();

return menu;
return popup;
}

/**
* Handle click on volume menu and calls super
* Handle click on volume popup and calls super
*
* @method handleClick
*/
Expand Down
91 changes: 91 additions & 0 deletions src/js/popup/popup-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* @file popup-button.js
*/
import ClickableComponent from '../clickable-component.js';
import Component from '../component.js';
import Popup from './popup.js';
import * as Dom from '../utils/dom.js';
import * as Fn from '../utils/fn.js';
import toTitleCase from '../utils/to-title-case.js';

/**
* A button class with a popup control
*
* @param {Player|Object} player
* @param {Object=} options
* @extends ClickableComponent
* @class PopupButton
*/
class PopupButton extends ClickableComponent {

constructor(player, options={}){
super(player, options);

this.update();
}

/**
* Update popup
*
* @method update
*/
update() {
let popup = this.createPopup();

if (this.popup) {
this.removeChild(this.popup);
}

this.popup = popup;
this.addChild(popup);

if (this.items && this.items.length === 0) {
this.hide();
} else if (this.items && this.items.length > 1) {
this.show();
}
}

/**
* Create popup - Override with specific functionality for component
*
* @return {Popup} The constructed popup
* @method createPopup
*/
createPopup() {}

/**
* Create the component's DOM element
*
* @return {Element}
* @method createEl
*/
createEl() {
return super.createEl('div', {
className: this.buildCSSClass()
});
}

/**
* Allow sub components to stack CSS class names
*
* @return {String} The constructed class name
* @method buildCSSClass
*/
buildCSSClass() {
var menuButtonClass = 'vjs-menu-button';

// If the inline option is passed, we want to use different styles altogether.
if (this.options_.inline === true) {
menuButtonClass += '-inline';
} else {
menuButtonClass += '-popup';
}

return `vjs-menu-button ${menuButtonClass} ${super.buildCSSClass()}`;
}

}

Component.registerComponent('PopupButton', PopupButton);
export default PopupButton;
59 changes: 59 additions & 0 deletions src/js/popup/popup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* @file popup.js
*/
import Component from '../component.js';
import * as Dom from '../utils/dom.js';
import * as Fn from '../utils/fn.js';
import * as Events from '../utils/events.js';

/**
* The Popup component is used to build pop up controls.
*
* @extends Component
* @class Popup
*/
class Popup extends Component {

/**
* Add a popup item to the popup
*
* @param {Object|String} component Component or component type to add
* @method addItem
*/
addItem(component) {
this.addChild(component);
component.on('click', Fn.bind(this, function(){
this.unlockShowing();
}));
}

/**
* Create the component's DOM element
*
* @return {Element}
* @method createEl
*/
createEl() {
let contentElType = this.options_.contentElType || 'ul';
this.contentEl_ = Dom.createEl(contentElType, {
className: 'vjs-menu-content'
});
var el = super.createEl('div', {
append: this.contentEl_,
className: 'vjs-menu'
});
el.appendChild(this.contentEl_);

// Prevent clicks from bubbling up. Needed for Popup Buttons,
// where a click on the parent is significant
Events.on(el, 'click', function(event){
event.preventDefault();
event.stopImmediatePropagation();
});

return el;
}
}

Component.registerComponent('Popup', Popup);
export default Popup;

0 comments on commit 0ffb27a

Please sign in to comment.