summaryrefslogtreecommitdiff
path: root/javascript/videojs/src/js/control-bar/volume-control/volume-level-tooltip.js
blob: 9df9843d0c021f97b6e2f8024428f02bb4d619c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
 * @file volume-level-tooltip.js
 */
import Component from '../../component';
import * as Dom from '../../utils/dom.js';
import * as Fn from '../../utils/fn.js';

/** @import Player from '../../player' */

/**
 * Volume level tooltips display a volume above or side by side the volume bar.
 *
 * @extends Component
 */
class VolumeLevelTooltip extends Component {

  /**
   * Creates an instance of this class.
   *
   * @param {Player} player
   *        The {@link 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.update = Fn.throttle(Fn.bind_(this, this.update), Fn.UPDATE_REFRESH_INTERVAL);
  }

  /**
   * Create the volume tooltip DOM element
   *
   * @return {Element}
   *         The element that was created.
   */
  createEl() {
    return super.createEl('div', {
      className: 'vjs-volume-tooltip'
    }, {
      'aria-hidden': 'true'
    });
  }

  /**
   * Updates the position of the tooltip relative to the `VolumeBar` and
   * its content text.
   *
   * @param {Object} rangeBarRect
   *        The `ClientRect` for the {@link VolumeBar} element.
   *
   * @param {number} rangeBarPoint
   *        A number from 0 to 1, representing a horizontal/vertical reference point
   *        from the left edge of the {@link VolumeBar}
   *
   * @param {boolean} vertical
   *        Referees to the Volume control position
   *        in the control bar{@link VolumeControl}
   *
   */
  update(rangeBarRect, rangeBarPoint, vertical, content) {
    if (!vertical) {
      const tooltipRect = Dom.getBoundingClientRect(this.el_);
      const playerRect = Dom.getBoundingClientRect(this.player_.el());
      const volumeBarPointPx = rangeBarRect.width * rangeBarPoint;

      if (!playerRect || !tooltipRect) {
        return;
      }

      const spaceLeftOfPoint = (rangeBarRect.left - playerRect.left) + volumeBarPointPx;
      const spaceRightOfPoint = (rangeBarRect.width - volumeBarPointPx) +
        (playerRect.right - rangeBarRect.right);
      let pullTooltipBy = tooltipRect.width / 2;

      if (spaceLeftOfPoint < pullTooltipBy) {
        pullTooltipBy += pullTooltipBy - spaceLeftOfPoint;
      } else if (spaceRightOfPoint < pullTooltipBy) {
        pullTooltipBy = spaceRightOfPoint;
      }

      if (pullTooltipBy < 0) {
        pullTooltipBy = 0;
      } else if (pullTooltipBy > tooltipRect.width) {
        pullTooltipBy = tooltipRect.width;
      }

      this.el_.style.right = `-${pullTooltipBy}px`;
    }
    this.write(`${content}%`);
  }

  /**
   * Write the volume to the tooltip DOM element.
   *
   * @param {string} content
   *        The formatted volume for the tooltip.
   */
  write(content) {
    Dom.textContent(this.el_, content);
  }

  /**
   * Updates the position of the volume tooltip relative to the `VolumeBar`.
   *
   * @param {Object} rangeBarRect
   *        The `ClientRect` for the {@link VolumeBar} element.
   *
   * @param {number} rangeBarPoint
   *        A number from 0 to 1, representing a horizontal/vertical reference point
   *        from the left edge of the {@link VolumeBar}
   *
   * @param {boolean} vertical
   *        Referees to the Volume control position
   *        in the control bar{@link VolumeControl}
   *
   * @param {number} volume
   *        The volume level to update the tooltip to
   *
   * @param {Function} cb
   *        A function that will be called during the request animation frame
   *        for tooltips that need to do additional animations from the default
   */
  updateVolume(rangeBarRect, rangeBarPoint, vertical, volume, cb) {
    this.requestNamedAnimationFrame('VolumeLevelTooltip#updateVolume', () => {
      this.update(rangeBarRect, rangeBarPoint, vertical, volume.toFixed(0));
      if (cb) {
        cb();
      }
    });
  }
}

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