summaryrefslogtreecommitdiff
path: root/javascript/videojs/src/js/control-bar/volume-control/volume-bar.js
diff options
context:
space:
mode:
Diffstat (limited to 'javascript/videojs/src/js/control-bar/volume-control/volume-bar.js')
-rw-r--r--javascript/videojs/src/js/control-bar/volume-control/volume-bar.js212
1 files changed, 212 insertions, 0 deletions
diff --git a/javascript/videojs/src/js/control-bar/volume-control/volume-bar.js b/javascript/videojs/src/js/control-bar/volume-control/volume-bar.js
new file mode 100644
index 0000000..4e2a02c
--- /dev/null
+++ b/javascript/videojs/src/js/control-bar/volume-control/volume-bar.js
@@ -0,0 +1,212 @@
+/**
+ * @file volume-bar.js
+ */
+import Slider from '../../slider/slider.js';
+import Component from '../../component.js';
+import * as Dom from '../../utils/dom.js';
+import {clamp} from '../../utils/num.js';
+import {IS_IOS, IS_ANDROID} from '../../utils/browser.js';
+
+/** @import Player from '../../player' */
+
+// Required children
+import './volume-level.js';
+import './mouse-volume-level-display.js';
+
+/**
+ * The bar that contains the volume level and can be clicked on to adjust the level
+ *
+ * @extends Slider
+ */
+class VolumeBar extends Slider {
+
+ /**
+ * 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);
+ this.on('slideractive', (e) => this.updateLastVolume_(e));
+ this.on(player, 'volumechange', (e) => this.updateARIAAttributes(e));
+ player.ready(() => this.updateARIAAttributes());
+ }
+
+ /**
+ * Create the `Component`'s DOM element
+ *
+ * @return {Element}
+ * The element that was created.
+ */
+ createEl() {
+ return super.createEl('div', {
+ className: 'vjs-volume-bar vjs-slider-bar'
+ }, {
+ 'aria-label': this.localize('Volume Level'),
+ 'aria-live': 'polite'
+ });
+ }
+
+ /**
+ * Handle mouse down on volume bar
+ *
+ * @param {Event} event
+ * The `mousedown` event that caused this to run.
+ *
+ * @listens mousedown
+ */
+ handleMouseDown(event) {
+ if (!Dom.isSingleLeftClick(event)) {
+ return;
+ }
+
+ super.handleMouseDown(event);
+ }
+
+ /**
+ * Handle movement events on the {@link VolumeMenuButton}.
+ *
+ * @param {Event} event
+ * The event that caused this function to run.
+ *
+ * @listens mousemove
+ */
+ handleMouseMove(event) {
+ const mouseVolumeLevelDisplay = this.getChild('mouseVolumeLevelDisplay');
+
+ if (mouseVolumeLevelDisplay) {
+ const volumeBarEl = this.el();
+ const volumeBarRect = Dom.getBoundingClientRect(volumeBarEl);
+ const vertical = this.vertical();
+ let volumeBarPoint = Dom.getPointerPosition(volumeBarEl, event);
+
+ volumeBarPoint = vertical ? volumeBarPoint.y : volumeBarPoint.x;
+ // The default skin has a gap on either side of the `VolumeBar`. This means
+ // that it's possible to trigger this behavior outside the boundaries of
+ // the `VolumeBar`. This ensures we stay within it at all times.
+ volumeBarPoint = clamp(volumeBarPoint, 0, 1);
+
+ mouseVolumeLevelDisplay.update(volumeBarRect, volumeBarPoint, vertical);
+ }
+
+ if (!Dom.isSingleLeftClick(event)) {
+ return;
+ }
+
+ this.checkMuted();
+ this.player_.volume(this.calculateDistance(event));
+ }
+
+ /**
+ * If the player is muted unmute it.
+ */
+ checkMuted() {
+ if (this.player_.muted()) {
+ this.player_.muted(false);
+ }
+ }
+
+ /**
+ * Get percent of volume level
+ *
+ * @return {number}
+ * Volume level percent as a decimal number.
+ */
+ getPercent() {
+ if (this.player_.muted()) {
+ return 0;
+ }
+ return this.player_.volume();
+ }
+
+ /**
+ * Increase volume level for keyboard users
+ */
+ stepForward() {
+ this.checkMuted();
+ this.player_.volume(this.player_.volume() + 0.1);
+ }
+
+ /**
+ * Decrease volume level for keyboard users
+ */
+ stepBack() {
+ this.checkMuted();
+ this.player_.volume(this.player_.volume() - 0.1);
+ }
+
+ /**
+ * Update ARIA accessibility attributes
+ *
+ * @param {Event} [event]
+ * The `volumechange` event that caused this function to run.
+ *
+ * @listens Player#volumechange
+ */
+ updateARIAAttributes(event) {
+ const ariaValue = this.player_.muted() ? 0 : this.volumeAsPercentage_();
+
+ this.el_.setAttribute('aria-valuenow', ariaValue);
+ this.el_.setAttribute('aria-valuetext', ariaValue + '%');
+ }
+
+ /**
+ * Returns the current value of the player volume as a percentage
+ *
+ * @private
+ */
+ volumeAsPercentage_() {
+ return Math.round(this.player_.volume() * 100);
+ }
+
+ /**
+ * When user starts dragging the VolumeBar, store the volume and listen for
+ * the end of the drag. When the drag ends, if the volume was set to zero,
+ * set lastVolume to the stored volume.
+ *
+ * @listens slideractive
+ * @private
+ */
+ updateLastVolume_() {
+ const volumeBeforeDrag = this.player_.volume();
+
+ this.one('sliderinactive', () => {
+ if (this.player_.volume() === 0) {
+ this.player_.lastVolume_(volumeBeforeDrag);
+ }
+ });
+ }
+
+}
+
+/**
+ * Default options for the `VolumeBar`
+ *
+ * @type {Object}
+ * @private
+ */
+VolumeBar.prototype.options_ = {
+ children: [
+ 'volumeLevel'
+ ],
+ barName: 'volumeLevel'
+};
+
+// MouseVolumeLevelDisplay tooltip should not be added to a player on mobile devices
+if (!IS_IOS && !IS_ANDROID) {
+ VolumeBar.prototype.options_.children.splice(0, 0, 'mouseVolumeLevelDisplay');
+}
+
+/**
+ * Call the update event for this Slider when this event happens on the player.
+ *
+ * @type {string}
+ */
+VolumeBar.prototype.playerEvent = 'volumechange';
+
+Component.registerComponent('VolumeBar', VolumeBar);
+export default VolumeBar;