summaryrefslogtreecommitdiff
path: root/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js')
-rw-r--r--extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js353
1 files changed, 353 insertions, 0 deletions
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js
new file mode 100644
index 00000000..0748ccd0
--- /dev/null
+++ b/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/mw.processEmbedPlayers.js
@@ -0,0 +1,353 @@
+/**
+ * Selector based embedPlayer processing
+ *
+ * @param {Function=}
+ * callback Optional Function to be called once video interfaces
+ * are ready
+ *
+ */
+
+( function( mw, $ ) { "use strict";
+
+mw.processEmbedPlayers = function( playerSet, callback ) {
+ mw.log( 'processEmbedPlayers:: playerSet: ', playerSet);
+ // The player id list container
+ var playerIdList = [];
+
+ // Check if the selected player set is ready if ready issue the parent callback
+ var areSelectedPlayersReady = function(){
+ var playersLoaded = true;
+ $.each( playerIdList, function(inx, playerId){
+ if( ! $( '#' + playerId )[0].playerReadyFlag ){
+ playersLoaded = false;
+ return false;
+ }
+ })
+ if( playersLoaded ){
+ if( callback ){
+ callback();
+ }
+ }
+ }
+
+ /**
+ * Adds a player element for the embedPlayer to rewrite
+ *
+ * uses embedPlayer interface on audio / video elements uses mvPlayList
+ * interface on playlist elements
+ *
+ * Once a player interface is established the following chain of functions
+ * are called;
+ *
+ * _this.checkPlayerSources()
+ * _this.setupSourcePlayer()
+ * _this.updatePlaybackInterface()
+ * _this.selectedPlayer.load()
+ * _this.showPlayer()
+ *
+ * @param {Element}
+ * playerElement DOM element to be swapped
+ */
+ var addPlayerElement = function( playerElement ) {
+ var _this = this;
+ mw.log('EmbedPlayer:: addElement:: ' + playerElement.id );
+
+ // Be sure to "stop" the target ( Firefox 3x keeps playing
+ // the video even though its been removed from the DOM )
+ if( playerElement.pause ){
+ playerElement.pause();
+ }
+
+ // Allow modules to override the wait for metadata flag:
+ $( mw ).trigger( 'EmbedPlayerWaitForMetaCheck', playerElement );
+
+ // DOM *could* load height, width and duration eventually, in some browsers
+ // By default, don't bother waiting for this.
+ var waitForMeta = false;
+
+ // if a plugin has told us not to waitForMeta, don't
+ if ( playerElement.waitForMeta !== false ) {
+ // Check if we should wait for metadata, after all
+ waitForMeta = waitForMetaCheck( playerElement );
+ }
+
+ var ranPlayerSwapFlag = false;
+
+ // Local callback to runPlayer swap once playerElement has metadata
+ var runPlayerSwap = function () {
+ // Don't run player swap twice
+ if( ranPlayerSwapFlag ){
+ return ;
+ }
+ ranPlayerSwapFlag = true;
+ mw.log( "processEmbedPlayers::runPlayerSwap::" + $( playerElement ).attr('id') );
+
+ var playerInterface = new mw.EmbedPlayer( playerElement );
+ var inDomPlayer = swapEmbedPlayerElement( playerElement, playerInterface );
+
+ // IE/Edge with WebM components re-triggers autoplay after removal as well.
+ if( playerElement.pause ){
+ playerElement.pause();
+ }
+
+ // Trigger the EmbedPlayerNewPlayer for embedPlayer interface
+ mw.log("processEmbedPlayers::trigger:: EmbedPlayerNewPlayer " + inDomPlayer.id );
+
+ // Allow plugins to add bindings to the inDomPlayer
+ $( mw ).trigger ( 'EmbedPlayerNewPlayer', inDomPlayer );
+
+ // Add a player ready binding:
+ $( inDomPlayer ).bind( 'playerReady.swap', function(event, id){
+ $( inDomPlayer ).unbind( 'playerReady.swap' );
+ areSelectedPlayersReady();
+ });
+
+ //
+ // Allow modules to block player build out
+ //
+ // this is needed in cases where you need to do an asynchronous
+ // player interface setup. like iframes asynchronous announcing its ready for
+ // bindings that can affect player setup.
+ mw.log("EmbedPlayer::addPlayerElement :trigger startPlayerBuildOut:" + inDomPlayer.id );
+ $( '#' + inDomPlayer.id ).triggerQueueCallback( 'startPlayerBuildOut', function(){
+ // Issue the checkPlayerSources call to the new player
+ // interface: make sure to use the element that is in the DOM:
+ inDomPlayer.checkPlayerSources();
+ });
+ };
+
+ if( waitForMeta && mw.config.get('EmbedPlayer.WaitForMeta' ) ) {
+ mw.log('processEmbedPlayers::WaitForMeta ( video missing height (' +
+ $( playerElement ).attr('height') + '), width (' +
+ $( playerElement ).attr('width') + ') or duration: ' +
+ $( playerElement ).attr('duration')
+ );
+ $( playerElement ).bind( "loadedmetadata", runPlayerSwap );
+
+ // Time-out of 5 seconds ( maybe still playable but no timely metadata )
+ setTimeout( runPlayerSwap, 5000 );
+ return ;
+ } else {
+ runPlayerSwap();
+ return ;
+ }
+ };
+
+ /**
+ * Check if we should wait for metadata.
+ *
+ * @return true if the size is "likely" to be updated by waiting for metadata
+ * false if the size has been set via an attribute or is already loaded
+ */
+ var waitForMetaCheck = function( playerElement ){
+ var waitForMeta = false;
+
+ // Don't wait for metadata for non html5 media elements
+ if( !playerElement ){
+ return false;
+ }
+ if( !playerElement.tagName || ( playerElement.tagName.toLowerCase() != 'audio' && playerElement.tagName.toLowerCase() != 'video' ) ){
+ return false;
+ }
+ // If we don't have a native player don't wait for metadata
+ if( !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'oggNative') &&
+ !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'webmNative') &&
+ !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'h264Native' ) &&
+ !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'appleVdnPlayer' ) )
+ {
+ return false;
+ }
+
+
+ var width = $( playerElement ).css( 'width' );
+ var height = $( playerElement ).css( 'height' );
+ // Css video defaults ( firefox )
+ if( $( playerElement ).css( 'width' ) == '300px' &&
+ $( playerElement ).css( 'height' ) == '150px'
+ ){
+ waitForMeta = true;
+ } else {
+ // Check if we should wait for duration:
+ if( $( playerElement ).attr( 'duration') ||
+ $( playerElement ).attr( 'durationHint') ||
+ $( playerElement ).attr('data-durationhint')
+ ){
+ // height, width and duration set; do not wait for meta data:
+ return false;
+ } else {
+ waitForMeta = true;
+ }
+ }
+
+ // Firefox ~ sometimes~ gives -1 for unloaded media
+ if ( $(playerElement).attr( 'width' ) == -1 || $(playerElement).attr( 'height' ) == -1 ) {
+ waitForMeta = true;
+ }
+
+ // Google Chrome / safari gives 0 width height for unloaded media
+ if( $(playerElement).attr( 'width' ) === 0 ||
+ $(playerElement).attr( 'height' ) === 0
+ ) {
+ waitForMeta = true;
+ }
+
+ // Firefox default width height is ~sometimes~ 150 / 300
+ if( playerElement.height == 150 && playerElement.width == 300 ){
+ waitForMeta = true;
+ }
+
+ // Make sure we have a src attribute or source child
+ // ( i.e not a video tag to be dynamically populated or looked up from
+ // xml resource description )
+ if( waitForMeta &&
+ (
+ $( playerElement ).attr('src') ||
+ $( playerElement ).find("source[src]").length !== 0
+ )
+ ) {
+ // Detect src type ( if no type set )
+ return true;
+ } else {
+ // playerElement is not likely to update its meta data ( no src )
+ return false;
+ }
+ };
+
+ /**
+ * swapEmbedPlayerElement
+ *
+ * Takes a video element as input and swaps it out with an embed player interface
+ *
+ * @param {Element}
+ * targetElement Element to be swapped
+ * @param {Object}
+ * playerInterface Interface to swap into the target element
+ */
+ var swapEmbedPlayerElement = function( targetElement, playerInterface ) {
+ mw.log( 'processEmbedPlayers::swapEmbedPlayerElement: ' + targetElement.id );
+ // Create a new element to swap the player interface into
+ var swapPlayerElement = document.createElement('div');
+
+ // Add a class that identifies all embedPlayers:
+ $( swapPlayerElement ).addClass( 'mwEmbedPlayer' );
+
+ // Get properties / methods from playerInterface:
+ for ( var method in playerInterface ) {
+ if ( method != 'readyState' ) { // readyState crashes IE ( don't include )
+ swapPlayerElement[ method ] = playerInterface[ method ];
+ }
+ }
+ // copy over css text:
+ swapPlayerElement.style.cssText = targetElement.style.cssText;
+ // player element must always be relative to host video and image layout
+ swapPlayerElement.style.position = 'relative';
+
+ // Copy any data attributes from the target player element over to the swapPlayerElement
+ var dataAttributes = mw.config.get("EmbedPlayer.DataAttributes");
+ if( dataAttributes ){
+ $.each( dataAttributes, function( attrName, na ){
+ if( $( targetElement ).data( attrName ) ){
+ $( swapPlayerElement ).data( attrName, $( targetElement ).data( attrName ) );
+ }
+ });
+ }
+ // Check for Persistent native player ( should keep the video embed around )
+ if( playerInterface.isPersistentNativePlayer()
+ ||
+ // Also check for native controls on a video or audio tag
+ ( playerInterface.useNativePlayerControls()
+ &&
+ ( targetElement.nodeName == 'video' || targetElement.nodeName == 'audio' )
+ )
+ ) {
+
+ $( targetElement )
+ .attr( 'id', playerInterface.pid )
+ .addClass( 'nativeEmbedPlayerPid' )
+ .show()
+ .after(
+ $( swapPlayerElement ).css( 'display', 'none' )
+ );
+
+ } else {
+ $( targetElement ).replaceWith( swapPlayerElement );
+ }
+
+ // If we don't already have a loadSpiner add one:
+ if( $('#loadingSpinner_' + playerInterface.id ).length == 0 && $.client.profile().name !== 'firefox' ){
+ if( playerInterface.useNativePlayerControls() || playerInterface.isPersistentNativePlayer() ) {
+ var $spinner = $( targetElement )
+ .getAbsoluteOverlaySpinner();
+ }else{
+ var $spinner = $( swapPlayerElement ).getAbsoluteOverlaySpinner();
+ }
+ $spinner.attr('id', 'loadingSpinner_' + playerInterface.id );
+ }
+ return swapPlayerElement;
+ };
+
+ // Add a loader for <div /> embed player rewrites:
+ $( playerSet ).each( function( index, playerElement) {
+
+ // Make sure the playerElement has an id:
+ if( !$( playerElement ).attr('id') ){
+ $( playerElement ).attr( "id", 'mwe_vid' + ( index ) );
+ }
+ // Add the player Id to the playerIdList
+ playerIdList.push( $( playerElement ).attr( "id") );
+
+ // If we are dynamically embedding on a "div" check if we can
+ // add a poster image behind the loader:
+ if( playerElement.nodeName.toLowerCase() == 'div'
+ &&
+ $(playerElement).attr( 'poster' ) )
+ {
+ var posterSrc = $(playerElement).attr( 'poster' );
+
+ // Set image size:
+ var width = $( playerElement ).width();
+ var height = $( playerElement ).height();
+ if( !width ){
+ var width = '100%';
+ }
+ if( !height ){
+ var height = '100%';
+ }
+
+ mw.log('EmbedPlayer:: set loading background: ' + posterSrc);
+ $( playerElement ).append(
+ $( '<img />' )
+ .attr( 'src', posterSrc)
+ .css({
+ 'position' : 'absolute',
+ 'width' : width,
+ 'height' : height
+ })
+ );
+ }
+ });
+
+ // Make sure we have user preference setup for setting preferences on video selection
+ var addedPlayersFlag = false;
+ mw.log("processEmbedPlayers:: Do: " + $( playerSet ).length + ' players ');
+ // Add each selected element to the player manager:
+ $( playerSet ).each( function( index, playerElement) {
+ // Make sure the video tag was not generated by our library:
+ if( $( playerElement ).hasClass( 'nativeEmbedPlayerPid' ) ){
+ $( '#loadingSpinner_' + $( playerElement ).attr('id') ).remove();
+ mw.log( 'processEmbedPlayers::$.embedPlayer skip embedPlayer gennerated video: ' + playerElement );
+ } else {
+ addedPlayersFlag = true;
+ // Add the player
+ addPlayerElement( playerElement );
+ }
+ });
+ if( !addedPlayersFlag ){
+ // Run the callback directly if no players were added
+ if( callback ){
+ callback();
+ }
+ }
+};
+
+})( mw, jQuery );