summaryrefslogtreecommitdiff
path: root/extensions/TimedMediaHandler/resources
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/TimedMediaHandler/resources')
-rw-r--r--extensions/TimedMediaHandler/resources/PopUpThumbVideo.css29
-rw-r--r--extensions/TimedMediaHandler/resources/download_sprite.pngbin0 -> 806 bytes
-rw-r--r--extensions/TimedMediaHandler/resources/embedPlayerIframe.css7
-rw-r--r--extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js67
-rw-r--r--extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js8
-rw-r--r--extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js90
-rw-r--r--extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js8
-rw-r--r--extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js380
-rw-r--r--extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js44
-rw-r--r--extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js46
-rw-r--r--extensions/TimedMediaHandler/resources/player_big_play_button.pngbin0 -> 987 bytes
-rw-r--r--extensions/TimedMediaHandler/resources/player_big_play_button_hover.pngbin0 -> 1022 bytes
-rw-r--r--extensions/TimedMediaHandler/resources/transcodeTable.css14
13 files changed, 693 insertions, 0 deletions
diff --git a/extensions/TimedMediaHandler/resources/PopUpThumbVideo.css b/extensions/TimedMediaHandler/resources/PopUpThumbVideo.css
new file mode 100644
index 00000000..3ba0572a
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/PopUpThumbVideo.css
@@ -0,0 +1,29 @@
+.PopUpMediaTransform a .play-btn-large{
+ position : absolute;
+ top: 50%;
+ left : 50%;
+ width: 70px;
+ height: 53px;
+ margin-left: -35px;
+ margin-top: -25px;
+ /* @embed */
+ background-image:url('player_big_play_button.png');
+}
+.PopUpMediaTransform a .play-btn-large :hover{
+ /* @embed */
+ background-image:url('player_big_play_button_hover.png');
+}
+.PopUpMediaTransform {
+ position : relative;
+ display: inline-block;
+}
+/* Should hopefully be only visible to screen readers */
+.mw-tmh-playtext {
+ display: block;
+ height: 0;
+ overflow: hidden;
+}
+
+li.gallerybox div.thumb div.PopUpMediaTransform {
+ margin: 0 auto;
+}
diff --git a/extensions/TimedMediaHandler/resources/download_sprite.png b/extensions/TimedMediaHandler/resources/download_sprite.png
new file mode 100644
index 00000000..541d4a99
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/download_sprite.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/resources/embedPlayerIframe.css b/extensions/TimedMediaHandler/resources/embedPlayerIframe.css
new file mode 100644
index 00000000..eb6e9003
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/embedPlayerIframe.css
@@ -0,0 +1,7 @@
+body {
+ margin-left: 0px;
+ margin-top: 0px;
+ margin-right: 0px;
+ margin-bottom: 0px;
+ overflow: hidden;
+}
diff --git a/extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js b/extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js
new file mode 100644
index 00000000..af3fd9f5
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/ext.tmh.OgvJsSupport.js
@@ -0,0 +1,67 @@
+( function( $, mw ) {
+
+ var support = mw.OgvJsSupport = {
+ /**
+ * Ensure that the OGVPlayer class is loaded before continuing.
+ *
+ * @return jQuery.Deferred
+ */
+ loadOgvJs: function() {
+ return $.Deferred( function( deferred ) {
+ if ( typeof OGVPlayer === 'undefined' ) {
+ mw.loader.using( 'ext.tmh.OgvJs', function() {
+ OGVLoader.base = support.basePath();
+ deferred.resolve();
+ } );
+ } else {
+ deferred.resolve();
+ }
+ });
+ },
+
+ /**
+ * Get the base path of ogv.js and friends.
+ *
+ * @return string
+ */
+ basePath: function() {
+ var ext = mw.config.get( 'wgExtensionAssetsPath' ),
+ binPlayers = ext + '/TimedMediaHandler/MwEmbedModules/EmbedPlayer/binPlayers';
+ return binPlayers + '/ogv.js';
+ },
+
+ /**
+ * Return a stub audio context
+ *
+ * This is used for iOS Safari to enable Web Audio by triggering an empty
+ * audio output channel during a user input event handler. Without that,
+ * audio is left disabled and won't work when we start things up after an
+ * asynchronous code load.
+ *
+ * @return AudioContext
+ */
+ initAudioContext: function() {
+ var AudioContext = window.AudioContext || window.webkitAudioContext;
+ if ( AudioContext ) {
+ var context = new AudioContext(),
+ node;
+ if ( context.createScriptProcessor ) {
+ node = context.createScriptProcessor( 1024, 0, 2 );
+ } else if ( context.createJavaScriptNode ) {
+ node = context.createJavaScriptNode( 1024, 0, 2 );
+ } else {
+ throw new Error( 'Bad version of web audio API?' );
+ }
+
+ // Don't actually run any audio, just start & stop the node
+ node.connect( context.destination );
+ node.disconnect();
+
+ return context;
+ } else {
+ return null;
+ }
+ }
+ };
+
+} )( jQuery, mediaWiki );
diff --git a/extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js b/extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js
new file mode 100644
index 00000000..b53bb6f8
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/ext.tmh.TimedTextSelector.js
@@ -0,0 +1,8 @@
+( function ( $, mw ) {
+ $( function () {
+ $( '#timedmedia-tt-go' ).click( function () {
+ window.location = mw.config.get( 'wgScript' ) + '?title=' + mw.util.wikiUrlencode( mw.config.get( 'wgPageName' ) ) + '.' + $( '#timedmedia-tt-input' ).val() + '.srt&action=edit';
+ } );
+ } );
+
+} )( jQuery, mediaWiki );
diff --git a/extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js b/extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js
new file mode 100644
index 00000000..a8c8f98d
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/ext.tmh.transcodetable.js
@@ -0,0 +1,90 @@
+/**
+* Javascript to support transcode table on image page
+*/
+( function ( mw, $ ) {
+ $( document ).ready( function () {
+ var errorPopup, $errorLink;
+
+ errorPopup = function () {
+ // pop up dialog
+ mw.addDialog( {
+ 'width': '640',
+ 'height': '480',
+ 'title': $(this).attr( 'title' ),
+ 'content': $('<textarea />')
+ .css( {
+ 'width':'99%',
+ 'height':'99%'
+ } )
+ .text( $(this).attr('data-error') )
+ } )
+ .css( 'overflow', 'hidden' );
+ return false;
+ };
+
+ // Old version. Need to keep for a little while in case of cached pages.
+ $( '.mw-filepage-transcodestatus .errorlink' ).click( errorPopup );
+ // New version.
+ $errorLink = $( '.mw-filepage-transcodestatus .mw-tmh-pseudo-error-link' );
+ $errorLink.wrapInner( function () {
+ var $this = $( this );
+ return $( '<a />' ).attr( {
+ href: '#',
+ title: $this.text(),
+ 'data-error': $this.attr( 'data-error' )
+ } ).click( errorPopup );
+ } );
+
+ // Reset transcode action:
+ $( '.mw-filepage-transcodereset a' ).click( function () {
+ var tKey = $( this ).attr( 'data-transcodekey' ),
+ buttons = {};
+
+ buttons[ mw.msg( 'mwe-ok' ) ] = function () {
+ var api,
+ _thisDialog = this,
+ cancelBtn = {};
+
+ // Only show cancel button while loading:
+ cancelBtn[ mw.msg( 'mwe-cancel' ) ] = function () {
+ $(this).dialog( 'close' );
+ };
+ $( _thisDialog ).dialog( 'option', 'buttons', cancelBtn );
+
+ $( this ).loadingSpinner();
+
+ api = new mw.Api();
+ api.postWithEditToken( {
+ 'action' : 'transcodereset',
+ 'transcodekey' : tKey,
+ 'title' : mw.config.get('wgPageName')
+ } ).done( function () {
+ // Refresh the page
+ location.reload();
+ } ).fail( function ( code, data ) {
+ if( data.error && data.error.info ){
+ $( _thisDialog ).text( data.error.info );
+ } else {
+ $( _thisDialog ).text( mw.msg( 'timedmedia-reset-error' ) );
+ }
+ var okBtn = {};
+ okBtn[ mw.msg('mwe-ok') ] = function() { $(this).dialog( 'close' ); };
+ $( _thisDialog ).dialog( 'option', 'buttons', okBtn );
+ } );
+ };
+ buttons[ mw.msg( 'mwe-cancel' ) ] = function () {
+ $( this ).dialog( 'close' );
+ };
+ // pop up dialog
+ mw.addDialog( {
+ 'width': '400',
+ 'height': '200',
+ 'title': mw.msg( 'timedmedia-reset' ),
+ 'content': mw.msg( 'timedmedia-reset-confirm' ),
+ 'buttons': buttons
+ } )
+ .css( 'overflow', 'hidden' );
+ return false;
+ });
+ });
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js
new file mode 100644
index 00000000..6167418b
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayer.loader.js
@@ -0,0 +1,8 @@
+( function ( mw, $ ) {
+ // Add MediaWikiSupportPlayer dependency on players with a mediaWiki title
+ $( mw ).bind( 'EmbedPlayerUpdateDependencies', function ( event, embedPlayer, dependencySet ) {
+ if ( $( embedPlayer ).attr( 'data-mwtitle' ) ) {
+ $.merge( dependencySet, ['mw.MediaWikiPlayerSupport'] );
+ }
+ } );
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js
new file mode 100644
index 00000000..16ce367c
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.MediaWikiPlayerSupport.js
@@ -0,0 +1,380 @@
+( 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(
+ $( '<source />' )
+ .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 = $( '<div />' );
+
+ // Add the title:
+ $creditLine.append(
+ $( '<span>' ).html(
+ mw.msg( 'mwe-embedplayer-credit-title',
+ // get the link
+ $( '<div>' ).append(
+ $( '<a/>' ).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( $( '<br />' ),
+ 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( $( '<br />' ),
+ 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 $( '<div/>' ).addClass( 'creditline' )
+ .append(
+ $( '<a/>' ).attr( {
+ 'href': articleUrl,
+ 'title': titleStr
+ } ).html(
+ $( '<img/>' ).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',
+ $( '<div>' ).append(
+ $( '<a />' ).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 );
diff --git a/extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js b/extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js
new file mode 100644
index 00000000..c0aa30df
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.PopUpThumbVideo.js
@@ -0,0 +1,44 @@
+/**
+* Simple script to add pop-up video dialog link support for video thumbnails
+*/
+( function ( mw, $ ) {
+ $( document ).ready( function () {
+ $('.PopUpMediaTransform a').each( function () {
+ var link, title,
+ parent = $( this ).parent();
+ if ( parent.attr( 'videopayload' ) ) {
+ $( this ).click( function ( /*event*/ ) {
+ var thisref = this;
+
+ mw.loader.using( 'mw.MwEmbedSupport', function () {
+ var $videoContainer = $( $( thisref ).parent().attr( 'videopayload' ) );
+ mw.addDialog({
+ 'width': 'auto',
+ 'height': 'auto',
+ 'title': mw.html.escape( $videoContainer.find( 'video, audio' ).attr( 'data-mwtitle' ) ),
+ 'content': $videoContainer,
+ 'close': function(){
+ // On close destroy the dialog rather than just hiding it,
+ // so it doesn't eat up resources or keep playing.
+ $( this ).remove();
+ return true;
+ },
+ 'open': function() {
+ $( this ).find( 'video, audio' ).embedPlayer();
+ }
+ })
+ .css( 'overflow', 'hidden' );
+ } );
+ // don't follow file link
+ return false;
+ } );
+ } else if ( parent.attr( 'data-videopayload' ) ) {
+ link = $( this ).attr( 'href' );
+ title = mw.Title.newFromImg( { src: link } );
+ if ( title && title.getPrefixedDb() !== mw.config.get( 'wgPageName' ) ) {
+ $( this ).attr( 'href', title.getUrl() );
+ }
+ } /* else fall back to linking directly to media file */
+ } );
+ } );
+} )( mediaWiki, jQuery );
diff --git a/extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js b/extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js
new file mode 100644
index 00000000..fd23690e
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/mw.TMHGalleryHook.js
@@ -0,0 +1,46 @@
+/**
+* Simple script to add pop-up video dialog link support for video thumbnails
+*/
+( function ( mw ) {
+ // Hook to allow dynamically resizing videos in image galleries
+ mw.hook( 'mediawiki.page.gallery.resize' ).add( function ( info ) {
+ var $mwPlayerContainer,
+ $popUp,
+ $tmhVideo,
+ $mwContainer = info.$imageDiv.find( '.mediaContainer' );
+ if ( info.resolved ) {
+ // Everything is already done here.
+ return;
+ }
+
+ $mwContainer = info.$imageDiv.find( '.mediaContainer' );
+ if ( $mwContainer.length ) {
+ // Add some padding, so caption doesn't overlap video controls if
+ // we are overlaying the caption on top of the image.
+ if ( !info.$outerDiv.parent().hasClass( 'mw-gallery-packed' ) ) {
+ info.$outerDiv.find( 'div.gallerytext' ).css( 'padding-bottom', '20px' );
+ }
+
+ info.$imageDiv.width( info.imgWidth );
+ $mwContainer.width( info.imgWidth );
+ $mwPlayerContainer = $mwContainer.children( '.mwPlayerContainer' );
+ if ( $mwPlayerContainer.length ) {
+ // Case 1: HTML5 player already loaded
+ $mwPlayerContainer.width( info.imgWidth ).height( info.imgHeight );
+ $mwPlayerContainer.find( 'img.playerPoster' ).width( info.imgWidth ).height( info.imgHeight );
+ } else {
+ // Case 2: Raw video element
+ $tmhVideo = info.$imageDiv.find( 'video' );
+ $tmhVideo.width( info.imgWidth ).height( info.imgHeight );
+ }
+ info.resolved = true;
+ return;
+ }
+
+ $popUp = info.$imageDiv.find( '.PopUpMediaTransform' );
+ if ( $popUp.length ) {
+ info.$imageDiv.width( info.imgWidth );
+ $popUp.add( $popUp.find( 'img' ) ).width( info.imgWidth ).height( info.imgHeight );
+ }
+ } );
+} )( mediaWiki );
diff --git a/extensions/TimedMediaHandler/resources/player_big_play_button.png b/extensions/TimedMediaHandler/resources/player_big_play_button.png
new file mode 100644
index 00000000..041fea9c
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/player_big_play_button.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/resources/player_big_play_button_hover.png b/extensions/TimedMediaHandler/resources/player_big_play_button_hover.png
new file mode 100644
index 00000000..3517563e
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/player_big_play_button_hover.png
Binary files differ
diff --git a/extensions/TimedMediaHandler/resources/transcodeTable.css b/extensions/TimedMediaHandler/resources/transcodeTable.css
new file mode 100644
index 00000000..795ce134
--- /dev/null
+++ b/extensions/TimedMediaHandler/resources/transcodeTable.css
@@ -0,0 +1,14 @@
+.mw-filepage-transcodestatus .download-btn {
+ background-image: url('download_sprite.png');
+ width: 49px;
+ height: 36px;
+ background-repeat:no-repeat;
+ background-position: -50px;
+}
+.mw-filepage-transcodestatus .download-btn:hover {
+ background-position: 0 0;
+}
+.mw-filepage-transcodestatus .download-btn span {
+ /* Text hidden by the above image */
+ display: none;
+}