control-bar_mute-toggle.js
/**
* @file mute-toggle.js
*/
import Button from '../button';
import Component from '../component';
import * as Dom from '../utils/dom.js';
import checkMuteSupport from './volume-control/check-mute-support';
import * as browser from '../utils/browser.js';
/** @import Player from './player' */
/**
* A button component for muting the audio.
*
* @extends Button
*/
class MuteToggle extends Button {
/**
* Creates an instance of this class.
*
* @param {Player} player
* The `Player` that this class should be attached to.
*
* @param {Object} [options]
* The key/value store of player options.
*/
constructor(player, options) {
super(player, options);
// hide this control if volume support is missing
checkMuteSupport(this, player);
this.on(player, ['loadstart', 'volumechange'], (e) => this.update(e));
}
/**
* Builds the default DOM `className`.
*
* @return {string}
* The DOM `className` for this object.
*/
buildCSSClass() {
return `vjs-mute-control ${super.buildCSSClass()}`;
}
/**
* This gets called when an `MuteToggle` is "clicked". See
* {@link ClickableComponent} for more detailed information on what a click can be.
*
* @param {Event} [event]
* The `keydown`, `tap`, or `click` event that caused this function to be
* called.
*
* @listens tap
* @listens click
*/
handleClick(event) {
const vol = this.player_.volume();
const lastVolume = this.player_.lastVolume_();
if (vol === 0) {
const volumeToSet = lastVolume < 0.1 ? 0.1 : lastVolume;
this.player_.volume(volumeToSet);
this.player_.muted(false);
} else {
this.player_.muted(this.player_.muted() ? false : true);
}
}
/**
* Update the `MuteToggle` button based on the state of `volume` and `muted`
* on the player.
*
* @param {Event} [event]
* The {@link Player#loadstart} event if this function was called
* through an event.
*
* @listens Player#loadstart
* @listens Player#volumechange
*/
update(event) {
this.updateIcon_();
this.updateControlText_();
}
/**
* Update the appearance of the `MuteToggle` icon.
*
* Possible states (given `level` variable below):
* - 0: crossed out
* - 1: zero bars of volume
* - 2: one bar of volume
* - 3: two bars of volume
*
* @private
*/
updateIcon_() {
const vol = this.player_.volume();
let level = 3;
this.setIcon('volume-high');
// in iOS when a player is loaded with muted attribute
// and volume is changed with a native mute button
// we want to make sure muted state is updated
if (browser.IS_IOS && this.player_.tech_ && this.player_.tech_.el_) {
this.player_.muted(this.player_.tech_.el_.muted);
}
if (vol === 0 || this.player_.muted()) {
this.setIcon('volume-mute');
level = 0;
} else if (vol < 0.33) {
this.setIcon('volume-low');
level = 1;
} else if (vol < 0.67) {
this.setIcon('volume-medium');
level = 2;
}
Dom.removeClass(this.el_, [0, 1, 2, 3].reduce((str, i) => str + `${i ? ' ' : ''}vjs-vol-${i}`, ''));
Dom.addClass(this.el_, `vjs-vol-${level}`);
}
/**
* If `muted` has changed on the player, update the control text
* (`title` attribute on `vjs-mute-control` element and content of
* `vjs-control-text` element).
*
* @private
*/
updateControlText_() {
const soundOff = this.player_.muted() || this.player_.volume() === 0;
const text = soundOff ? 'Unmute' : 'Mute';
if (this.controlText() !== text) {
this.controlText(text);
}
}
}
/**
* The text that should display over the `MuteToggle`s controls. Added for localization.
*
* @type {string}
* @protected
*/
MuteToggle.prototype.controlText_ = 'Mute';
Component.registerComponent('MuteToggle', MuteToggle);
export default MuteToggle;