You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
5.3 KiB

1 year ago
  1. /* global _wpmejsSettings, MediaElementPlayer */
  2. (function ($, _, Backbone) {
  3. 'use strict';
  4. /** @namespace wp */
  5. window.wp = window.wp || {};
  6. var WPPlaylistView = Backbone.View.extend(/** @lends WPPlaylistView.prototype */{
  7. /**
  8. * @constructs
  9. *
  10. * @param {Object} options The options to create this playlist view with.
  11. * @param {Object} options.metadata The metadata
  12. */
  13. initialize : function (options) {
  14. this.index = 0;
  15. this.settings = {};
  16. this.data = options.metadata || $.parseJSON( this.$('script.wp-playlist-script').html() );
  17. this.playerNode = this.$( this.data.type );
  18. this.tracks = new Backbone.Collection( this.data.tracks );
  19. this.current = this.tracks.first();
  20. if ( 'audio' === this.data.type ) {
  21. this.currentTemplate = wp.template( 'wp-playlist-current-item' );
  22. this.currentNode = this.$( '.wp-playlist-current-item' );
  23. }
  24. this.renderCurrent();
  25. if ( this.data.tracklist ) {
  26. this.itemTemplate = wp.template( 'wp-playlist-item' );
  27. this.playingClass = 'wp-playlist-playing';
  28. this.renderTracks();
  29. }
  30. this.playerNode.attr( 'src', this.current.get( 'src' ) );
  31. _.bindAll( this, 'bindPlayer', 'bindResetPlayer', 'setPlayer', 'ended', 'clickTrack' );
  32. if ( ! _.isUndefined( window._wpmejsSettings ) ) {
  33. this.settings = _.clone( _wpmejsSettings );
  34. }
  35. this.settings.success = this.bindPlayer;
  36. this.setPlayer();
  37. },
  38. bindPlayer : function (mejs) {
  39. this.mejs = mejs;
  40. this.mejs.addEventListener( 'ended', this.ended );
  41. },
  42. bindResetPlayer : function (mejs) {
  43. this.bindPlayer( mejs );
  44. this.playCurrentSrc();
  45. },
  46. setPlayer: function (force) {
  47. if ( this.player ) {
  48. this.player.pause();
  49. this.player.remove();
  50. this.playerNode = this.$( this.data.type );
  51. }
  52. if (force) {
  53. this.playerNode.attr( 'src', this.current.get( 'src' ) );
  54. this.settings.success = this.bindResetPlayer;
  55. }
  56. // This is also our bridge to the outside world.
  57. this.player = new MediaElementPlayer( this.playerNode.get(0), this.settings );
  58. },
  59. playCurrentSrc : function () {
  60. this.renderCurrent();
  61. this.mejs.setSrc( this.playerNode.attr( 'src' ) );
  62. this.mejs.load();
  63. this.mejs.play();
  64. },
  65. renderCurrent : function () {
  66. var dimensions, defaultImage = 'wp-includes/images/media/video.png';
  67. if ( 'video' === this.data.type ) {
  68. if ( this.data.images && this.current.get( 'image' ) && -1 === this.current.get( 'image' ).src.indexOf( defaultImage ) ) {
  69. this.playerNode.attr( 'poster', this.current.get( 'image' ).src );
  70. }
  71. dimensions = this.current.get( 'dimensions' );
  72. if ( dimensions && dimensions.resized ) {
  73. this.playerNode.attr( dimensions.resized );
  74. }
  75. } else {
  76. if ( ! this.data.images ) {
  77. this.current.set( 'image', false );
  78. }
  79. this.currentNode.html( this.currentTemplate( this.current.toJSON() ) );
  80. }
  81. },
  82. renderTracks : function () {
  83. var self = this, i = 1, tracklist = $( '<div class="wp-playlist-tracks"></div>' );
  84. this.tracks.each(function (model) {
  85. if ( ! self.data.images ) {
  86. model.set( 'image', false );
  87. }
  88. model.set( 'artists', self.data.artists );
  89. model.set( 'index', self.data.tracknumbers ? i : false );
  90. tracklist.append( self.itemTemplate( model.toJSON() ) );
  91. i += 1;
  92. });
  93. this.$el.append( tracklist );
  94. this.$( '.wp-playlist-item' ).eq(0).addClass( this.playingClass );
  95. },
  96. events : {
  97. 'click .wp-playlist-item' : 'clickTrack',
  98. 'click .wp-playlist-next' : 'next',
  99. 'click .wp-playlist-prev' : 'prev'
  100. },
  101. clickTrack : function (e) {
  102. e.preventDefault();
  103. this.index = this.$( '.wp-playlist-item' ).index( e.currentTarget );
  104. this.setCurrent();
  105. },
  106. ended : function () {
  107. if ( this.index + 1 < this.tracks.length ) {
  108. this.next();
  109. } else {
  110. this.index = 0;
  111. this.setCurrent();
  112. }
  113. },
  114. next : function () {
  115. this.index = this.index + 1 >= this.tracks.length ? 0 : this.index + 1;
  116. this.setCurrent();
  117. },
  118. prev : function () {
  119. this.index = this.index - 1 < 0 ? this.tracks.length - 1 : this.index - 1;
  120. this.setCurrent();
  121. },
  122. loadCurrent : function () {
  123. var last = this.playerNode.attr( 'src' ) && this.playerNode.attr( 'src' ).split('.').pop(),
  124. current = this.current.get( 'src' ).split('.').pop();
  125. this.mejs && this.mejs.pause();
  126. if ( last !== current ) {
  127. this.setPlayer( true );
  128. } else {
  129. this.playerNode.attr( 'src', this.current.get( 'src' ) );
  130. this.playCurrentSrc();
  131. }
  132. },
  133. setCurrent : function () {
  134. this.current = this.tracks.at( this.index );
  135. if ( this.data.tracklist ) {
  136. this.$( '.wp-playlist-item' )
  137. .removeClass( this.playingClass )
  138. .eq( this.index )
  139. .addClass( this.playingClass );
  140. }
  141. this.loadCurrent();
  142. }
  143. });
  144. /**
  145. * Initialize media playlists in the document.
  146. *
  147. * Only initializes new playlists not previously-initialized.
  148. *
  149. * @since 4.9.3
  150. * @return {void}
  151. */
  152. function initialize() {
  153. $( '.wp-playlist:not(:has(.mejs-container))' ).each( function() {
  154. new WPPlaylistView( { el: this } );
  155. } );
  156. }
  157. /**
  158. * Expose the API publicly on window.wp.playlist.
  159. *
  160. * @namespace wp.playlist
  161. * @since 4.9.3
  162. * @type {object}
  163. */
  164. window.wp.playlist = {
  165. initialize: initialize
  166. };
  167. $( document ).ready( initialize );
  168. window.WPPlaylistView = WPPlaylistView;
  169. }(jQuery, _, Backbone));