/**
* @file clickable-component.js
*/
import Component from './component' ;
import * as Dom from './utils/dom.js' ;
import log from './utils/log.js' ;
import {assign} from './utils/obj' ;
import keycode from 'keycode' ;
/**
* Composant cliquable ou actionnable au clavier, mais qui n'est pas un
* bouton HTML natif.
*
* @extends Component
*/
class ClickableComponent extends Component {
/**
* Crée une instance de cette classe.
*
* @param {Player} player
* Le `Player` auquel cette classe doit être attachée.
*
* @param {Objet} [options]
* Le magasin clé/valeur des options des composants.
*
* @param {function} [options.clickHandler]
* La fonction à appeler lorsque le bouton est cliqué / activé
*
* @param {string} [options.controlText]
* Texte à placer sur le bouton
*
* @param {string} [options.className]
* Une classe ou une liste de classes séparées par des espaces pour ajouter le composant
*
*/
constructor(player, options) {
super(player, options) ;
if (this.options_.controlText) {
this.controlText(this.options_.controlText) ;
}
this.handleMouseOver_ = (e) => this.handleMouseOver(e) ;
this.handleMouseOut_ = (e) => this.handleMouseOut(e) ;
this.handleClick_ = (e) => this.handleClick(e) ;
this.handleKeyDown_ = (e) => this.handleKeyDown(e) ;
this.emitTapEvents() ;
this.enable() ;
}
/**
* Créer l'élément DOM `ClickableComponent`s.
*
* @param {string} [tag=div]
* Le type de nœud de l'élément.
*
* @param {Objet} [props={}]
* Un objet de propriétés à définir sur l'élément.
*
* @param {Objet} [attributes={}]
* Un objet d'attributs à définir sur l'élément.
*
* @return {Element}
* L'élément qui est créé.
*/
createEl(tag = 'div', props = {}, attributes = {}) {
props = assign({
className : this.buildCSSClass(),
tabIndex : 0
}, props) ;
if (tag === 'button') {
log.error(`La création d'un ClickableComponent avec un élément HTML de ${tag} n'est pas prise en charge ; utilisez plutôt un Button.`) ;
}
// Ajouter des attributs ARIA pour les éléments cliquables qui ne sont pas des boutons HTML natifs
attributs = assign({
rôle : "button" (bouton)
}, attributs) ;
this.tabIndex_ = props.tabIndex ;
const el = Dom.createEl(tag, props, attributes) ;
el.appendChild(Dom.createEl('span', {
className : 'vjs-icon-placeholder'
}, {
aria-hidden" : vrai
})) ;
this.createControlTextEl(el) ;
return el ;
}
dispose() {
// supprimer controlTextEl_ lors de l'élimination
this.controlTextEl_ = null ;
super.dispose() ;
}
/**
* Créer un élément de contrôle textuel sur ce `ClickableComponent`
*
* @param {Element} [el]
* Élément parent du texte de contrôle.
*
* @return {Element}
* L'élément de texte du contrôle qui est créé.
*/
createControlTextEl(el) {
this.controlTextEl_ = Dom.createEl('span', {
className : 'vjs-control-text'
}, {
// indique à l'utilisateur du lecteur d'écran que le texte de l'élément peut être modifié
aria-live" : "poli
}) ;
if (el) {
el.appendChild(this.controlTextEl_) ;
}
this.controlText(this.controlText_, el) ;
return this.controlTextEl_ ;
}
/**
* Obtient ou définit le texte de localisation à utiliser pour les contrôles du `ClickableComponent`.
*
* @param {string} [texte]
* Texte de contrôle pour l'élément.
*
* @param {Element} [el=this.el()]
* Élément sur lequel le titre doit être placé.
*
* @return {string}
* - Le texte du contrôle lors de l'obtention de
*/
controlText(text, el = this.el()) {
if (text === undefined) {
return this.controlText_ || 'Texte nécessaire' ;
}
const localizedText = this.localize(text) ;
this.controlText_ = texte ;
Dom.textContent(this.controlTextEl_, localizedText) ;
if (!this.nonIconControl && !this.player_.options_.noUITitleAttributes) {
// Définir l'attribut title si seule une icône est affichée
el.setAttribute('title', localizedText) ;
}
}
/**
* Construit le DOM par défaut `className`.
*
* @return {string}
* Le `nom de classe` du DOM pour cet objet.
*/
buildCSSClass() {
return `vjs-control vjs-button ${super.buildCSSClass()}` ;
}
/**
* Activer ce `ClickableComponent` (composant cliquable)
*/
enable() {
if (!this.enabled_) {
this.enabled_ = true ;
this.removeClass('vjs-disabled') ;
this.el_.setAttribute('aria-disabled', 'false') ;
if (typeof this.tabIndex_ !== 'undefined') {
this.el_.setAttribute('tabIndex', this.tabIndex_) ;
}
this.on(['tap', 'click'], this.handleClick_) ;
this.on('keydown', this.handleKeyDown_) ;
}
}
/**
* Désactiver ce `ClickableComponent` (composant cliquable)
*/
disable() {
this.enabled_ = false ;
this.addClass('vjs-disabled') ;
this.el_.setAttribute('aria-disabled', 'true') ;
if (typeof this.tabIndex_ !== 'undefined') {
this.el_.removeAttribute('tabIndex') ;
}
this.off('mouseover', this.handleMouseOver_) ;
this.off('mouseout', this.handleMouseOut_) ;
this.off(['tap', 'click'], this.handleClick_) ;
this.off('keydown', this.handleKeyDown_) ;
}
/**
* Gère le changement de langue dans ClickableComponent pour le lecteur dans les composants
*
*
*/
handleLanguagechange() {
this.controlText(this.controlText_) ;
}
/**
* Gestionnaire d'événement appelé lorsqu'un `ClickableComponent` reçoit une commande
* événement `click` ou `tap`.
*
* @param {EventTarget~Event} event
* L'événement `tap` ou `click` qui a provoqué l'appel de cette fonction.
*
* @listens tap
* @listens click
* @abstract
*/
handleClick(event) {
if (this.options_.clickHandler) {
this.options_.clickHandler.call(this, arguments) ;
}
}
/**
* Gestionnaire d'événement appelé lorsqu'un `ClickableComponent` reçoit une commande
* événement `keydown`.
*
* Par défaut, si la touche est Espace ou Entrée, elle déclenche un événement `click`.
*
* @param {EventTarget~Event} event
* L'événement `keydown` qui a provoqué l'appel de cette fonction.
*
* @listens keydown
*/
handleKeyDown(event) {
// Prendre en charge l'opération de la touche Espace ou Entrée pour déclencher un événement de clic. En outre,
// empêche l'événement de se propager dans le DOM et de déclencher
// Raccourcis clavier du joueur.
if (keycode.isEventKey(event, 'Space') || keycode.isEventKey(event, 'Enter')) {
event.preventDefault() ;
event.stopPropagation() ;
this.trigger('click') ;
} else {
// Transmettre la gestion des pressions de touches pour les touches non prises en charge
super.handleKeyDown(event) ;
}
}
}
Component.registerComponent('ClickableComponent', ClickableComponent) ;
export default ClickableComponent ;