Source: ui/presentation_time.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.ui.PresentationTimeTracker');
  7. goog.require('shaka.ads.AdManager');
  8. goog.require('shaka.ui.Controls');
  9. goog.require('shaka.ui.Element');
  10. goog.require('shaka.ui.Locales');
  11. goog.require('shaka.ui.Utils');
  12. goog.require('shaka.util.Dom');
  13. /**
  14. * @extends {shaka.ui.Element}
  15. * @final
  16. * @export
  17. */
  18. shaka.ui.PresentationTimeTracker = class extends shaka.ui.Element {
  19. /**
  20. * @param {!HTMLElement} parent
  21. * @param {!shaka.ui.Controls} controls
  22. */
  23. constructor(parent, controls) {
  24. super(parent, controls);
  25. /** @type {!HTMLButtonElement} */
  26. this.currentTime_ = shaka.util.Dom.createButton();
  27. this.currentTime_.classList.add('shaka-current-time');
  28. this.setValue_('0:00');
  29. this.parent.appendChild(this.currentTime_);
  30. this.eventManager.listen(this.currentTime_, 'click', () => {
  31. // Jump to LIVE if the user clicks on the current time.
  32. if (this.player.isLive()) {
  33. this.video.currentTime = this.player.seekRange().end;
  34. }
  35. });
  36. this.eventManager.listen(this.player, 'loading', () => {
  37. shaka.ui.Utils.setDisplay(this.currentTime_, true);
  38. });
  39. this.eventManager.listen(this.controls, 'timeandseekrangeupdated', () => {
  40. this.updateTime_();
  41. });
  42. this.eventManager.listen(this.player, 'trackschanged', () => {
  43. this.onTracksChanged_();
  44. });
  45. this.eventManager.listen(
  46. this.adManager, shaka.ads.AdManager.AD_STARTED, () => {
  47. shaka.ui.Utils.setDisplay(this.currentTime_, false);
  48. });
  49. this.eventManager.listen(
  50. this.adManager, shaka.ads.AdManager.AD_STOPPED, () => {
  51. shaka.ui.Utils.setDisplay(this.currentTime_, true);
  52. });
  53. }
  54. /** @private */
  55. setValue_(value) {
  56. // To avoid constant updates to the DOM, which makes debugging more
  57. // difficult, only set the value if it has changed. If we don't do this
  58. // check, the DOM updates constantly, this element flashes in the debugger
  59. // in Chrome, and you can't make changes in the CSS panel.
  60. if (value != this.currentTime_.textContent) {
  61. this.currentTime_.textContent = value;
  62. }
  63. }
  64. /** @private */
  65. updateTime_() {
  66. const isSeeking = this.controls.isSeeking();
  67. let displayTime = this.controls.getDisplayTime();
  68. const seekRange = this.player.seekRange();
  69. const seekRangeSize = seekRange.end - seekRange.start;
  70. const Utils = shaka.ui.Utils;
  71. if (this.player.isLive()) {
  72. // The amount of time we are behind the live edge.
  73. const behindLive = Math.floor(seekRange.end - displayTime);
  74. displayTime = Math.max(0, behindLive);
  75. const showHour = seekRangeSize >= 3600;
  76. // Consider "LIVE" when less than 1 second behind the live-edge. Always
  77. // show the full time string when seeking, including the leading '-';
  78. // otherwise, the time string "flickers" near the live-edge.
  79. // The button should only be clickable when it's live stream content, and
  80. // the current play time is behind live edge.
  81. if ((displayTime >= 1) || isSeeking) {
  82. this.setValue_('- ' + Utils.buildTimeString(displayTime, showHour));
  83. this.currentTime_.disabled = false;
  84. } else {
  85. this.setValue_(this.localization.resolve(shaka.ui.Locales.Ids.LIVE));
  86. this.currentTime_.disabled = true;
  87. }
  88. } else {
  89. const showHour = seekRangeSize >= 3600;
  90. const currentTime = Math.max(0, displayTime - seekRange.start);
  91. let value = Utils.buildTimeString(currentTime, showHour);
  92. if (seekRangeSize) {
  93. value += ' / ' + Utils.buildTimeString(seekRangeSize, showHour);
  94. }
  95. this.setValue_(value);
  96. this.currentTime_.disabled = true;
  97. }
  98. }
  99. /**
  100. * Set the aria label to be 'Live' when the content is live stream.
  101. * @private
  102. */
  103. onTracksChanged_() {
  104. if (this.player.isLive()) {
  105. const ariaLabel = shaka.ui.Locales.Ids.SKIP_TO_LIVE;
  106. this.currentTime_.ariaLabel = this.localization.resolve(ariaLabel);
  107. }
  108. }
  109. };
  110. /**
  111. * @implements {shaka.extern.IUIElement.Factory}
  112. * @final
  113. */
  114. shaka.ui.PresentationTimeTracker.Factory = class {
  115. /** @override */
  116. create(rootElement, controls) {
  117. return new shaka.ui.PresentationTimeTracker(rootElement, controls);
  118. }
  119. };
  120. shaka.ui.Controls.registerElement(
  121. 'time_and_duration', new shaka.ui.PresentationTimeTracker.Factory());