Source: ui/ad_statistics_button.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.ui.AdStatisticsButton');
  7. goog.require('shaka.log');
  8. goog.require('shaka.ads.Utils');
  9. goog.require('shaka.ui.ContextMenu');
  10. goog.require('shaka.ui.Controls');
  11. goog.require('shaka.ui.Element');
  12. goog.require('shaka.ui.Enums');
  13. goog.require('shaka.ui.Locales');
  14. goog.require('shaka.ui.Localization');
  15. goog.require('shaka.ui.OverflowMenu');
  16. goog.require('shaka.ui.Utils');
  17. goog.require('shaka.util.Dom');
  18. goog.require('shaka.util.Timer');
  19. goog.requireType('shaka.ui.Controls');
  20. /**
  21. * @extends {shaka.ui.Element}
  22. * @final
  23. * @export
  24. */
  25. shaka.ui.AdStatisticsButton = class extends shaka.ui.Element {
  26. /**
  27. * @param {!HTMLElement} parent
  28. * @param {!shaka.ui.Controls} controls
  29. */
  30. constructor(parent, controls) {
  31. super(parent, controls);
  32. /** @private {!HTMLButtonElement} */
  33. this.button_ = shaka.util.Dom.createButton();
  34. this.button_.classList.add('shaka-ad-statistics-button');
  35. /** @private {!HTMLElement} */
  36. this.icon_ = shaka.util.Dom.createHTMLElement('i');
  37. this.icon_.classList.add('material-icons-round');
  38. this.icon_.textContent =
  39. shaka.ui.Enums.MaterialDesignIcons.STATISTICS_ON;
  40. this.button_.appendChild(this.icon_);
  41. const label = shaka.util.Dom.createHTMLElement('label');
  42. label.classList.add('shaka-overflow-button-label');
  43. /** @private {!HTMLElement} */
  44. this.nameSpan_ = shaka.util.Dom.createHTMLElement('span');
  45. label.appendChild(this.nameSpan_);
  46. /** @private {!HTMLElement} */
  47. this.stateSpan_ = shaka.util.Dom.createHTMLElement('span');
  48. this.stateSpan_.classList.add('shaka-current-selection-span');
  49. label.appendChild(this.stateSpan_);
  50. this.button_.appendChild(label);
  51. this.parent.appendChild(this.button_);
  52. /** @private {!HTMLElement} */
  53. this.container_ = shaka.util.Dom.createHTMLElement('div');
  54. this.container_.classList.add('shaka-no-propagation');
  55. this.container_.classList.add('shaka-show-controls-on-mouse-over');
  56. this.container_.classList.add('shaka-ad-statistics-container');
  57. this.container_.classList.add('shaka-hidden');
  58. const controlsContainer = this.controls.getControlsContainer();
  59. controlsContainer.appendChild(this.container_);
  60. /** @private {!Array} */
  61. this.statisticsList_ = [];
  62. /** @private {!Object.<string, (number|!Array.<number>)>} */
  63. this.currentStats_ = this.adManager.getStats();
  64. /** @private {!Object.<string, HTMLElement>} */
  65. this.displayedElements_ = {};
  66. const parseLoadTimes = (name) => {
  67. let totalTime = 0;
  68. const loadTimes =
  69. /** @type {!Array.<number>} */ (this.currentStats_[name]);
  70. for (const loadTime of loadTimes) {
  71. totalTime += parseFloat(loadTime);
  72. }
  73. return totalTime;
  74. };
  75. const showNumber = (name) => {
  76. return this.currentStats_[name];
  77. };
  78. /** @private {!Object.<string, function(string):string>} */
  79. this.parseFrom_ = {
  80. 'loadTimes': parseLoadTimes,
  81. 'averageLoadTime': showNumber,
  82. 'started': showNumber,
  83. 'playedCompletely': showNumber,
  84. 'skipped': showNumber,
  85. 'errors': showNumber,
  86. };
  87. /** @private {shaka.util.Timer} */
  88. this.timer_ = new shaka.util.Timer(() => {
  89. this.onTimerTick_();
  90. });
  91. this.updateLocalizedStrings_();
  92. this.loadContainer_();
  93. this.eventManager.listen(
  94. this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
  95. this.updateLocalizedStrings_();
  96. });
  97. this.eventManager.listen(
  98. this.localization, shaka.ui.Localization.LOCALE_CHANGED, () => {
  99. this.updateLocalizedStrings_();
  100. });
  101. this.eventManager.listen(this.button_, 'click', () => {
  102. this.onClick_();
  103. this.updateLocalizedStrings_();
  104. });
  105. this.eventManager.listen(this.player, 'loading', () => {
  106. shaka.ui.Utils.setDisplay(this.button_, false);
  107. });
  108. this.eventManager.listen(
  109. this.adManager, shaka.ads.Utils.AD_STARTED, () => {
  110. shaka.ui.Utils.setDisplay(this.button_, true);
  111. });
  112. }
  113. /** @private */
  114. onClick_() {
  115. shaka.ui.Utils.setDisplay(this.parent, false);
  116. if (this.container_.classList.contains('shaka-hidden')) {
  117. this.icon_.textContent =
  118. shaka.ui.Enums.MaterialDesignIcons.STATISTICS_OFF;
  119. this.timer_.tickEvery(0.1);
  120. shaka.ui.Utils.setDisplay(this.container_, true);
  121. } else {
  122. this.icon_.textContent =
  123. shaka.ui.Enums.MaterialDesignIcons.STATISTICS_ON;
  124. this.timer_.stop();
  125. shaka.ui.Utils.setDisplay(this.container_, false);
  126. }
  127. }
  128. /** @private */
  129. updateLocalizedStrings_() {
  130. const LocIds = shaka.ui.Locales.Ids;
  131. this.nameSpan_.textContent =
  132. this.localization.resolve(LocIds.AD_STATISTICS);
  133. this.button_.ariaLabel = this.localization.resolve(LocIds.AD_STATISTICS);
  134. const labelText = this.container_.classList.contains('shaka-hidden') ?
  135. LocIds.OFF : LocIds.ON;
  136. this.stateSpan_.textContent = this.localization.resolve(labelText);
  137. }
  138. /** @private */
  139. generateComponent_(name) {
  140. const section = shaka.util.Dom.createHTMLElement('div');
  141. const label = shaka.util.Dom.createHTMLElement('label');
  142. label.textContent = name + ':';
  143. section.appendChild(label);
  144. const value = shaka.util.Dom.createHTMLElement('span');
  145. value.textContent = this.parseFrom_[name](name);
  146. section.appendChild(value);
  147. this.displayedElements_[name] = value;
  148. return section;
  149. }
  150. /** @private */
  151. loadContainer_() {
  152. for (const name of this.controls.getConfig().adStatisticsList) {
  153. if (name in this.currentStats_) {
  154. this.container_.appendChild(this.generateComponent_(name));
  155. this.statisticsList_.push(name);
  156. } else {
  157. shaka.log.alwaysWarn('Unrecognized ad statistic element:', name);
  158. }
  159. }
  160. }
  161. /** @private */
  162. onTimerTick_() {
  163. this.currentStats_ = this.adManager.getStats();
  164. for (const name of this.statisticsList_) {
  165. this.displayedElements_[name].textContent =
  166. this.parseFrom_[name](name);
  167. }
  168. }
  169. /** @override */
  170. release() {
  171. this.timer_.stop();
  172. this.timer_ = null;
  173. super.release();
  174. }
  175. };
  176. /**
  177. * @implements {shaka.extern.IUIElement.Factory}
  178. * @final
  179. */
  180. shaka.ui.AdStatisticsButton.Factory = class {
  181. /** @override */
  182. create(rootElement, controls) {
  183. return new shaka.ui.AdStatisticsButton(rootElement, controls);
  184. }
  185. };
  186. shaka.ui.OverflowMenu.registerElement(
  187. 'ad_statistics', new shaka.ui.AdStatisticsButton.Factory());
  188. shaka.ui.ContextMenu.registerElement(
  189. 'ad_statistics', new shaka.ui.AdStatisticsButton.Factory());