chapters-button.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. 'use strict';
  2. exports.__esModule = true;
  3. var _textTrackButton = require('./text-track-button.js');
  4. var _textTrackButton2 = _interopRequireDefault(_textTrackButton);
  5. var _component = require('../../component.js');
  6. var _component2 = _interopRequireDefault(_component);
  7. var _chaptersTrackMenuItem = require('./chapters-track-menu-item.js');
  8. var _chaptersTrackMenuItem2 = _interopRequireDefault(_chaptersTrackMenuItem);
  9. var _toTitleCase = require('../../utils/to-title-case.js');
  10. var _toTitleCase2 = _interopRequireDefault(_toTitleCase);
  11. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  12. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  13. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  14. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
  15. * @file chapters-button.js
  16. */
  17. /**
  18. * The button component for toggling and selecting chapters
  19. * Chapters act much differently than other text tracks
  20. * Cues are navigation vs. other tracks of alternative languages
  21. *
  22. * @extends TextTrackButton
  23. */
  24. var ChaptersButton = function (_TextTrackButton) {
  25. _inherits(ChaptersButton, _TextTrackButton);
  26. /**
  27. * Creates an instance of this class.
  28. *
  29. * @param {Player} player
  30. * The `Player` that this class should be attached to.
  31. *
  32. * @param {Object} [options]
  33. * The key/value store of player options.
  34. *
  35. * @param {Component~ReadyCallback} [ready]
  36. * The function to call when this function is ready.
  37. */
  38. function ChaptersButton(player, options, ready) {
  39. _classCallCheck(this, ChaptersButton);
  40. var _this = _possibleConstructorReturn(this, _TextTrackButton.call(this, player, options, ready));
  41. _this.el_.setAttribute('aria-label', 'Chapters Menu');
  42. return _this;
  43. }
  44. /**
  45. * Builds the default DOM `className`.
  46. *
  47. * @return {string}
  48. * The DOM `className` for this object.
  49. */
  50. ChaptersButton.prototype.buildCSSClass = function buildCSSClass() {
  51. return 'vjs-chapters-button ' + _TextTrackButton.prototype.buildCSSClass.call(this);
  52. };
  53. /**
  54. * Update the menu based on the current state of its items.
  55. *
  56. * @param {EventTarget~Event} [event]
  57. * An event that triggered this function to run.
  58. *
  59. * @listens TextTrackList#addtrack
  60. * @listens TextTrackList#removetrack
  61. * @listens TextTrackList#change
  62. */
  63. ChaptersButton.prototype.update = function update(event) {
  64. if (!this.track_ || event && (event.type === 'addtrack' || event.type === 'removetrack')) {
  65. this.setTrack(this.findChaptersTrack());
  66. }
  67. _TextTrackButton.prototype.update.call(this);
  68. };
  69. /**
  70. * Set the currently selected track for the chapters button.
  71. *
  72. * @param {TextTrack} track
  73. * The new track to select. Nothing will change if this is the currently selected
  74. * track.
  75. */
  76. ChaptersButton.prototype.setTrack = function setTrack(track) {
  77. if (this.track_ === track) {
  78. return;
  79. }
  80. if (!this.updateHandler_) {
  81. this.updateHandler_ = this.update.bind(this);
  82. }
  83. // here this.track_ refers to the old track instance
  84. if (this.track_) {
  85. var remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);
  86. if (remoteTextTrackEl) {
  87. remoteTextTrackEl.removeEventListener('load', this.updateHandler_);
  88. }
  89. this.track_ = null;
  90. }
  91. this.track_ = track;
  92. // here this.track_ refers to the new track instance
  93. if (this.track_) {
  94. this.track_.mode = 'hidden';
  95. var _remoteTextTrackEl = this.player_.remoteTextTrackEls().getTrackElementByTrack_(this.track_);
  96. if (_remoteTextTrackEl) {
  97. _remoteTextTrackEl.addEventListener('load', this.updateHandler_);
  98. }
  99. }
  100. };
  101. /**
  102. * Find the track object that is currently in use by this ChaptersButton
  103. *
  104. * @return {TextTrack|undefined}
  105. * The current track or undefined if none was found.
  106. */
  107. ChaptersButton.prototype.findChaptersTrack = function findChaptersTrack() {
  108. var tracks = this.player_.textTracks() || [];
  109. for (var i = tracks.length - 1; i >= 0; i--) {
  110. // We will always choose the last track as our chaptersTrack
  111. var track = tracks[i];
  112. if (track.kind === this.kind_) {
  113. return track;
  114. }
  115. }
  116. };
  117. /**
  118. * Get the caption for the ChaptersButton based on the track label. This will also
  119. * use the current tracks localized kind as a fallback if a label does not exist.
  120. *
  121. * @return {string}
  122. * The tracks current label or the localized track kind.
  123. */
  124. ChaptersButton.prototype.getMenuCaption = function getMenuCaption() {
  125. if (this.track_ && this.track_.label) {
  126. return this.track_.label;
  127. }
  128. return this.localize((0, _toTitleCase2['default'])(this.kind_));
  129. };
  130. /**
  131. * Create menu from chapter track
  132. *
  133. * @return {Menu}
  134. * New menu for the chapter buttons
  135. */
  136. ChaptersButton.prototype.createMenu = function createMenu() {
  137. this.options_.title = this.getMenuCaption();
  138. return _TextTrackButton.prototype.createMenu.call(this);
  139. };
  140. /**
  141. * Create a menu item for each text track
  142. *
  143. * @return {TextTrackMenuItem[]}
  144. * Array of menu items
  145. */
  146. ChaptersButton.prototype.createItems = function createItems() {
  147. var items = [];
  148. if (!this.track_) {
  149. return items;
  150. }
  151. var cues = this.track_.cues;
  152. if (!cues) {
  153. return items;
  154. }
  155. for (var i = 0, l = cues.length; i < l; i++) {
  156. var cue = cues[i];
  157. var mi = new _chaptersTrackMenuItem2['default'](this.player_, { track: this.track_, cue: cue });
  158. items.push(mi);
  159. }
  160. return items;
  161. };
  162. return ChaptersButton;
  163. }(_textTrackButton2['default']);
  164. /**
  165. * `kind` of TextTrack to look for to associate it with this menu.
  166. *
  167. * @type {string}
  168. * @private
  169. */
  170. ChaptersButton.prototype.kind_ = 'chapters';
  171. /**
  172. * The text that should display over the `ChaptersButton`s controls. Added for localization.
  173. *
  174. * @type {string}
  175. * @private
  176. */
  177. ChaptersButton.prototype.controlText_ = 'Chapters';
  178. _component2['default'].registerComponent('ChaptersButton', ChaptersButton);
  179. exports['default'] = ChaptersButton;