( function ( mw, $ ) { /** * Merge in the default video attributes supported by embedPlayer: */ mw.mergeConfig( 'EmbedPlayer.Attributes', { // A apiTitleKey for looking up subtitles, credits and related videos 'data-mwtitle': null, // The apiProvider where to lookup the title key 'data-mwprovider': null } ); // Add mediaWiki player support to target embedPlayer $( mw ).bind( 'EmbedPlayerNewPlayer', function ( event, embedPlayer ) { mw.addMediaWikiPlayerSupport( embedPlayer ); }); /** * Closure function wraps mediaWiki embedPlayer bindings */ mw.addMediaWikiPlayerSupport = function ( embedPlayer ) { var apiTitleKey, apiProvider, $creditsCache = false; // Set some local variables: if ( !embedPlayer['data-mwtitle'] ) { return false; } else { apiTitleKey = embedPlayer['data-mwtitle']; // legacy support ( set as attribute ) embedPlayer.apiTitleKey = apiTitleKey; } // Set local apiProvider via config if not defined apiProvider = embedPlayer['data-mwprovider']; if ( !apiProvider ) { apiProvider = mw.config.get( 'EmbedPlayer.ApiProvider' ); } /** * Loads mediaWiki sources for a given embedPlayer * @param {function} callback Function called once player sources have been added */ function loadPlayerSources( callback ) { // Setup the request var request = { 'prop': 'imageinfo', // In case the user added File: or Image: to the apiKey: 'titles': 'File:' + decodeURIComponent( apiTitleKey ).replace( /^(File:|Image:)/, '' ), 'iiprop': 'url|size|dimensions|metadata', 'iiurlwidth': embedPlayer.getWidth(), 'redirects': true // automatically resolve redirects }; // Run the request: mw.getJSON( mw.getApiProviderURL( apiProvider ), request, function ( data ) { var i, page, imageinfo; if ( data.query.pages ) { for ( i in data.query.pages ) { if ( i === '-1' ) { callback( false ); return ; } page = data.query.pages[i]; } } else { callback( false ); return ; } // Make sure we have imageinfo: if ( !page.imageinfo || !page.imageinfo[0] ) { callback( false ); return ; } imageinfo = page.imageinfo[0]; // TODO these should call public methods rather than update internals: // Update the poster embedPlayer.poster = imageinfo.thumburl; // Add the media src embedPlayer.mediaElement.tryAddSource( $( '' ) .attr( 'src', imageinfo.url ) .get( 0 ) ); // Set the duration if ( imageinfo.metadata[2].name === 'length' ) { embedPlayer.duration = imageinfo.metadata[2].value; } // Set the width height // Make sure we have an accurate aspect ratio if ( imageinfo.height !== 0 && imageinfo.width !== 0 ) { embedPlayer.height = Math.floor( embedPlayer.width * ( imageinfo.height / imageinfo.width ) ); } // Update the css for the player interface $( embedPlayer ).css( 'height', embedPlayer.height ); callback(); }); } /** * Build a clip credit from the resource wikiText page * * TODO parse the resource page template * * @param {String} resourceHTML Resource wiki text page contents */ function doCreditLine( resourceHTML, articleUrl ) { var authUrl, $page, $author, $authorText, $links, $date, $authorLink, imgSize = {}, // Get the title string ( again a "Title" like js object could help out here. ) titleStr = embedPlayer.apiTitleKey.replace( /_/g, ' ' ), // Setup the initial credits line: $creditLine = $( '
' ); // Add the title: $creditLine.append( $( '' ).html( mw.msg( 'mwe-embedplayer-credit-title', // get the link $( '
' ).append( $( '' ).attr( { 'href': articleUrl, 'title': titleStr } ) .text( titleStr ) )[0].innerHTML ) ) ); // Parse some data from the page info template if possible: $page = $( resourceHTML ); // Look for author: $author = $page.find( '#fileinfotpl_aut' ); if ( $author.length ) { // Get the real author sibling of fileinfotpl_aut $authorText = $author.next(); // Remove white space: $authorText.find( 'br' ).remove(); // Update link to be absolute per page url context: $links = $authorText.find( 'a' ); if ( $links.length ) { $links.each( function ( i, authorLink ) { $authorLink = $( authorLink ); authUrl = $authorLink.attr( 'href' ); authUrl = mw.absoluteUrl( authUrl, articleUrl ); $authorLink.attr( 'href', authUrl ); }); } $creditLine.append( $( '
' ), mw.msg( 'mwe-embedplayer-credit-author', $authorText.html() ) ); } // Look for date: $date = $page.find( '#fileinfotpl_date' ); if ( $date.length ) { // Get the real date sibling of fileinfotpl_date $date = $date.next(); // remove white space: $date.find( 'br' ).remove(); $creditLine.append( $( '
' ), mw.msg( 'mwe-embedplayer-credit-date', $date.html() ) ); } // Build out the image and credit line if ( embedPlayer.isAudio() ) { imgSize.height = imgSize.width = ( embedPlayer.controlBuilder.getOverlayWidth() < 250 ) ? 45 : 80; } else { imgSize.width = ( embedPlayer.controlBuilder.getOverlayWidth() < 250 ) ? 45 : 120; imgSize.height = Math.floor( imgSize.width * ( embedPlayer.getHeight() / embedPlayer.getWidth() ) ); } return $( '
' ).addClass( 'creditline' ) .append( $( '' ).attr( { 'href': articleUrl, 'title': titleStr } ).html( $( '' ).attr( { 'border': 0, 'src': embedPlayer.poster } ).css( imgSize ) ) ) .append( $creditLine ); } /** * Issues a request to populate the credits box */ function showCredits( $target, callback ) { var apiUrl, fileTitle, request; if ( $creditsCache ) { $target.html( $creditsCache ); callback( true ); return; } // Setup shortcuts: apiUrl = mw.getApiProviderURL( apiProvider ); fileTitle = 'File:' + decodeURIComponent( apiTitleKey ).replace( /^File:|^Image:/, ''); // Get the image page ( cache for 1 hour ) request = { 'action': 'parse', 'page': fileTitle, 'smaxage': 3600, 'maxage': 3600 }; mw.getJSON( apiUrl, request, function ( data ) { var descUrl = apiUrl.replace( 'api.php', 'index.php'); descUrl += '?title=' + encodeURIComponent( fileTitle ); if ( data && data.parse && data.parse.text && data.parse.text['*'] ) { // TODO improve provider 'concept' to support page title link $creditsCache = doCreditLine( data.parse.text['*'], descUrl ); } else { $creditsCache = doCreditLine( false, descUrl ); } $target.html( $creditsCache ); callback( true ); } ); } /** * Adds embedPlayer Bindings */ // Show credits when requested $( embedPlayer ).bindQueueCallback( 'showCredits', function ( $target, callback ) { if ( $target.data( 'playerId') !== embedPlayer.id ) { // bad event trigger return ; } // Only request the credits once: showCredits( $target, callback ); }); // Show credits on clip complete: $( embedPlayer ).bind( 'onEndedDone', function ( event, id ) { if ( embedPlayer.id !== id ) { // possible event trigger error. ( skip ) return ; } // dont show credits for audio elements, // seek to begining instead if ( embedPlayer.isAudio() ) { embedPlayer.setCurrentTime( 0 ); return ; } var cb = embedPlayer.controlBuilder; cb.checkMenuOverlay(); cb.showMenuOverlay(); cb.showMenuItem( 'credits' ); }); $( embedPlayer ).bind( 'showInlineDownloadLink', function () { // Add recommend HTML5 player if we have non-native playback: if ( embedPlayer.controlBuilder.checkNativeWarning( ) ) { embedPlayer.controlBuilder.addWarningBinding( 'EmbedPlayer.ShowNativeWarning', mw.msg( 'mwe-embedplayer-for_best_experience', $( '
' ).append( $( '' ).attr({ 'href': 'http://www.mediawiki.org/wiki/Extension:TimedMediaHandler/Client_download', 'target': '_new' }) )[0].innerHTML ), true ); } }); $( embedPlayer ).bind( 'TimedText_BuildCCMenu', function ( event, $menu, id ) { var _this, pageTitle, addTextPage, $li; if ( id !== embedPlayer.id ) { _this = $( '#' + id )[0].timedText; embedPlayer = _this.embedPlayer; } // Put in the "Make Transcript" link if config enabled and we have an api key if ( embedPlayer.apiTitleKey ) { // check if not already there: if ( $menu.find( '.add-timed-text' ).length ) { // add text link already present return ; } pageTitle = 'TimedText:' + decodeURIComponent( embedPlayer.apiTitleKey ).replace( /^File:|^Image:/, '' ); addTextPage = mw.getApiProviderURL( apiProvider ) .replace( 'api.php', 'index.php') + '?title=' + encodeURIComponent( pageTitle ); $li = $.getLineItem( mw.msg( 'mwe-timedtext-upload-timed-text'), 'script', function () { window.location = addTextPage; }); $li.addClass( 'add-timed-text') .find( 'a' ) .attr( { 'href': addTextPage, 'target': '_new' } ); $menu.append( $li ); } }); $( embedPlayer ).bindQueueCallback( 'checkPlayerSourcesEvent', function ( callback ) { // Only load source if none are available: if ( embedPlayer.mediaElement.sources.length === 0 ) { loadPlayerSources( callback ); } else { // No source to load, issue callback directly callback(); } } ); $( mw ).bindQueueCallback( 'TimedText_LoadTextSource', function ( source, callback ) { if ( !source.mwtitle || !source.mwprovider ) { callback(); return ; } // Load via api var apiUrl = mw.getApiProviderURL( source.mwprovider ), // Get the image page ( cache for 1 hour ) request = { 'action': 'parse', 'page': source.mwtitle, 'smaxage': 3600, 'maxage': 3600 }; mw.getJSON( apiUrl, request, function ( data ) { if ( data && data.parse && data.parse.text && data.parse.text['*'] ) { source.loaded = true; source.mimeType = 'text/mw-srt'; source.captions = source.getCaptions( data.parse.text['*'] ); callback(); } else { mw.log( 'Error: MediaWiki api error in getting timed text:', data ); callback(); } }); }); $( embedPlayer ).bind( 'getShareIframeSrc', function ( event, callback, id ) { if ( id !== embedPlayer.id ) { embedPlayer = $( '#' + id )[0]; } var iframeUrl = false; // Do a special check for wikimediacommons provider as a known shared reop if ( embedPlayer['data-mwprovider'] === 'wikimediacommons' ) { iframeUrl = '//commons.wikimedia.org/wiki/File:' + decodeURIComponent( embedPlayer.apiTitleKey ).replace( /^(File:|Image:)/, '' ); } else { // use the local wiki: if ( mw.config.get( 'wgServer' ) && mw.config.get( 'wgArticlePath' ) ) { iframeUrl = mw.config.get( 'wgServer' ) + mw.config.get( 'wgArticlePath' ).replace( /\$1/, 'File:' + decodeURIComponent( embedPlayer.apiTitleKey ).replace( /^(File:|Image:)/, '' ) ); } } if ( iframeUrl ) { iframeUrl += '?embedplayer=yes'; } callback( iframeUrl ); }); }; } )( mediaWiki, jQuery );