2016-01-25 18:30:12 -05:00
|
|
|
/**
|
|
|
|
* @file button.js
|
|
|
|
*/
|
|
|
|
import Component from './component';
|
|
|
|
import * as Dom from './utils/dom.js';
|
|
|
|
import * as Events from './utils/events.js';
|
|
|
|
import * as Fn from './utils/fn.js';
|
|
|
|
import log from './utils/log.js';
|
|
|
|
import document from 'global/document';
|
|
|
|
import assign from 'object.assign';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clickable Component which is clickable or keyboard actionable, but is not a native HTML button
|
|
|
|
*
|
|
|
|
* @param {Object} player Main Player
|
|
|
|
* @param {Object=} options Object of option names and values
|
|
|
|
* @extends Component
|
|
|
|
* @class ClickableComponent
|
|
|
|
*/
|
|
|
|
class ClickableComponent extends Component {
|
|
|
|
|
|
|
|
constructor(player, options) {
|
|
|
|
super(player, options);
|
|
|
|
|
|
|
|
this.emitTapEvents();
|
|
|
|
|
2016-11-03 19:43:15 +00:00
|
|
|
this.enable();
|
2016-01-25 18:30:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create the component's DOM element
|
|
|
|
*
|
|
|
|
* @param {String=} type Element's node type. e.g. 'div'
|
|
|
|
* @param {Object=} props An object of properties that should be set on the element
|
|
|
|
* @param {Object=} attributes An object of attributes that should be set on the element
|
|
|
|
* @return {Element}
|
|
|
|
* @method createEl
|
|
|
|
*/
|
2016-07-25 09:49:38 -04:00
|
|
|
createEl(tag = 'div', props = {}, attributes = {}) {
|
2016-01-25 18:30:12 -05:00
|
|
|
props = assign({
|
|
|
|
className: this.buildCSSClass(),
|
|
|
|
tabIndex: 0
|
|
|
|
}, props);
|
|
|
|
|
|
|
|
if (tag === 'button') {
|
|
|
|
log.error(`Creating a ClickableComponent with an HTML element of ${tag} is not supported; use a Button instead.`);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add ARIA attributes for clickable element which is not a native HTML button
|
|
|
|
attributes = assign({
|
2016-07-25 09:49:38 -04:00
|
|
|
'role': 'button',
|
|
|
|
|
|
|
|
// let the screen reader user know that the text of the element may change
|
|
|
|
'aria-live': 'polite'
|
2016-01-25 18:30:12 -05:00
|
|
|
}, attributes);
|
|
|
|
|
2016-11-03 19:43:15 +00:00
|
|
|
this.tabIndex_ = props.tabIndex;
|
|
|
|
|
2016-08-03 15:29:12 -04:00
|
|
|
const el = super.createEl(tag, props, attributes);
|
2016-01-25 18:30:12 -05:00
|
|
|
|
|
|
|
this.createControlTextEl(el);
|
|
|
|
|
|
|
|
return el;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* create control text
|
|
|
|
*
|
|
|
|
* @param {Element} el Parent element for the control text
|
|
|
|
* @return {Element}
|
|
|
|
* @method controlText
|
|
|
|
*/
|
|
|
|
createControlTextEl(el) {
|
|
|
|
this.controlTextEl_ = Dom.createEl('span', {
|
|
|
|
className: 'vjs-control-text'
|
|
|
|
});
|
|
|
|
|
|
|
|
if (el) {
|
|
|
|
el.appendChild(this.controlTextEl_);
|
|
|
|
}
|
|
|
|
|
2016-05-17 10:17:12 +02:00
|
|
|
this.controlText(this.controlText_, el);
|
2016-01-25 18:30:12 -05:00
|
|
|
|
|
|
|
return this.controlTextEl_;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Controls text - both request and localize
|
|
|
|
*
|
2016-05-17 10:17:12 +02:00
|
|
|
* @param {String} text Text for element
|
|
|
|
* @param {Element=} el Element to set the title on
|
2016-01-25 18:30:12 -05:00
|
|
|
* @return {String}
|
|
|
|
* @method controlText
|
|
|
|
*/
|
2016-07-25 09:49:38 -04:00
|
|
|
controlText(text, el = this.el()) {
|
|
|
|
if (!text) {
|
|
|
|
return this.controlText_ || 'Need Text';
|
|
|
|
}
|
|
|
|
|
2016-05-17 10:17:12 +02:00
|
|
|
const localizedText = this.localize(text);
|
2016-01-25 18:30:12 -05:00
|
|
|
|
|
|
|
this.controlText_ = text;
|
2016-05-17 10:17:12 +02:00
|
|
|
this.controlTextEl_.innerHTML = localizedText;
|
|
|
|
el.setAttribute('title', localizedText);
|
2016-01-25 18:30:12 -05:00
|
|
|
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allows sub components to stack CSS class names
|
|
|
|
*
|
|
|
|
* @return {String}
|
|
|
|
* @method buildCSSClass
|
|
|
|
*/
|
|
|
|
buildCSSClass() {
|
|
|
|
return `vjs-control vjs-button ${super.buildCSSClass()}`;
|
|
|
|
}
|
|
|
|
|
2016-03-25 14:16:56 -04:00
|
|
|
/**
|
|
|
|
* Enable the component element
|
|
|
|
*
|
|
|
|
* @return {Component}
|
|
|
|
* @method enable
|
|
|
|
*/
|
|
|
|
enable() {
|
|
|
|
this.removeClass('vjs-disabled');
|
|
|
|
this.el_.setAttribute('aria-disabled', 'false');
|
2016-11-03 19:43:15 +00:00
|
|
|
if (typeof this.tabIndex_ !== 'undefined') {
|
|
|
|
this.el_.setAttribute('tabIndex', this.tabIndex_);
|
|
|
|
}
|
|
|
|
this.on('tap', this.handleClick);
|
|
|
|
this.on('click', this.handleClick);
|
|
|
|
this.on('focus', this.handleFocus);
|
|
|
|
this.on('blur', this.handleBlur);
|
2016-03-25 14:16:56 -04:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disable the component element
|
|
|
|
*
|
|
|
|
* @return {Component}
|
|
|
|
* @method disable
|
|
|
|
*/
|
|
|
|
disable() {
|
|
|
|
this.addClass('vjs-disabled');
|
|
|
|
this.el_.setAttribute('aria-disabled', 'true');
|
2016-11-03 19:43:15 +00:00
|
|
|
if (typeof this.tabIndex_ !== 'undefined') {
|
|
|
|
this.el_.removeAttribute('tabIndex');
|
|
|
|
}
|
|
|
|
this.off('tap', this.handleClick);
|
|
|
|
this.off('click', this.handleClick);
|
|
|
|
this.off('focus', this.handleFocus);
|
|
|
|
this.off('blur', this.handleBlur);
|
2016-03-25 14:16:56 -04:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2016-01-25 18:30:12 -05:00
|
|
|
/**
|
|
|
|
* Handle Click - Override with specific functionality for component
|
|
|
|
*
|
|
|
|
* @method handleClick
|
|
|
|
*/
|
|
|
|
handleClick() {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle Focus - Add keyboard functionality to element
|
|
|
|
*
|
|
|
|
* @method handleFocus
|
|
|
|
*/
|
|
|
|
handleFocus() {
|
|
|
|
Events.on(document, 'keydown', Fn.bind(this, this.handleKeyPress));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle KeyPress (document level) - Trigger click when Space or Enter key is pressed
|
|
|
|
*
|
|
|
|
* @method handleKeyPress
|
|
|
|
*/
|
|
|
|
handleKeyPress(event) {
|
2016-07-25 09:49:38 -04:00
|
|
|
|
2016-01-25 18:30:12 -05:00
|
|
|
// Support Space (32) or Enter (13) key operation to fire a click event
|
|
|
|
if (event.which === 32 || event.which === 13) {
|
|
|
|
event.preventDefault();
|
|
|
|
this.handleClick(event);
|
|
|
|
} else if (super.handleKeyPress) {
|
2016-07-25 09:49:38 -04:00
|
|
|
|
|
|
|
// Pass keypress handling up for unsupported keys
|
|
|
|
super.handleKeyPress(event);
|
2016-01-25 18:30:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle Blur - Remove keyboard triggers
|
|
|
|
*
|
|
|
|
* @method handleBlur
|
|
|
|
*/
|
|
|
|
handleBlur() {
|
|
|
|
Events.off(document, 'keydown', Fn.bind(this, this.handleKeyPress));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Component.registerComponent('ClickableComponent', ClickableComponent);
|
|
|
|
export default ClickableComponent;
|