Source: ui/playback_rate_selection.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.ui.PlaybackRateSelection');
  7. goog.require('shaka.ui.Controls');
  8. goog.require('shaka.ui.Enums');
  9. goog.require('shaka.ui.Locales');
  10. goog.require('shaka.ui.Localization');
  11. goog.require('shaka.ui.OverflowMenu');
  12. goog.require('shaka.ui.SettingsMenu');
  13. goog.require('shaka.ui.Utils');
  14. goog.require('shaka.util.Dom');
  15. goog.requireType('shaka.ui.Controls');
  16. /**
  17. * @extends {shaka.ui.SettingsMenu}
  18. * @final
  19. * @export
  20. */
  21. shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
  22. /**
  23. * @param {!HTMLElement} parent
  24. * @param {!shaka.ui.Controls} controls
  25. */
  26. constructor(parent, controls) {
  27. super(parent, controls, shaka.ui.Enums.MaterialDesignIcons.PLAYBACK_RATE);
  28. this.button.classList.add('shaka-playbackrate-button');
  29. this.menu.classList.add('shaka-playback-rates');
  30. this.button.classList.add('shaka-tooltip-status');
  31. if (!Array.from(parent.classList).includes('shaka-overflow-menu')) {
  32. this.playbackRateMark = shaka.util.Dom.createHTMLElement('span');
  33. this.playbackRateMark.classList.add('shaka-overflow-playback-rate-mark');
  34. this.button.appendChild(this.playbackRateMark);
  35. }
  36. this.eventManager.listen(
  37. this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
  38. this.updateLocalizedStrings_();
  39. });
  40. this.eventManager.listen(
  41. this.localization, shaka.ui.Localization.LOCALE_CHANGED, () => {
  42. this.updateLocalizedStrings_();
  43. });
  44. this.eventManager.listen(this.player, 'loaded', () => {
  45. this.updatePlaybackRateSelection_();
  46. });
  47. this.eventManager.listen(this.player, 'ratechange', () => {
  48. this.updatePlaybackRateSelection_();
  49. });
  50. // Set up all the strings in the user's preferred language.
  51. this.updateLocalizedStrings_();
  52. this.addPlaybackRates_();
  53. this.updatePlaybackRateSelection_();
  54. }
  55. /**
  56. * @private
  57. */
  58. updateLocalizedStrings_() {
  59. const LocIds = shaka.ui.Locales.Ids;
  60. this.backButton.ariaLabel = this.localization.resolve(LocIds.BACK);
  61. this.button.ariaLabel = this.localization.resolve(LocIds.PLAYBACK_RATE);
  62. this.nameSpan.textContent = this.localization.resolve(LocIds.PLAYBACK_RATE);
  63. this.backSpan.textContent = this.localization.resolve(LocIds.PLAYBACK_RATE);
  64. }
  65. /**
  66. * Update checkmark icon and related class and attribute for the chosen rate
  67. * button.
  68. * @private
  69. */
  70. updatePlaybackRateSelection_() {
  71. const rate = this.player.getPlaybackRate();
  72. // Remove the old checkmark icon and related tags and classes if it exists.
  73. const checkmarkIcon = shaka.ui.Utils.getDescendantIfExists(
  74. this.menu, 'material-icons-round shaka-chosen-item');
  75. if (checkmarkIcon) {
  76. const previouslySelectedButton = checkmarkIcon.parentElement;
  77. previouslySelectedButton.removeAttribute('aria-selected');
  78. const previouslySelectedSpan =
  79. previouslySelectedButton.getElementsByTagName('span')[0];
  80. previouslySelectedSpan.classList.remove('shaka-chosen-item');
  81. previouslySelectedButton.removeChild(checkmarkIcon);
  82. }
  83. // Find the button that represents the newly selected playback rate.
  84. // Add the checkmark icon, related tags and classes to the newly selected
  85. // button.
  86. const span = Array.from(this.menu.querySelectorAll('span')).find((el) => {
  87. return el.textContent == (rate + 'x');
  88. });
  89. if (span) {
  90. const button = span.parentElement;
  91. button.appendChild(shaka.ui.Utils.checkmarkIcon());
  92. button.ariaSelected = 'true';
  93. span.classList.add('shaka-chosen-item');
  94. }
  95. // Set the label to display the current playback rate in the overflow menu,
  96. // in the format of '1x', '1.5x', etc.
  97. this.currentSelection.textContent = rate + 'x';
  98. this.button.setAttribute('shaka-status', rate + 'x');
  99. if (this.playbackRateMark) {
  100. this.playbackRateMark.textContent = rate + 'x';
  101. }
  102. }
  103. /** @private */
  104. addPlaybackRates_() {
  105. for (const rate of this.controls.getConfig().playbackRates) {
  106. const button = shaka.util.Dom.createButton();
  107. const span = shaka.util.Dom.createHTMLElement('span');
  108. span.textContent = rate + 'x';
  109. button.appendChild(span);
  110. this.eventManager.listen(button, 'click', () => {
  111. if (rate == this.video.defaultPlaybackRate) {
  112. this.player.cancelTrickPlay();
  113. } else {
  114. this.player.trickPlay(rate, /* useTrickPlayTrack= */ false);
  115. }
  116. });
  117. this.menu.appendChild(button);
  118. }
  119. shaka.ui.Utils.focusOnTheChosenItem(this.menu);
  120. }
  121. };
  122. /**
  123. * @implements {shaka.extern.IUIElement.Factory}
  124. * @final
  125. */
  126. shaka.ui.PlaybackRateSelection.Factory = class {
  127. /** @override */
  128. create(rootElement, controls) {
  129. return new shaka.ui.PlaybackRateSelection(rootElement, controls);
  130. }
  131. };
  132. shaka.ui.OverflowMenu.registerElement(
  133. 'playback_rate', new shaka.ui.PlaybackRateSelection.Factory());
  134. shaka.ui.Controls.registerElement(
  135. 'playback_rate', new shaka.ui.PlaybackRateSelection.Factory());