Index: branches/MwEmbedStandAlone/loader.js |
— | — | @@ -123,6 +123,9 @@ |
124 | 124 | "mwEmbed" : "mwEmbed.js", |
125 | 125 | "window.jQuery" : "libraries/jquery/jquery-1.4.2.js", |
126 | 126 | |
| 127 | + "$j.mobile" : "libraries/jquerymobile/jquery.mobile-1.0a2.js", |
| 128 | + "mw.style.mobile" : "libraries/jquerymobile/jquery.mobile-1.0a2.css", |
| 129 | + |
127 | 130 | "mw.Language" : "components/mw.Language.js", |
128 | 131 | "mw.Parser" : "components/mw.Parser.js", |
129 | 132 | "mw.Api" : "components/mw.Api.js", |
Index: branches/MwEmbedStandAlone/mwEmbed.js |
— | — | @@ -482,6 +482,7 @@ |
483 | 483 | } |
484 | 484 | return cleanRequest; |
485 | 485 | }, |
| 486 | + |
486 | 487 | /** |
487 | 488 | * Load a set of scripts. Will issue many load requests or package the |
488 | 489 | * request for the resource loader |
— | — | @@ -793,7 +794,7 @@ |
794 | 795 | } |
795 | 796 | return moduleList; |
796 | 797 | }, |
797 | | - |
| 798 | + |
798 | 799 | /** |
799 | 800 | * Loads javascript or css associated with a resourceName |
800 | 801 | * |
— | — | @@ -1160,7 +1161,7 @@ |
1161 | 1162 | return $j( '#mwTempLoaderDialog' ); |
1162 | 1163 | }; |
1163 | 1164 | mw.isIphone = function(){ |
1164 | | - return ( navigator.userAgent.indexOf('iPhone') != -1 ); |
| 1165 | + return ( navigator.userAgent.indexOf('iPhone') != -1 && ! mw.isIpad() ); |
1165 | 1166 | }; |
1166 | 1167 | mw.isIpod = function(){ |
1167 | 1168 | return ( navigator.userAgent.indexOf('iPod') != -1 ); |
— | — | @@ -1181,17 +1182,44 @@ |
1182 | 1183 | * |
1183 | 1184 | */ |
1184 | 1185 | mw.isHTML5FallForwardNative = function(){ |
1185 | | - // Check for a mobile html5 user agent: |
1186 | | - if ( ( mw.isIphone() ) || |
1187 | | - ( mw.isIpod() ) || |
1188 | | - ( mw.isIpad() ) || |
1189 | | - ( mw.isAndroid2() ) || |
1190 | | - // to debug in chrome / desktop safari |
| 1186 | + if( mw.isMobileHTML5() ){ |
| 1187 | + return true; |
| 1188 | + } |
| 1189 | + // Fall forward native: |
| 1190 | + // if the browser supports flash ( don't use html5 ) |
| 1191 | + if( mw.supportsFlash() ){ |
| 1192 | + return false; |
| 1193 | + } |
| 1194 | + // No flash return true if the browser supports html5 video tag with basic support for canPlayType: |
| 1195 | + if( mw.supportsHTML5() ){ |
| 1196 | + return true; |
| 1197 | + } |
| 1198 | + |
| 1199 | + return false; |
| 1200 | + } |
| 1201 | + |
| 1202 | + mw.isMobileHTML5 = function(){ |
| 1203 | + // Check for a mobile html5 user agent: |
| 1204 | + if ( (navigator.userAgent.indexOf('iPhone') != -1) || |
| 1205 | + (navigator.userAgent.indexOf('iPod') != -1) || |
| 1206 | + (navigator.userAgent.indexOf('iPad') != -1) || |
| 1207 | + (navigator.userAgent.indexOf('Android 2.') != -1) || |
| 1208 | + // Force html5 for chrome / desktop safari |
1191 | 1209 | (document.URL.indexOf('forceMobileHTML5') != -1 ) |
1192 | | - ) { |
| 1210 | + ){ |
1193 | 1211 | return true; |
1194 | 1212 | } |
1195 | | - |
| 1213 | + return false; |
| 1214 | + } |
| 1215 | + mw.supportsHTML5 = function(){ |
| 1216 | + var dummyvid = document.createElement( "video" ); |
| 1217 | + if( dummyvid.canPlayType ) { |
| 1218 | + return true; |
| 1219 | + } |
| 1220 | + return false; |
| 1221 | + } |
| 1222 | + |
| 1223 | + mw.supportsFlash = function(){ |
1196 | 1224 | // Check if the client does not have flash and has the video tag |
1197 | 1225 | if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) { |
1198 | 1226 | for ( var i = 0; i < navigator.mimeTypes.length; i++ ) { |
— | — | @@ -1201,31 +1229,26 @@ |
1202 | 1230 | type = type.substr( 0, semicolonPos ); |
1203 | 1231 | } |
1204 | 1232 | if (type == 'application/x-shockwave-flash' ) { |
1205 | | - // flash is installed don't use html5 |
1206 | | - return false; |
| 1233 | + // flash is installed |
| 1234 | + return true; |
1207 | 1235 | } |
1208 | 1236 | } |
1209 | | - } |
1210 | | - // For IE: |
| 1237 | + } |
| 1238 | + |
| 1239 | + // for IE: |
1211 | 1240 | var hasObj = true; |
1212 | | - try { |
1213 | | - var obj = new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' ); |
1214 | | - } catch ( e ) { |
1215 | | - hasObj = false; |
| 1241 | + if( typeof ActiveXObject != 'undefined' ){ |
| 1242 | + try { |
| 1243 | + var obj = new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' ); |
| 1244 | + } catch ( e ) { |
| 1245 | + hasObj = false; |
| 1246 | + } |
| 1247 | + if( hasObj ){ |
| 1248 | + return true; |
| 1249 | + } |
1216 | 1250 | } |
1217 | | - if( hasObj ){ |
1218 | | - return false; |
1219 | | - } |
1220 | | - // No flash return true if the browser supports html5 video tag with basic support for canPlayType: |
1221 | | - var dummyvid = document.createElement( "video" ); |
1222 | | - // temporary hack firefox does not work well with native player: |
1223 | | - if( dummyvid.canPlayType && !$j.browser.mozilla) { |
1224 | | - return true; |
1225 | | - } |
1226 | | - // No video tag or flash, return false ( normal "install flash" user flow ) |
1227 | 1251 | return false; |
1228 | 1252 | }; |
1229 | | - |
1230 | 1253 | /** |
1231 | 1254 | * Similar to php isset function checks if the variable exists. Does a safe |
1232 | 1255 | * check of a descendant method or variable |
Index: branches/MwEmbedStandAlone/modules/TimedText/loader.js |
— | — | @@ -13,7 +13,11 @@ |
14 | 14 | |
15 | 15 | "RemoteMwTimedText" : "remotes/RemoteMwTimedText.js" |
16 | 16 | } ); |
17 | | - |
| 17 | + |
| 18 | + mw.setDefaultConfig( 'EmbedPlayer.SourceAttributes', [ |
| 19 | + 'srclang' |
| 20 | + ]); |
| 21 | + |
18 | 22 | mw.setDefaultConfig( { |
19 | 23 | // If the Timed Text interface should be displayed: |
20 | 24 | // 'always' Displays link and call to contribute always |
Index: branches/MwEmbedStandAlone/modules/TimedText/mw.TimedText.js |
— | — | @@ -132,7 +132,21 @@ |
133 | 133 | $j( embedPlayer ).bind( 'play', function() { |
134 | 134 | // Will load and setup timedText sources (if not loaded already loaded ) |
135 | 135 | _this.setupTextSources(); |
136 | | - } ); |
| 136 | + } ); |
| 137 | + |
| 138 | + // Setup display binding |
| 139 | + $j( embedPlayer ).bind( 'onShowControlBar', function(event, layout ){ |
| 140 | + // Move the text track if present |
| 141 | + embedPlayer.$interface.find( '.track' ) |
| 142 | + .animate( layout, 'slow' ); |
| 143 | + }); |
| 144 | + |
| 145 | + $j( embedPlayer ).bind( 'onHideControlBar', function(event, layout ){ |
| 146 | + // Move the text track down if present |
| 147 | + embedPlayer.$interface.find( '.track' ) |
| 148 | + .animate( layout, 'slow' ); |
| 149 | + }); |
| 150 | + |
137 | 151 | }, |
138 | 152 | |
139 | 153 | /** |
— | — | @@ -323,7 +337,6 @@ |
324 | 338 | */ |
325 | 339 | autoSelectSource: function() { |
326 | 340 | this.enabledSources = []; |
327 | | - |
328 | 341 | // Check if any source matches our "local" |
329 | 342 | for( var i=0; i < this.textSources.length; i++ ) { |
330 | 343 | var source = this.textSources[ i ]; |
— | — | @@ -1395,7 +1408,6 @@ |
1396 | 1409 | var langKey = subPage.title.split( '.' ); |
1397 | 1410 | var extension = langKey.pop(); |
1398 | 1411 | langKey = langKey.pop(); |
1399 | | - |
1400 | 1412 | //NOTE: we hard code the mw-srt type |
1401 | 1413 | // ( This is because mediaWiki srt files can have wiki-text and parsed as such ) |
1402 | 1414 | if( extension == 'srt' ) { |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js |
— | — | @@ -25,9 +25,6 @@ |
26 | 26 | // media url |
27 | 27 | 'src', |
28 | 28 | |
29 | | - // media codecs attribute ( if provided ) |
30 | | - 'codecs', |
31 | | - |
32 | 29 | // Title string for the source asset |
33 | 30 | 'title', |
34 | 31 | |
— | — | @@ -51,17 +48,8 @@ |
52 | 49 | // If the source is the default source |
53 | 50 | 'default', |
54 | 51 | |
55 | | - // Language key used for subtitle tracks |
56 | | - 'srclang', |
57 | | - |
58 | 52 | // titleKey ( used for api lookups ) |
59 | | - 'titleKey', |
60 | | - |
61 | | - // The provider type ( for what type of api query to make ) |
62 | | - 'provider_type', |
63 | | - |
64 | | - // The api url for the provider |
65 | | - 'provider_url' |
| 53 | + 'titleKey' |
66 | 54 | ] ); |
67 | 55 | |
68 | 56 | /** |
— | — | @@ -460,7 +448,7 @@ |
461 | 449 | |
462 | 450 | // Check if we are using native controls ( should keep the video embed |
463 | 451 | // around ) |
464 | | - if( playerInterface.useNativePlayerControls() ) { |
| 452 | + if( playerInterface.useNativePlayerControls() || playerInterface.isPersistentNativePlayer() ) { |
465 | 453 | $j( targetElement ) |
466 | 454 | .attr( 'id', playerInterface.pid ) |
467 | 455 | .addClass( 'nativeEmbedPlayerPid' ) |
— | — | @@ -583,13 +571,9 @@ |
584 | 572 | |
585 | 573 | // End time in npt format |
586 | 574 | end_npt: null, |
587 | | - |
588 | | - // A provider "id" to identify api request type |
589 | | - provider_type : null, |
590 | | - |
591 | | - // The api url for the provider |
592 | | - provider_url : null, |
593 | | - |
| 575 | + |
| 576 | + // Language of the file |
| 577 | + srclang: null, |
594 | 578 | /** |
595 | 579 | * MediaSource constructor: |
596 | 580 | */ |
— | — | @@ -729,7 +713,7 @@ |
730 | 714 | * seeks) |
731 | 715 | * @return {String} the URI of the source. |
732 | 716 | */ |
733 | | - getSrc : function( serverSeekTime ) { |
| 717 | + getSrc: function( serverSeekTime ) { |
734 | 718 | if ( !serverSeekTime || !this.URLTimeEncoding ) { |
735 | 719 | return this.src; |
736 | 720 | } |
— | — | @@ -1441,9 +1425,11 @@ |
1442 | 1426 | }, |
1443 | 1427 | |
1444 | 1428 | stopEventPropagation: function(){ |
| 1429 | + this.stopMonitor(); |
1445 | 1430 | this._propagateEvents = false; |
1446 | 1431 | }, |
1447 | 1432 | restoreEventPropagation: function(){ |
| 1433 | + this.startMonitor(); |
1448 | 1434 | this._propagateEvents = true; |
1449 | 1435 | }, |
1450 | 1436 | /** |
— | — | @@ -1738,15 +1724,7 @@ |
1739 | 1725 | |
1740 | 1726 | // Auto select player based on default order |
1741 | 1727 | if ( !this.mediaElement.selectedSource ) { |
1742 | | - // check for parent clip: |
1743 | | - if ( typeof this.pc != 'undefined' ) { |
1744 | | - mw.log( 'no sources, type:' + this.type + ' check for html' ); |
1745 | | - // do load player if just displaying innerHTML: |
1746 | | - if ( this.pc.type == 'text/html' ) { |
1747 | | - this.selectedPlayer = mw.EmbedTypes.players.defaultPlayer( 'text/html' ); |
1748 | | - mw.log( 'set selected player:' + this.selectedPlayer.mimeType ); |
1749 | | - } |
1750 | | - } |
| 1728 | + mw.log( 'setupSourcePlayer:: no sources, type:' + this.type ); |
1751 | 1729 | } else { |
1752 | 1730 | this.selectedPlayer = mw.EmbedTypes.players.defaultPlayer( this.mediaElement.selectedSource.mimeType ); |
1753 | 1731 | } |
— | — | @@ -1912,12 +1890,16 @@ |
1913 | 1891 | var _this = this; |
1914 | 1892 | |
1915 | 1893 | this.seeking = true; |
1916 | | - // Run the seeking hook |
1917 | | - $j( this.embedPlayer ).trigger( 'onSeek' ); |
1918 | 1894 | |
1919 | 1895 | // See if we should do a server side seek ( player independent ) |
1920 | 1896 | if ( this.supportsURLTimeEncoding() ) { |
1921 | | - mw.log( 'EmbedPlayer::doSeek:: updated serverSeekTime: ' + mw.seconds2npt ( this.serverSeekTime ) ); |
| 1897 | + mw.log( 'EmbedPlayer::doSeek:: updated serverSeekTime: ' + mw.seconds2npt ( this.serverSeekTime ) + |
| 1898 | + ' currentTime: ' + _this.currentTime ); |
| 1899 | + // make sure we need to seek: |
| 1900 | + if( _this.currentTime == _this.serverSeekTime ){ |
| 1901 | + return ; |
| 1902 | + } |
| 1903 | + |
1922 | 1904 | this.stop(); |
1923 | 1905 | this.didSeekJump = true; |
1924 | 1906 | // Make sure this.serverSeekTime is up-to-date: |
— | — | @@ -1951,10 +1933,13 @@ |
1952 | 1934 | /** |
1953 | 1935 | * On clip done action. Called once a clip is done playing |
1954 | 1936 | */ |
1955 | | - onClipDone: function() { |
| 1937 | + onClipDone: function() { |
| 1938 | + var _this = this; |
| 1939 | + // don't run onclipdone if _propagateEvents is off |
| 1940 | + if( !_this._propagateEvents ){ |
| 1941 | + return ; |
| 1942 | + } |
1956 | 1943 | mw.log( 'EmbedPlayer::onClipDone:' + this.id + ' doneCount:' + this.donePlayingCount + ' stop state:' +this.isStopped() ); |
1957 | | - var _this = this; |
1958 | | - |
1959 | 1944 | // Only run stopped once: |
1960 | 1945 | if( !this.isStopped() ){ |
1961 | 1946 | // Stop the monitor: |
— | — | @@ -2034,6 +2019,7 @@ |
2035 | 2020 | * Show the player |
2036 | 2021 | */ |
2037 | 2022 | showPlayer : function () { |
| 2023 | + |
2038 | 2024 | mw.log( 'EmbedPlayer:: Show player: ' + this.id + ' interace: w:' + this.width + ' h:' + this.height ); |
2039 | 2025 | var _this = this; |
2040 | 2026 | // Set-up the local controlBuilder instance: |
— | — | @@ -2056,14 +2042,26 @@ |
2057 | 2043 | // position the "player" absolute inside the relative interface |
2058 | 2044 | // parent: |
2059 | 2045 | .css('position', 'absolute'); |
2060 | | - } |
2061 | | - |
| 2046 | + } |
| 2047 | + |
2062 | 2048 | // Set up local jQuery object reference to "mwplayer_interface" |
2063 | 2049 | this.$interface = $j( this ).parent( '.mwplayer_interface' ); |
2064 | 2050 | |
| 2051 | + // if a isPersistentNativePlayer ( overlay the controls ) |
| 2052 | + if( this.isPersistentNativePlayer() ){ |
| 2053 | + this.$interface.css({ |
| 2054 | + 'position' : 'absolute', |
| 2055 | + 'top' : '0px', |
| 2056 | + 'left' : '0px', |
| 2057 | + 'background': null |
| 2058 | + }) |
| 2059 | + $j(this).show(); |
| 2060 | + this.controls = true; |
| 2061 | + } |
| 2062 | + |
2065 | 2063 | // Update Thumbnail for the "player" |
2066 | 2064 | this.updatePosterHTML(); |
2067 | | - |
| 2065 | + |
2068 | 2066 | // Add controls if enabled: |
2069 | 2067 | if ( this.controls ) { |
2070 | 2068 | this.controlBuilder.addControls(); |
— | — | @@ -2090,6 +2088,7 @@ |
2091 | 2089 | * [misssingType] missing type mime |
2092 | 2090 | */ |
2093 | 2091 | showPluginMissingHTML: function( ) { |
| 2092 | + mw.log("showPluginMissingHTML"); |
2094 | 2093 | // Get mime type for unsuported formats: |
2095 | 2094 | var missingType = ''; |
2096 | 2095 | var or = ''; |
— | — | @@ -2098,7 +2097,7 @@ |
2099 | 2098 | or = ' or '; |
2100 | 2099 | } |
2101 | 2100 | // Remove the loading spinner if present: |
2102 | | - $j('.playerLoadingSpinner').remove(); |
| 2101 | + $j('.playerLoadingSpinner,.loadingSpinner').remove(); |
2103 | 2102 | |
2104 | 2103 | // If the native video is already displayed hide it: |
2105 | 2104 | if( $j( '#' + this.pid ).length != 0 ){ |
— | — | @@ -2117,9 +2116,6 @@ |
2118 | 2117 | } |
2119 | 2118 | var source = this.mediaElement.sources[0]; |
2120 | 2119 | // Check if we have user defined missing html msg: |
2121 | | - if ( this.user_missing_plugin_html ) { |
2122 | | - $j( this ).html( this.user_missing_plugin_html ); |
2123 | | - } else { |
2124 | 2120 | $j( this ).html( |
2125 | 2121 | $j('<div />').append( |
2126 | 2122 | gM( 'mwe-embedplayer-generic_missing_plugin', missingType ), |
— | — | @@ -2132,7 +2128,6 @@ |
2133 | 2129 | .text( gM( 'mwe-embedplayer-download_clip' ) ) |
2134 | 2130 | ) |
2135 | 2131 | ); |
2136 | | - } |
2137 | 2132 | // hide |
2138 | 2133 | }, |
2139 | 2134 | |
— | — | @@ -2296,33 +2291,36 @@ |
2297 | 2292 | var thumb_html = ''; |
2298 | 2293 | var class_atr = ''; |
2299 | 2294 | var style_atr = ''; |
2300 | | - |
2301 | | - |
| 2295 | + |
2302 | 2296 | if( this.useNativePlayerControls() ){ |
2303 | 2297 | this.showNativePlayer(); |
2304 | 2298 | return ; |
2305 | 2299 | } |
2306 | | - |
| 2300 | + |
2307 | 2301 | // Set by default thumb value if not found |
2308 | 2302 | var posterSrc = ( this.poster ) ? this.poster : |
2309 | 2303 | mw.getConfig( 'imagesPath' ) + 'vid_default_thumb.jpg'; |
2310 | 2304 | |
2311 | | - // Poster support is not very consistent in browsers |
2312 | | - // use a jpg poster image: |
2313 | | - $j( this ).html( |
2314 | | - $j( '<img />' ) |
2315 | | - .css({ |
2316 | | - 'position' : 'relative', |
2317 | | - 'width' : '100%', |
2318 | | - 'height' : '100%' |
2319 | | - }) |
2320 | | - .attr({ |
2321 | | - 'id' : 'img_thumb_' + this.id, |
2322 | | - 'src' : posterSrc |
2323 | | - }) |
2324 | | - .addClass( 'playerPoster' ) |
2325 | | - ); |
2326 | | - |
| 2305 | + // Update PersistentNativePlayer poster: |
| 2306 | + if( this.isPersistentNativePlayer() ){ |
| 2307 | + $j( '#' + this.pid ).attr('poster', posterSrc); |
| 2308 | + } else { |
| 2309 | + // Poster support is not very consistent in browsers |
| 2310 | + // use a jpg poster image: |
| 2311 | + $j( this ).html( |
| 2312 | + $j( '<img />' ) |
| 2313 | + .css({ |
| 2314 | + 'position' : 'relative', |
| 2315 | + 'width' : '100%', |
| 2316 | + 'height' : '100%' |
| 2317 | + }) |
| 2318 | + .attr({ |
| 2319 | + 'id' : 'img_thumb_' + this.id, |
| 2320 | + 'src' : posterSrc |
| 2321 | + }) |
| 2322 | + .addClass( 'playerPoster' ) |
| 2323 | + ); |
| 2324 | + } |
2327 | 2325 | if ( this.controls |
2328 | 2326 | && this.height > this.controlBuilder.getComponentHeight( 'playButtonLarge' ) |
2329 | 2327 | ) { |
— | — | @@ -2343,18 +2341,31 @@ |
2344 | 2342 | useNativePlayerControls: function() { |
2345 | 2343 | if( this.usenativecontrols === true ){ |
2346 | 2344 | return true; |
2347 | | - } |
2348 | | - |
| 2345 | + } |
2349 | 2346 | if( mw.getConfig('EmbedPlayer.NativeControls') === true ) { |
2350 | 2347 | return true; |
2351 | 2348 | } |
2352 | | - if( mw.getConfig('EmbedPlayer.NativeControlsMobileSafari' ) && |
2353 | | - mw.isHTML5FallForwardNative() |
2354 | | - ){ |
| 2349 | + |
| 2350 | + // Do some device detection devices that don't support overlays |
| 2351 | + // and go into full screen once play is clicked: |
| 2352 | + if( mw.isAndroid2() || mw.isIpod() || mw.isIphone() ){ |
2355 | 2353 | return true; |
| 2354 | + } |
| 2355 | + // iPad can use html controls if its a persistantPlayer in the dom before loading ) |
| 2356 | + // else it needs to use native controls: |
| 2357 | + if( mw.isIpad() ){ |
| 2358 | + if( this.isPersistentNativePlayer() ){ |
| 2359 | + return false; |
| 2360 | + } else { |
| 2361 | + return true; |
| 2362 | + } |
2356 | 2363 | } |
2357 | 2364 | return false; |
2358 | 2365 | }, |
| 2366 | + |
| 2367 | + isPersistentNativePlayer: function(){ |
| 2368 | + return $j('#' + this.pid ).hasClass('persistentNativePlayer'); |
| 2369 | + }, |
2359 | 2370 | |
2360 | 2371 | |
2361 | 2372 | /** |
— | — | @@ -2366,62 +2377,46 @@ |
2367 | 2378 | */ |
2368 | 2379 | showNativePlayer: function(){ |
2369 | 2380 | var _this = this; |
2370 | | - // Empty the player |
2371 | | - $j(this).empty(); |
| 2381 | + |
| 2382 | + // Empty the player of any child nodes |
| 2383 | + $j(this).empty(); |
2372 | 2384 | |
2373 | 2385 | // Remove the player loader spinner if it exists |
2374 | 2386 | $j('#loadingSpinner_' + this.id ).remove(); |
2375 | 2387 | |
2376 | | - |
2377 | | - // Check if we need to refresh mobile safari |
2378 | | - var mobileSafariNeedsRefresh = false; |
2379 | | - |
2380 | | - // Unhide the original video element if not part of a playerThemer embed |
2381 | | - if( !$j( '#' + this.pid ).hasClass('PlayerThemer') ){ |
2382 | | - $j( '#' + this.pid ) |
2383 | | - .css( { |
2384 | | - 'position' : 'absolute' |
2385 | | - } ) |
2386 | | - .show() |
2387 | | - .attr('controls', 'true'); |
2388 | | - |
2389 | | - mobileSafariNeedsRefresh = true; |
| 2388 | + // Setup the source |
| 2389 | + var source = this.mediaElement.getSources( 'video/h264' )[0]; |
| 2390 | + // Support fake user agent |
| 2391 | + if( !source || !source.src ){ |
| 2392 | + mw.log( 'Warning: Your probably fakeing the iPhone userAgent ( no h.264 source )' ); |
| 2393 | + source = this.mediaElement.getSources( 'video/ogg' )[0]; |
2390 | 2394 | } |
2391 | | - |
2392 | | - // iPad does not handle video tag update for attributes like "controls" |
2393 | | - // so we have to do a full replace ( if controls are not included |
2394 | | - // initially ) |
2395 | | - if( mw.isHTML5FallForwardNative() && mobileSafariNeedsRefresh ) { |
2396 | | - var source = this.mediaElement.getSources( 'video/h264' )[0]; |
2397 | | - // XXX note this should be updated once mobile supports h.264 |
2398 | | - if( !source || !source.src ){ |
2399 | | - mw.log( 'Warning: Your probably fakeing the iPhone userAgent ( no h.264 source )' ); |
2400 | | - source = this.mediaElement.getSources( 'video/ogg' )[0]; |
2401 | | - } |
2402 | | - |
2403 | | - var videoAttribues = { |
2404 | | - 'id' : _this.pid, |
2405 | | - 'poster': _this.poster, |
2406 | | - 'src' : source.src, |
2407 | | - 'controls' : 'true' |
2408 | | - } |
2409 | | - |
2410 | | - if( this.loop ){ |
2411 | | - videoAttribues[ 'loop' ] = 'true'; |
2412 | | - } |
2413 | | - var cssStyle = { |
2414 | | - 'width' : _this.width, |
2415 | | - 'height' : _this.height |
2416 | | - }; |
2417 | | - $j( '#' + this.pid ).replaceWith( |
2418 | | - _this.getNativePlayerHtml( videoAttribues, cssStyle ) |
2419 | | - ) |
2420 | | - // Bind native events: |
2421 | | - this.applyMediaElementBindings(); |
| 2395 | + |
| 2396 | + // Setup videoAttribues |
| 2397 | + var videoAttribues = { |
| 2398 | + 'poster': _this.poster, |
| 2399 | + 'src' : source.src, |
| 2400 | + 'controls' : 'true' |
2422 | 2401 | } |
| 2402 | + if( this.loop ){ |
| 2403 | + videoAttribues[ 'loop' ] = 'true'; |
| 2404 | + } |
| 2405 | + var cssStyle = { |
| 2406 | + 'width' : _this.width, |
| 2407 | + 'height' : _this.height |
| 2408 | + }; |
| 2409 | + |
| 2410 | + // If not a persistentNativePlayer swap the video tag |
| 2411 | + // completely instead of just updating properties: |
| 2412 | + $j( '#' + this.pid ).replaceWith( |
| 2413 | + _this.getNativePlayerHtml( videoAttribues, cssStyle ) |
| 2414 | + ) |
| 2415 | + |
| 2416 | + // Bind native events: |
| 2417 | + this.applyMediaElementBindings(); |
| 2418 | + |
2423 | 2419 | // Android only can play with a special play button ( no native controls |
2424 | | - // in the dom , and no auto-play ) |
2425 | | - // and only with 'native display' |
| 2420 | + // persistentNativePlayer has no controls: |
2426 | 2421 | if( mw.isAndroid2() ){ |
2427 | 2422 | this.addPlayBtnLarge(); |
2428 | 2423 | } |
— | — | @@ -2494,7 +2489,7 @@ |
2495 | 2490 | } else { |
2496 | 2491 | // old style embed: |
2497 | 2492 | var iframeUrl = mw.getMwEmbedPath() + 'mwEmbedFrame.php?'; |
2498 | | - var params = {}; |
| 2493 | + var params = {'src[]':[]}; |
2499 | 2494 | |
2500 | 2495 | if ( this.roe ) { |
2501 | 2496 | params.roe = this.roe; |
— | — | @@ -2512,7 +2507,7 @@ |
2513 | 2508 | for( var i=0; i < this.mediaElement.sources.length; i++ ){ |
2514 | 2509 | var source = this.mediaElement.sources[i]; |
2515 | 2510 | if( source.src ) { |
2516 | | - params['src[]'] = mw.absoluteUrl( source.src ); |
| 2511 | + params['src[]'].push(mw.absoluteUrl( source.src )); |
2517 | 2512 | } |
2518 | 2513 | } |
2519 | 2514 | // Output the poster attr |
— | — | @@ -2654,15 +2649,7 @@ |
2655 | 2650 | */ |
2656 | 2651 | play: function() { |
2657 | 2652 | var _this = this; |
2658 | | - |
2659 | | - if( this.paused && this.bubbleEventCheck() ){ |
2660 | | - this.paused = false; |
2661 | | - mw.log("trigger play event::" + !this.paused); |
2662 | | - $j( this ).trigger( 'play' ); |
2663 | | - } |
2664 | | - this.paused = false; |
2665 | | - |
2666 | | - mw.log( "EmbedPlayer:: play" ); |
| 2653 | + mw.log( "EmbedPlayer:: play: " + this._propagateEvents ); |
2667 | 2654 | // Hide any overlay: |
2668 | 2655 | this.controlBuilder.closeMenuOverlay(); |
2669 | 2656 | |
— | — | @@ -2673,14 +2660,22 @@ |
2674 | 2661 | return; |
2675 | 2662 | } else { |
2676 | 2663 | this.thumbnail_disp = false; |
| 2664 | + // hide any button if present: |
| 2665 | + this.$interface.find( '.play-btn-large' ).remove(); |
2677 | 2666 | this.doEmbedHTML(); |
2678 | 2667 | } |
2679 | 2668 | } else { |
2680 | 2669 | // the plugin is already being displayed |
2681 | 2670 | this.seeking = false; |
2682 | 2671 | } |
| 2672 | + // Trigger the play event |
| 2673 | + if( this.paused && this.bubbleEventCheck() ){ |
| 2674 | + this.paused = false; |
| 2675 | + mw.log("trigger play event::" + !this.paused); |
| 2676 | + $j( this ).trigger( 'play' ); |
| 2677 | + } |
| 2678 | + this.paused = false; |
2683 | 2679 | |
2684 | | - |
2685 | 2680 | this.$interface.find('.play-btn span') |
2686 | 2681 | .removeClass( 'ui-icon-play' ) |
2687 | 2682 | .addClass( 'ui-icon-pause' ); |
— | — | @@ -2691,8 +2686,8 @@ |
2692 | 2687 | .click( function( ) { |
2693 | 2688 | _this.pause(); |
2694 | 2689 | } ) |
2695 | | - .attr( 'title', gM( 'mwe-embedplayer-pause_clip' ) ); |
2696 | | - |
| 2690 | + .attr( 'title', gM( 'mwe-embedplayer-pause_clip' ) ); |
| 2691 | + |
2697 | 2692 | // Start the monitor if not already started |
2698 | 2693 | this.monitor(); |
2699 | 2694 | |
— | — | @@ -2949,6 +2944,10 @@ |
2950 | 2945 | stopMonitor: function(){ |
2951 | 2946 | this.thumbnail_disp = true; |
2952 | 2947 | }, |
| 2948 | + // xxx temporary hack we need a better stop monitor system |
| 2949 | + startMonitor: function(){ |
| 2950 | + this.thumbnail_disp = false; |
| 2951 | + }, |
2953 | 2952 | |
2954 | 2953 | /** |
2955 | 2954 | * Checks if the currentTime was updated outside of the getPlayerElementTime |
— | — | @@ -2961,8 +2960,9 @@ |
2962 | 2961 | // If the time has been updated and is in range issue a seek |
2963 | 2962 | if( _this.getDuration() && _this.currentTime <= _this.getDuration() ){ |
2964 | 2963 | var seekPercent = _this.currentTime / _this.getDuration(); |
2965 | | - mw.log("monitor::" + _this.previousTime + ' != ' + |
| 2964 | + mw.log("checkForCurrentTimeSeek::" + _this.previousTime + ' != ' + |
2966 | 2965 | _this.currentTime + " javascript based currentTime update to " + seekPercent); |
| 2966 | + _this.previousTime = _this.currentTime; |
2967 | 2967 | this.doSeek( seekPercent ); |
2968 | 2968 | } |
2969 | 2969 | } |
— | — | @@ -2974,17 +2974,18 @@ |
2975 | 2975 | */ |
2976 | 2976 | monitor: function() { |
2977 | 2977 | var _this = this; |
2978 | | - |
| 2978 | + |
2979 | 2979 | // Check for current time update outside of embed player |
2980 | 2980 | this.checkForCurrentTimeSeek(); |
2981 | | - |
| 2981 | + |
| 2982 | + |
2982 | 2983 | // Update currentTime via embedPlayer |
2983 | | - _this.currentTime = _this.getPlayerElementTime(); |
| 2984 | + _this.currentTime = _this.getPlayerElementTime(); |
2984 | 2985 | |
2985 | 2986 | // Update any offsets from server seek |
2986 | | - if( _this.serverSeekTime && _this.supportsURLTimeEncoding ){ |
2987 | | - _this.currentTime = _this.serverSeekTime + _this.getPlayerElementTime() |
2988 | | - } |
| 2987 | + if( _this.serverSeekTime && _this.supportsURLTimeEncoding() ){ |
| 2988 | + _this.currentTime = parseInt( _this.serverSeekTime ) + parseInt( _this.getPlayerElementTime() ); |
| 2989 | + } |
2989 | 2990 | |
2990 | 2991 | // Update the previousTime ( so we can know if the user-javascript |
2991 | 2992 | // changed currentTime ) |
— | — | @@ -2996,7 +2997,9 @@ |
2997 | 2998 | // _this.previousVolume ); |
2998 | 2999 | if( Math.round( _this.volume * 100 ) != Math.round( _this.previousVolume * 100 ) ) { |
2999 | 3000 | _this.setInterfaceVolume( _this.volume ); |
3000 | | - $j( this ).trigger('volumeChanged', _this.volume ); |
| 3001 | + if( _this._propagateEvents ){ |
| 3002 | + $j( this ).trigger('volumeChanged', _this.volume ); |
| 3003 | + } |
3001 | 3004 | } |
3002 | 3005 | |
3003 | 3006 | // Update the previous volume |
— | — | @@ -3013,8 +3016,9 @@ |
3014 | 3017 | _this.muted = _this.getPlayerElementMuted(); |
3015 | 3018 | } |
3016 | 3019 | |
3017 | | - // mw.log( 'Monitor:: ' + this.currentTime + ' duration: ' + ( parseInt( |
| 3020 | + //mw.log( 'Monitor:: ' + this.currentTime + ' duration: ' + ( parseInt( |
3018 | 3021 | // this.getDuration() ) + 1 ) + ' is seeking: ' + this.seeking ); |
| 3022 | + |
3019 | 3023 | if ( this.currentTime >= 0 && this.duration ) { |
3020 | 3024 | if ( !this.userSlide && !this.seeking ) { |
3021 | 3025 | if ( parseInt( this.startOffset ) != 0 ) { |
— | — | @@ -3032,8 +3036,8 @@ |
3033 | 3037 | // Check if we are "done" |
3034 | 3038 | var endPresentationTime = ( this.startOffset ) ? ( this.startOffset + this.duration ) : this.duration; |
3035 | 3039 | if ( this.currentTime >= endPresentationTime ) { |
3036 | | - mw.log( "should run clip done :: " + this.currentTime + ' > ' + endPresentationTime ); |
3037 | | - this.onClipDone(); |
| 3040 | + mw.log( "should run clip done :: " + this.currentTime + ' > ' + endPresentationTime ); |
| 3041 | + this.onClipDone(); |
3038 | 3042 | } |
3039 | 3043 | } else { |
3040 | 3044 | // Media lacks duration just show end time |
— | — | @@ -3057,7 +3061,9 @@ |
3058 | 3062 | // run the "native" progress event on the virtual html5 object if set |
3059 | 3063 | if( this.progressEventData ) { |
3060 | 3064 | // mw.log("trigger:progress event on html5 proxy"); |
3061 | | - $j( this ).trigger( 'progress', this.progressEventData ); |
| 3065 | + if( _this._propagateEvents ){ |
| 3066 | + $j( this ).trigger( 'progress', this.progressEventData ); |
| 3067 | + } |
3062 | 3068 | } |
3063 | 3069 | |
3064 | 3070 | // Call monitor at 250ms interval. ( use setInterval to avoid stacking |
— | — | @@ -3076,7 +3082,9 @@ |
3077 | 3083 | } |
3078 | 3084 | |
3079 | 3085 | // mw.log('trigger:monitor:: ' + this.currentTime ); |
3080 | | - $j( this ).trigger( 'monitorEvent' ); |
| 3086 | + if( _this._propagateEvents ){ |
| 3087 | + $j( this ).trigger( 'monitorEvent' ); |
| 3088 | + } |
3081 | 3089 | }, |
3082 | 3090 | |
3083 | 3091 | /** |
— | — | @@ -3206,13 +3214,19 @@ |
3207 | 3215 | */ |
3208 | 3216 | |
3209 | 3217 | /** |
3210 | | - * Get the current selected media source |
| 3218 | + * Get the current selected media source or first source |
3211 | 3219 | * |
3212 | 3220 | * @return src url |
3213 | 3221 | */ |
3214 | 3222 | getSrc: function() { |
| 3223 | + if( this.currentTime && !this.serverSeekTime){ |
| 3224 | + this.serverSeekTime = this.currentTime; |
| 3225 | + } |
3215 | 3226 | if( this.mediaElement.selectedSource ){ |
3216 | 3227 | return this.mediaElement.selectedSource.getSrc( this.serverSeekTime ); |
| 3228 | + } else if( this.mediaElement ){ |
| 3229 | + // get the first source: |
| 3230 | + return this.mediaElement.getSources()[0].getSrc( this.serverSeekTime ); |
3217 | 3231 | } |
3218 | 3232 | return false; |
3219 | 3233 | }, |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.IFramePlayerApiClient.js |
— | — | @@ -1,7 +1,7 @@ |
2 | 2 | /** |
3 | | -* iFrame api mapping support |
4 | | -* |
5 | | -* Client side ( binds a given iFrames to expose the player api ) |
| 3 | +* iFrame api mapping support |
| 4 | +* |
| 5 | +* Client side ( binds a given iFrames to expose the player api ) |
6 | 6 | */ |
7 | 7 | mw.IFramePlayerApiClient = function( iframe, playerProxy, options ){ |
8 | 8 | return this.init( iframe , playerProxy, options); |
— | — | @@ -48,11 +48,11 @@ |
49 | 49 | //mw.log("IframePlayerApiClient:: hanldeReciveMsg "); |
50 | 50 | // Confirm the event is coming for the target host: |
51 | 51 | if( event.origin != this.iframeServer){ |
52 | | - mw.log("Skip msg from host does not match iFrame player: " + event.origin + |
| 52 | + mw.log("Skip msg from host does not match iFrame player: " + event.origin + |
53 | 53 | ' != iframe Server: ' + this.iframeServer ) |
54 | 54 | return ; |
55 | 55 | }; |
56 | | - // Decode the message |
| 56 | + // Decode the message |
57 | 57 | var msgObject = JSON.parse( event.data ); |
58 | 58 | var playerAttributes = mw.getConfig( 'EmbedPlayer.Attributes' ); |
59 | 59 | // Before we update local attributes check that the object has not been updated by user js |
— | — | @@ -60,7 +60,7 @@ |
61 | 61 | if( attrName != 'id' ){ |
62 | 62 | if( _this._prevPlayerProxy[ attrName ] != _this.playerProxy[ attrName ] ){ |
63 | 63 | mw.log( "IFramePlayerApiClient:: User js update:" + attrName + ' set to: ' + this.playerProxy[ attrName ] + ' != old: ' + _this._prevPlayerProxy[ attrName ] ); |
64 | | - // Send the updated attribute back to the iframe: |
| 64 | + // Send the updated attribute back to the iframe: |
65 | 65 | _this.postMessage({ |
66 | 66 | 'attrName' : attrName, |
67 | 67 | 'attrValue' : _this.playerProxy[ attrName ] |
— | — | @@ -81,7 +81,7 @@ |
82 | 82 | } |
83 | 83 | } |
84 | 84 | } |
85 | | - // Trigger any binding events |
| 85 | + // Trigger any binding events |
86 | 86 | if( typeof msgObject.triggerName != 'undefined' && msgObject.triggerArgs != 'undefined') { |
87 | 87 | mw.log('IFramePlayerApiClient:: trigger: ' + msgObject.triggerName ); |
88 | 88 | $j( _this.playerProxy ).trigger( msgObject.triggerName, msgObject.triggerArgs ); |
— | — | @@ -91,9 +91,9 @@ |
92 | 92 | 'postMessage': function( msgObj ){ |
93 | 93 | mw.log( "IFramePlayerApiClient:: postMessage(): " + JSON.stringify( msgObj ) ); |
94 | 94 | $j.postMessage( |
95 | | - JSON.stringify( msgObj ), |
96 | | - mw.absoluteUrl( $j( this.iframe ).attr('src') ), |
97 | | - this.iframe.contentWindow |
| 95 | + JSON.stringify( msgObj ), |
| 96 | + mw.absoluteUrl( $j( this.iframe ).attr('src') ), |
| 97 | + this.iframe.contentWindow |
98 | 98 | ); |
99 | 99 | } |
100 | 100 | }; |
— | — | @@ -107,7 +107,7 @@ |
108 | 108 | // Append '_ifp' ( iframe player ) to id of real iframe so that 'id', and 'src' attributes don't conflict |
109 | 109 | var originalIframeId = ( $( this.selector ).attr( 'id' ) )? $( this.selector ).attr( 'id' ) : Math.floor( 9999999 * Math.random() ); |
110 | 110 | var iframePlayerId = originalIframeId + '_ifp' ; // here we use random to generate a unique id |
111 | | - // Append the div element proxy after the iframe |
| 111 | + // Append the div element proxy after the iframe |
112 | 112 | $j( this.selector ) |
113 | 113 | .attr('id', iframePlayerId) |
114 | 114 | .after( |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/mw.PlayerControlBuilder.js |
— | — | @@ -89,7 +89,7 @@ |
90 | 90 | }, |
91 | 91 | |
92 | 92 | /** |
93 | | - * Add the controls html to palyer interface |
| 93 | + * Add the controls html to player interface |
94 | 94 | */ |
95 | 95 | addControls: function() { |
96 | 96 | // Set up local pointer to the embedPlayer |
— | — | @@ -105,11 +105,16 @@ |
106 | 106 | _this.displayOptionsMenuFlag = false; |
107 | 107 | |
108 | 108 | |
109 | | - // Setup the controlBar container |
| 109 | + // Setup the controlBar container ( starts hidden ) |
110 | 110 | var $controlBar = $j('<div />') |
111 | 111 | .addClass( 'ui-state-default ui-widget-header ui-helper-clearfix control-bar' ) |
112 | | - .css( 'height', this.height ); |
| 112 | + .css( 'height', this.height ) |
113 | 113 | |
| 114 | + // Controls are hidden by default if overlaying controls: |
| 115 | + if( _this.checkOverlayControls() ){ |
| 116 | + $controlBar.hide(); |
| 117 | + } |
| 118 | + |
114 | 119 | $controlBar.css( { |
115 | 120 | 'position': 'absolute', |
116 | 121 | 'bottom' : '0px', |
— | — | @@ -118,10 +123,10 @@ |
119 | 124 | } ); |
120 | 125 | |
121 | 126 | // Check for overlay controls: |
122 | | - if( ! _this.checkOverlayControls() ) { |
| 127 | + if( ! _this.checkOverlayControls() && ! embedPlayer.controls === false) { |
123 | 128 | // Add some space to interface for the control bar ( if not overlaying controls ) |
124 | | - embedPlayer.$interface.css( { |
125 | | - 'height' : parseInt( embedPlayer.height ) + parseInt( this.height ) +2 |
| 129 | + $j( embedPlayer ).css( { |
| 130 | + 'height' : parseInt( embedPlayer.height ) - parseInt( this.height ) |
126 | 131 | } ); |
127 | 132 | } |
128 | 133 | |
— | — | @@ -219,7 +224,7 @@ |
220 | 225 | // Set target width |
221 | 226 | var targetWidth = windowSize.width; |
222 | 227 | var targetHeight = targetWidth * ( embedPlayer.getHeight() / embedPlayer.getWidth() ); |
223 | | - |
| 228 | + |
224 | 229 | // Check if it exceeds the height constraint: |
225 | 230 | if( targetHeight > windowSize.height ){ |
226 | 231 | targetHeight = windowSize.height; |
— | — | @@ -622,14 +627,10 @@ |
623 | 628 | // Hide the control bar |
624 | 629 | this.embedPlayer.$interface.find( '.control-bar') |
625 | 630 | .fadeOut( animateDuration ); |
| 631 | + mw.log('about to trigger hide control bar') |
| 632 | + // Allow interface items to update: |
| 633 | + $j( this.embedPlayer ).trigger('onHideControlBar', {'bottom' : 10} ); |
626 | 634 | |
627 | | - // Move the timed text XXX this should go into timedText module |
628 | | - this.embedPlayer.$interface.find( '.track' ) |
629 | | - .stop() |
630 | | - .animate( { |
631 | | - 'bottom' : 10 |
632 | | - }, 'slow' ); |
633 | | - |
634 | 635 | }, |
635 | 636 | |
636 | 637 | /** |
— | — | @@ -643,18 +644,13 @@ |
644 | 645 | $j( this.embedPlayer.getPlayerElement() ).css( 'z-index', '1' ); |
645 | 646 | } |
646 | 647 | mw.log( 'PlayerControlBuilder:: ShowControlBar' ); |
647 | | - // Move up text track if present |
648 | | - this.embedPlayer.$interface.find( '.track' ) |
649 | | - .animate( |
650 | | - { |
651 | | - 'bottom' : this.getHeight() + 10 |
652 | | - }, |
653 | | - animateDuration |
654 | | - ); |
655 | | - |
| 648 | + |
656 | 649 | // Show interface controls |
657 | 650 | this.embedPlayer.$interface.find( '.control-bar' ) |
658 | 651 | .fadeIn( animateDuration ); |
| 652 | + |
| 653 | + // Trigger the screen overlay with layout info: |
| 654 | + $j( this.embedPlayer ).trigger( 'onShowControlBar', {'bottom' : this.getHeight() + 10 } ); |
659 | 655 | }, |
660 | 656 | |
661 | 657 | /** |
— | — | @@ -674,18 +670,25 @@ |
675 | 671 | } |
676 | 672 | |
677 | 673 | // If the config is false |
678 | | - if( mw.getConfig( 'EmbedPlayer.OverlayControls' ) == false){ |
| 674 | + if( mw.getConfig( 'EmbedPlayer.OverlayControls' ) === false){ |
679 | 675 | return false; |
680 | 676 | } |
| 677 | + // iPad supports overlays but the touch events mean we want the controls displayed all the |
| 678 | + // time for now. |
| 679 | + if( mw.isIpad() ){ |
| 680 | + return false; |
| 681 | + } |
| 682 | + |
681 | 683 | |
682 | 684 | // Don't hide controls when content "height" is 0px ( audio tags ) |
683 | 685 | if( this.embedPlayer.getPlayerHeight() === 0 && |
684 | | - $j(this.embedPlayer).css('height').indexOf('%') == -1 ){ |
| 686 | + $j(this.embedPlayer).css('height').indexOf('%') === -1 ){ |
685 | 687 | return false; |
686 | 688 | } |
687 | 689 | if( this.embedPlayer.controls === false ){ |
688 | 690 | return false; |
689 | 691 | } |
| 692 | + |
690 | 693 | // Past all tests OverlayControls is true: |
691 | 694 | return true; |
692 | 695 | }, |
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerNative.js |
— | — | @@ -8,9 +8,6 @@ |
9 | 9 | //Instance Name |
10 | 10 | instanceOf: 'Native', |
11 | 11 | |
12 | | - // Counts the number of times we tried to access the video element |
13 | | - grab_try_count:0, |
14 | | - |
15 | 12 | // Flag to only load the video ( not play it ) |
16 | 13 | onlyLoadFlag:false, |
17 | 14 | |
— | — | @@ -27,7 +24,6 @@ |
28 | 25 | // If the media loaded event has been fired |
29 | 26 | mediaLoadedFlag: null, |
30 | 27 | |
31 | | - |
32 | 28 | // All the native events per: |
33 | 29 | // http://www.w3.org/TR/html5/video.html#mediaevents |
34 | 30 | nativeEvents : [ |
— | — | @@ -69,11 +65,16 @@ |
70 | 66 | * Updates the supported features given the "type of player" |
71 | 67 | */ |
72 | 68 | updateFeatureSupport: function(){ |
73 | | - // iWhatever devices appear to have a broken |
74 | | - // dom overlay implementation of video atm. (hopefully iphone OS 4 fixes this ) |
75 | | - if( mw.isHTML5FallForwardNative() ) { |
| 69 | + // The native controls function checks for overly support |
| 70 | + // especially the special case of iPad in-dom or not support |
| 71 | + if( this.useNativePlayerControls() ) { |
76 | 72 | this.supports.overlays = false; |
| 73 | + this.supports.volumeControl = false; |
77 | 74 | } |
| 75 | + // iOS does not support volume control ( only iPad can have controls ) |
| 76 | + if( mw.isIpad() ){ |
| 77 | + this.supports.volumeControl = false; |
| 78 | + } |
78 | 79 | }, |
79 | 80 | |
80 | 81 | /** |
— | — | @@ -85,12 +86,21 @@ |
86 | 87 | // Reset some play state flags: |
87 | 88 | _this.bufferStartFlag = false; |
88 | 89 | _this.bufferEndFlag = false; |
| 90 | + |
| 91 | + mw.log( "native play url:" + this.getSrc( this.currentTime ) + ' startOffset: ' + this.start_ntp + ' end: ' + this.end_ntp ); |
89 | 92 | |
90 | | - mw.log( "native play url:" + this.getSrc() + ' startOffset: ' + this.start_ntp + ' end: ' + this.end_ntp ); |
91 | | - |
92 | 93 | // Check if using native controls and already the "pid" is already in the DOM |
93 | | - if( this.useNativePlayerControls() && $j( '#' + this.pid ).length && |
94 | | - typeof $j( '#' + this.pid ).get(0).play != 'undefined' ) { |
| 94 | + if( ( this.useNativePlayerControls() |
| 95 | + || |
| 96 | + this.isPersistentNativePlayer() |
| 97 | + ) |
| 98 | + && $j( '#' + this.pid ).length |
| 99 | + && typeof $j( '#' + this.pid ).get(0).play != 'undefined' ) { |
| 100 | + |
| 101 | + // Update the player source: |
| 102 | + $j( '#' + this.pid ).attr('src', this.getSrc( this.currentTime ) ); |
| 103 | + $j( '#' + this.pid ).get(0).load(); |
| 104 | + |
95 | 105 | _this.postEmbedJS(); |
96 | 106 | return ; |
97 | 107 | } |
— | — | @@ -115,14 +125,13 @@ |
116 | 126 | } |
117 | 127 | // Update required attributes |
118 | 128 | if( !playerAttribtues[ 'id'] ) playerAttribtues['id'] = this.pid; |
119 | | - if( !playerAttribtues['src'] ) playerAttribtues['src'] = this.getSrc(); |
| 129 | + if( !playerAttribtues['src'] ) playerAttribtues['src'] = this.getSrc( this.currentTime); |
120 | 130 | |
121 | 131 | // If autoplay pass along to attribute ( needed for iPad / iPod no js autoplay support |
122 | 132 | if( this.autoplay ) { |
123 | 133 | playerAttribtues['autoplay'] = 'true'; |
124 | 134 | } |
125 | 135 | |
126 | | - |
127 | 136 | if( !cssSet ){ |
128 | 137 | cssSet = {}; |
129 | 138 | } |
— | — | @@ -200,7 +209,11 @@ |
201 | 210 | monitor: function(){ |
202 | 211 | var _this = this; |
203 | 212 | var vid = _this.getPlayerElement(); |
204 | | - |
| 213 | + |
| 214 | + // Update duration |
| 215 | + if( vid && vid.duration ){ |
| 216 | + this.duration = vid.duration; |
| 217 | + } |
205 | 218 | // Update the bufferedPercent |
206 | 219 | if( vid && vid.buffered && vid.buffered.end && vid.duration ) { |
207 | 220 | this.bufferedPercent = ( vid.buffered.end(0) / vid.duration ); |
— | — | @@ -217,8 +230,6 @@ |
218 | 231 | doSeek: function( percentage ) { |
219 | 232 | mw.log( 'Native::doSeek p: ' + percentage + ' : ' + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec ); |
220 | 233 | this.seeking = true; |
221 | | - // Run the seeking hook |
222 | | - $j( this.embedPlayer ).trigger( 'onSeek' ); |
223 | 234 | |
224 | 235 | // Run the onSeeking interface update |
225 | 236 | this.controlBuilder.onSeek(); |
— | — | @@ -487,8 +498,6 @@ |
488 | 499 | //( if not already set from interface ) |
489 | 500 | if( !this.seeking ) { |
490 | 501 | this.seeking = true; |
491 | | - // Run the seeking hook (somewhat redundant ) |
492 | | - $j( this ).trigger( 'onSeek' ); |
493 | 502 | |
494 | 503 | // Run the onSeeking interface update |
495 | 504 | this.controlBuilder.onSeek(); |
— | — | @@ -506,7 +515,6 @@ |
507 | 516 | onseeked: function() { |
508 | 517 | mw.log("native:onSeeked"); |
509 | 518 | |
510 | | - mw.log("native:onSeeked:trigger"); |
511 | 519 | // Trigger the html5 action on the parent |
512 | 520 | if( this.seeking && this.useNativePlayerControls() ){ |
513 | 521 | this.seeking = false; |
— | — | @@ -527,9 +535,11 @@ |
528 | 536 | * Handle the native play event |
529 | 537 | */ |
530 | 538 | onplay: function(){ |
531 | | - mw.log("EmbedPlayer:native:: OnPlay"); |
| 539 | + mw.log("EmbedPlayer:native:: OnPlay::" + this._propagateEvents ); |
532 | 540 | // Update the interface ( if paused ) |
533 | | - this.parent_play(); |
| 541 | + if( this._propagateEvents ){ |
| 542 | + this.parent_play(); |
| 543 | + } |
534 | 544 | }, |
535 | 545 | |
536 | 546 | /** |
— | — | @@ -551,7 +561,7 @@ |
552 | 562 | this.onLoadedCallback(); |
553 | 563 | } |
554 | 564 | |
555 | | - // Tigger "media loaded" |
| 565 | + // Trigger "media loaded" |
556 | 566 | if( ! this.mediaLoadedFlag ){ |
557 | 567 | $j( this ).trigger( 'mediaLoaded' ); |
558 | 568 | this.mediaLoadedFlag = true; |
— | — | @@ -569,7 +579,6 @@ |
570 | 580 | */ |
571 | 581 | onprogress: function( event ) { |
572 | 582 | var e = event.originalEvent; |
573 | | - //mw.log("onprogress: e:" + e + ' ' + e.loaded + ' && ' + e.total ); |
574 | 583 | if( e && e.loaded && e.total ) { |
575 | 584 | this.bufferedPercent = e.loaded / e.total; |
576 | 585 | this.progressEventData = e.loaded; |
— | — | @@ -584,8 +593,9 @@ |
585 | 594 | */ |
586 | 595 | onended: function() { |
587 | 596 | var _this = this; |
588 | | - mw.log( 'EmbedPlayer:native: onended:' + this.playerElement.currentTime + ' real dur:' + this.getDuration() ); |
589 | | - |
590 | | - this.onClipDone(); |
| 597 | + mw.log( 'EmbedPlayer:native: onended:' + this.playerElement.currentTime + ' real dur:' + this.getDuration() + ' ended ' + this._propagateEvents ); |
| 598 | + if( this._propagateEvents ){ |
| 599 | + this.onClipDone(); |
| 600 | + } |
591 | 601 | } |
592 | 602 | }; |
Index: branches/MwEmbedStandAlone/remotes/mediaWiki.js |
— | — | @@ -4,7 +4,7 @@ |
5 | 5 | */ |
6 | 6 | var urlparts = getRemoteEmbedPath(); |
7 | 7 | var mwEmbedHostPath = urlparts[0]; |
8 | | -var mwRemoteVersion = 'r177'; |
| 8 | +var mwRemoteVersion = 'r179'; |
9 | 9 | var mwUseScriptLoader = true; |
10 | 10 | |
11 | 11 | // Log the mwRemote version makes it easy to debug cache issues |
— | — | @@ -92,7 +92,7 @@ |
93 | 93 | // NOTE this is REQUIRED for apiProxy to work across projects where the user has not universally enabled the gadget |
94 | 94 | mw.setConfig( 'Mw.AppendWithJS', 'withJS=MediaWiki:MwEmbed.js'); |
95 | 95 | |
96 | | -// Allow all wikimedia regEx domains matches to support api-proxy requests |
| 96 | +// Allow all wikimedia RegEx domains matches to support api-proxy requests |
97 | 97 | // NOTE remember to put $ at the end of the domain or it would match en.wikipedia.org.evil.com |
98 | 98 | mw.setConfig( 'ApiProxy.DomainWhiteList', |
99 | 99 | [ /wikimedia\.org$/ , /wikipedia\.org$/ , /wiktionary.org$/ , /wikinews.org$/ , /wikibooks.org$/ , /wikisource.org$/ , /wikiversity.org$/ , /wikiquote.org$/ ] |
— | — | @@ -280,9 +280,11 @@ |
281 | 281 | |
282 | 282 | // Check for special "embedplayer" yes and set relevent config: |
283 | 283 | if( mwReqParam['embedplayer'] == 'yes' ){ |
284 | | - mwAddCommonStyleSheet(); |
| 284 | + mwAddCommonStyleSheet(); |
| 285 | + |
285 | 286 | // Only rewrite the main embed player |
286 | | - var playerDiv = document.getElementById( 'file' ).childNodes[0].cloneNode( true ); |
| 287 | + var playerDiv = document.getElementById( 'file' ).childNodes[0].cloneNode( true ); |
| 288 | + document.body.style.overflow = 'hidden'; |
287 | 289 | document.body.innerHTML = '<div id="loadingPlayer" style="height:100%;width:100%"><div class="loadingSpinner" style="position:absolute;left:50%;top:50%"></div></div>'; |
288 | 290 | document.body.appendChild( playerDiv ); |
289 | 291 | } |