r71863 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r71862‎ | r71863 | r71864 >
Date:22:30, 28 August 2010
Author:dale
Status:deferred
Tags:
Comment:
* sync with latest kaltura html5 lib updates
** some skin theme loading fixes
** server side seek for kaltura player
* other minor cleanup
Modified paths:
  • /branches/MwEmbedStandAlone/README (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/loader.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerKplayer.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/kskin/mw.PlayerSkinKskin.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/tests/Player_ServerSideSeek.html (added) (history)
  • /branches/MwEmbedStandAlone/modules/EmbedPlayer/tests/Player_Sources.html (added) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/Sequencer.i18n.php (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/actions/mw.SequencerActionsEdit.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/actions/mw.SequencerActionsSequence.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerMenu.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerServer.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/remotes/mw.MediaWikiRemoteSequencer.js (modified) (history)
  • /branches/MwEmbedStandAlone/mwEmbed.js (modified) (history)
  • /branches/MwEmbedStandAlone/remotes/mediaWiki.js (modified) (history)

Diff [purge]

Index: branches/MwEmbedStandAlone/mwEmbed.js
@@ -505,7 +505,7 @@
506506 // Issue the load request check check loadStates to see if we are
507507 // "done"
508508 for( var loadName in loadStates ) {
509 - mw.log("loadMany: load: " + loadName );
 509+ //mw.log("loadMany: load: " + loadName );
510510 this.load( loadName, function ( loadName ) {
511511 loadStates[ loadName ] = 1;
512512
@@ -1834,6 +1834,18 @@
18351835 return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src;
18361836 }
18371837 };
 1838+ /**
 1839+ * Check if a given source string is likely a url
 1840+ *
 1841+ * @return {boolean}
 1842+ * true if a url
 1843+ * false if a string
 1844+ */
 1845+ mw.isUrl = function( src ){
 1846+ var parsedSrc = mw.parseUri( src );
 1847+ // if the url is just a string source and host will match
 1848+ return ( parsedSrc.host != parsedSrc.source );
 1849+ };
18381850
18391851 /**
18401852 * Escape quotes in a text string
@@ -1987,23 +1999,30 @@
19882000 * @return true if found, return false if not found
19892001 */
19902002 mw.hasJQueryUiCss = function(){
1991 - var hasUiCss = false;
 2003+ var hasUiCss = false;
 2004+ var cssStyleSheetNames = ['jquery-ui-1.7.2.css', 'jquery-ui.css'];
19922005 // Load the jQuery ui skin if usability skin not set
19932006 $j( 'link' ).each( function( na, linkNode ){
1994 - if( $j( linkNode ).attr( 'href' ).indexOf( 'jquery-ui-1.7.2.css' ) != -1 ) {
1995 - hasUiCss = true;
1996 - return true;
1997 - }
 2007+ $j.each( cssStyleSheetNames, function(inx, sheetName ){
 2008+ if( $j( linkNode ).attr( 'href' ).indexOf( sheetName ) != -1 ){
 2009+ hasUiCss = true;
 2010+ return true;
 2011+ }
 2012+ })
19982013 } );
1999 - // Check all the "style" nodes for @import of jquery-ui-1.7.2.css
 2014+ // Check all the "style" nodes for @import for sheet name
20002015 // xxx Note: we could do this a bit cleaner with regEx
20012016 $j( 'style' ).each( function( na, styleNode ){
2002 - if( $j( styleNode ).text().indexOf( '@import' ) != -1
2003 - && $j( styleNode ).text().indexOf( 'jquery-ui-1.7.2.css' ) != -1 ){
 2017+ $j.each( cssStyleSheetNames, function(inx, sheetName ){
 2018+ if( $j( styleNode ).text().indexOf( '@import' ) != -1
 2019+ &&
 2020+ $j( styleNode ).text().indexOf( sheetName ) != -1 )
 2021+ {
20042022 hasUiCss=true;
2005 - }
2006 - });
2007 -
 2023+ return true;
 2024+ }
 2025+ });
 2026+ });
20082027 return hasUiCss;
20092028 }
20102029
Index: branches/MwEmbedStandAlone/README
@@ -1,5 +1,5 @@
2 -# Kaltura HTML5 Media Javascript Library
32
 3+
44 ## Library Overview
55
66 [html5]: https://developer.mozilla.org/En/Using_audio_and_video_in_FireFox
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/loader.js
@@ -14,7 +14,7 @@
1515
1616 // A default apiProvider ( ie where to lookup subtitles, video properties etc )
1717 // NOTE: Each player instance can also specify a specific provider
18 - "EmbedPlayer.ApiProvider" : "commons",
 18+ "EmbedPlayer.ApiProvider" : "local",
1919
2020 // What tags will be re-written to video player by default
2121 // Set to empty string or null to avoid automatic video tag rewrites to embedPlayer
@@ -210,41 +210,26 @@
211211 * @param {Array} dependencyRequest The library request array
212212 */
213213 mw.embedPlayerUpdateLibraryRequest = function(playerElement, dependencyRequest ){
214 - var playerClassName = $j( playerElement ).attr( 'class' );
215 - var playerSkins = {};
216 -
217 - // Set playerClassName to default
218 - if( ! playerClassName ){
219 - playerClassName = mw.getConfig( 'EmbedPlayer.SkinName' );
220 - }
221 - // compre with lower case:
222 - playerClassName = playerClassName.toLowerCase();
223 - for( var n=0; n < mw.validSkins.length ; n++ ) {
224 - // Get any other skins that we need to load
225 - // That way skin js can be part of the single script-loader request:
226 - if( playerClassName.indexOf( mw.validSkins[ n ].toLowerCase() ) !== -1) {
227 - // Add skin name to playerSkins
228 - playerSkins[ mw.validSkins[ n ].toLowerCase() ] = true;
229 - }
 214+ var skinName = $j( playerElement ).attr( 'class' );
 215+ // Set playerClassName to default if unset or not a valid skin
 216+ if( ! skinName || $j.inArray( skinName.toLowerCase(), mw.validSkins ) == -1 ){
 217+ skinName = mw.getConfig( 'EmbedPlayer.SkinName' );
230218 }
 219+ skinName = skinName.toLowerCase();
 220+ // Add the skin to the request
 221+ var skinCaseName = skinName.charAt(0).toUpperCase() + skinName.substr(1);
 222+ // The skin js:
 223+ if( $j.inArray( 'mw.PlayerSkin' + skinCaseName, dependencyRequest ) == -1 ){
 224+ dependencyRequest.push( 'mw.PlayerSkin' + skinCaseName );
 225+ }
 226+ // The skin css
 227+ if( $j.inArray( 'mw.style.PlayerSkin' + skinCaseName, dependencyRequest ) == -1 ){
 228+ dependencyRequest.push( 'mw.style.PlayerSkin' + skinCaseName );
 229+ }
231230
232 -
233 - // Add the player skins css and js to the load request:
234 - for( var pSkin in playerSkins ) {
235 - // Make sure first letter of skin is upper case to load skin class:
236 - var f = pSkin.charAt(0).toUpperCase();
237 - pSkin = f + pSkin.substr(1);
238 -
239 - // Add skin js
240 - dependencyRequest.push( 'mw.PlayerSkin' + pSkin );
241 - // Add the skin css
242 - dependencyRequest.push( 'mw.style.PlayerSkin' + pSkin );
243 - }
244 -
245231 // Allow extension to extend the request.
246232 $j( mw ).trigger( 'LoaderEmbedPlayerUpdateRequest',
247233 [ playerElement, dependencyRequest ] );
248 -
249234 }
250235
251236 } )( window.mw );
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/tests/Player_ServerSideSeek.html
@@ -0,0 +1,14 @@
 2+<html>
 3+ <head>
 4+ <script type="text/javascript" src="http://html5.kaltura.org/js"></script>
 5+ </head>
 6+ <body>
 7+ <h2>mwEmbed / archive.org server side seek</h2>
 8+
 9+ <video poster="http://www.archive.org/download/night_of_the_living_dead/format=Thumbnail&x.jpg"
 10+ style="width:400px;height:300px" durationHint="5717.21">
 11+ <source URLTimeEncoding="true" src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead_512kb.mp4"/>
 12+ <source URLTimeEncoding="true" src="http://www.archive.org/download/night_of_the_living_dead/night_of_the_living_dead.ogv"/>
 13+ </video>
 14+ </body>
 15+</html>
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/tests/Player_Sources.html
@@ -0,0 +1,20 @@
 2+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 3+<html xmlns="http://www.w3.org/1999/xhtml">
 4+<head>
 5+<title>Player sources</title>
 6+
 7+<script type="text/javascript" src="../../../mwEmbed.js?debug=true"></script>
 8+</head>
 9+<body>
 10+
 11+
 12+<video poster="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream.jpg"
 13+ duration="10:53" preload="auto">
 14+ <source type="video/webm" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream_400p.webm" />
 15+ <source type="video/h264" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream_iphone.m4v" />
 16+ <source type="video/ogg" src="http://cdn.kaltura.org/apis/html5lib/kplayer-examples/media/elephants-dream_400p.ogv" />
 17+</video>
 18+
 19+
 20+</body>
 21+</html>
\ No newline at end of file
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js
@@ -75,7 +75,7 @@
7676 /*
7777 * The default video attributes supported by embedPlayer
7878 */
79 -mw.setConfig( 'embedPlayerAttributes', {
 79+mw.setConfig( 'EmbedPlayer.Attributes', {
8080 /*
8181 * Base html element attributes:
8282 */
@@ -264,7 +264,7 @@
265265 * Attributes Object can include any key value pair that would otherwise be
266266 * an attribute in the html element.
267267 *
268 - * also see: mw.getConfig( 'embedPlayerAttributes' )
 268+ * also see: mw.getConfig( 'EmbedPlayer.Attributes' )
269269 *
270270 * @param {Function=} callback Optional Function to be called once video interfaces are ready
271271 *
@@ -369,6 +369,8 @@
370370 // Functions to run after the video interface is ready
371371 callbackFunctions : null,
372372
 373+ playerElementQueue: [],
 374+
373375 /**
374376 * Constructor initializes callbackFunctions and playerList
375377 */
@@ -422,13 +424,13 @@
423425 playerElement.id = 'vid' + ( this.playerList.length + 1 );
424426 }
425427 mw.log('EmbedPlayerManager: addElement:: ' + playerElement.id );
426 -
 428+
427429 // Add the element id to playerList
428430 this.playerList.push( playerElement.id );
429431
430432 // Check for player attributes such as skins or plugins attributes
431433 // that add to the request set
432 - var playerDependencyRequest = [ ];
 434+ var playerDependencyRequest = [];
433435
434436 // merge in any custom attributes
435437 $j.extend( playerElement, attributes );
@@ -436,10 +438,11 @@
437439 // Update the list of dependent libraries for the player
438440 // ( allows extensions to add to the dependency list )
439441 mw.embedPlayerUpdateLibraryRequest( playerElement, playerDependencyRequest );
440 -
 442+
441443 // Load any skins we need then swap in the interface
442 - mw.load( playerDependencyRequest, function() {
443 - var waitForMeta = true;
 444+ mw.load( playerDependencyRequest, function() {
 445+ var waitForMeta = true;
 446+
444447 // Be sure to "stop" the target ( sometimes firefox keeps playing the video even
445448 // though its been removed from the DOM )
446449 if( playerElement.pause ){
@@ -497,7 +500,7 @@
498501 playerElement.removeEventListener( "loadedmetadata", runPlayerSwap, true );
499502 playerElement.addEventListener( "loadedmetadata", runPlayerSwap, true );
500503
501 - // Time-out of 5 seconds ( maybe still playable but no timely metadata )
 504+ // Time-out of 5 seconds ( maybe still playable but no timely metadata )
502505 setTimeout( runPlayerSwap, 5000 );
503506 return ;
504507 } else {
@@ -850,11 +853,11 @@
851854 },
852855
853856 /** URI function.
854 - * @param {Number} seek_time_sec Int: Used to adjust the URI for url based seeks)
 857+ * @param {Number} serverSeekTime Int: Used to adjust the URI for url based seeks)
855858 * @return {String} the URI of the source.
856859 */
857 - getSrc : function( seek_time_sec ) {
858 - if ( !seek_time_sec || !this.URLTimeEncoding ) {
 860+ getSrc : function( serverSeekTime ) {
 861+ if ( !serverSeekTime || !this.URLTimeEncoding ) {
859862 return this.src;
860863 }
861864 var endvar = '';
@@ -863,7 +866,7 @@
864867 }
865868 return mw.replaceUrlParams( this.src,
866869 {
867 - 't': mw.seconds2npt( seek_time_sec ) + endvar
 870+ 't': mw.seconds2npt( serverSeekTime ) + endvar
868871 }
869872 );
870873 },
@@ -1032,6 +1035,7 @@
10331036 if ( $j( videoElement ).attr( "src" ) ) {
10341037 _this.tryAddSource( videoElement );
10351038 }
 1039+
10361040 // Process elements source children
10371041 $j( videoElement ).find( 'source,track' ).each( function( ) {
10381042 _this.tryAddSource( this );
@@ -1126,7 +1130,7 @@
11271131 * Selects the default source via cookie preference, default marked, or by id order
11281132 */
11291133 autoSelectSource: function() {
1130 - mw.log( 'EmbedPlayer::mediaElement::autoSelectSource:' );
 1134+ mw.log( 'EmbedPlayer::mediaElement::autoSelectSource:' + this.id);
11311135 // Select the default source
11321136 var playableSources = this.getPlayableSources();
11331137 var flash_flag = ogg_flag = false;
@@ -1359,7 +1363,7 @@
13601364 'cmmlData': null,
13611365
13621366 // Stores the seek time request, Updated by the doSeek function
1363 - 'seek_time_sec' : 0,
 1367+ 'serverSeekTime' : 0,
13641368
13651369 // If the embedPlayer is current 'seeking'
13661370 'seeking' : false,
@@ -1390,14 +1394,18 @@
13911395 customAttributes = { };
13921396 }
13931397
1394 - var playerAttributes = mw.getConfig( 'embedPlayerAttributes' );
1395 -
 1398+ var playerAttributes = mw.getConfig( 'EmbedPlayer.Attributes' );
13961399 // Setup the player Interface from supported attributes:
13971400 for ( var attr in playerAttributes ) {
13981401 if ( customAttributes[ attr ] || customAttributes[ attr ] === false ) {
13991402 this[ attr ] = customAttributes[ attr ];
1400 - } else if ( element.getAttribute( attr ) ) {
1401 - this[ attr ] = element.getAttribute( attr );
 1403+ } else if ( element.getAttribute( attr ) != null ) {
 1404+ // boolean attributes
 1405+ if( element.getAttribute( attr ) == '' ){
 1406+ this[ attr ] = true;
 1407+ } else {
 1408+ this[ attr ] = element.getAttribute( attr );
 1409+ }
14021410 } else {
14031411 this[attr] = playerAttributes[attr];
14041412 }
@@ -1612,7 +1620,7 @@
16131621 // Scope the end of check for player sources so it can be called in a callback
16141622 var finishCheckPlayerSources = function(){
16151623 // Run embedPlayer sources hook
1616 - mw.runTriggersCallback( _this, 'checkPlayerSourcesEvent', function(){
 1624+ mw.runTriggersCallback( _this, 'checkPlayerSourcesEvent', function(){
16171625 _this.checkForTimedText();
16181626 })
16191627 }
@@ -1643,7 +1651,7 @@
16441652
16451653 // Set local apiProvider via config if not defined
16461654 if( !_this.apiProvider ) {
1647 - _this.apiProvider = 'local';
 1655+ _this.apiProvider = mw.getConfig( 'EmbedPlayer.ApiProvider' );
16481656 }
16491657
16501658 // Setup the request
@@ -1930,7 +1938,8 @@
19311939 },
19321940
19331941 /**
1934 - * Seek function (should be implemented by embed player interface )
 1942+ * Seek function ( should be implemented by embedPlayer interface playerNative, playerKplayer etc. )
 1943+ * embedPlayer doSeek only handles URL time seeks
19351944 */
19361945 doSeek: function( percent ) {
19371946 var _this = this;
@@ -1940,18 +1949,21 @@
19411950 $j( this.embedPlayer ).trigger( 'onSeek' );
19421951
19431952 // See if we should do a server side seek ( player independent )
1944 - if ( this.supportsURLTimeEncoding() ) {
1945 - // Make sure this.seek_time_sec is up-to-date:
1946 - this.seek_time_sec = mw.npt2seconds( this.start_npt ) + parseFloat( percent * this.getDuration() );
1947 - mw.log( 'EmbedPlayer::doSeek:: updated seek_time_sec: ' + mw.seconds2npt ( this.seek_time_sec ) );
 1953+ if ( this.supportsURLTimeEncoding() ) {
 1954+ mw.log( 'EmbedPlayer::doSeek:: updated serverSeekTime: ' + mw.seconds2npt ( this.serverSeekTime ) );
19481955 this.stop();
19491956 this.didSeekJump = true;
 1957+ // Make sure this.serverSeekTime is up-to-date:
 1958+ this.serverSeekTime = mw.npt2seconds( this.start_npt ) + parseFloat( percent * this.getDuration() );
19501959 // Update the slider
1951 - this.updatePlayHead( percent );
1952 - }
 1960+ this.updatePlayHead( percent );
 1961+ }
 1962+
19531963 // Do play request in 100ms ( give the dom time to swap out the embed player )
1954 - setTimeout( function() {
 1964+ setTimeout( function() {
 1965+ _this.seeking = false;
19551966 _this.play()
 1967+ _this.monitor();
19561968 }, 100 );
19571969
19581970 // Run the onSeeking interface update
@@ -2050,7 +2062,7 @@
20512063
20522064 // Stop the clip (load the thumbnail etc)
20532065 this.stop();
2054 - this.seek_time_sec = 0;
 2066+ this.serverSeekTime = 0;
20552067 this.updatePlayHead( 0 );
20562068
20572069 // Make sure we are not in preview mode( no end clip actions in preview mode)
@@ -2215,9 +2227,9 @@
22162228
22172229 // reset seek_offset:
22182230 if ( this.mediaElement.selectedSource.URLTimeEncoding ) {
2219 - this.seek_time_sec = 0;
 2231+ this.serverSeekTime = 0;
22202232 } else {
2221 - this.seek_time_sec = mw.npt2seconds( start_npt );
 2233+ this.serverSeekTime = mw.npt2seconds( start_npt );
22222234 }
22232235 },
22242236
@@ -2773,8 +2785,8 @@
27742786 // no longer seeking:
27752787 this.didSeekJump = false;
27762788
2777 - // reset current time and prev time
2778 - this.currentTime = this.previousTime = 0;
 2789+ // reset current time and prev time and seek offset
 2790+ this.currentTime = this.previousTime = this.serverSeekTime = 0;
27792791
27802792 // Previous player set time
27812793
@@ -2979,7 +2991,12 @@
29802992
29812993 // Update currentTime via embedPlayer
29822994 _this.currentTime = _this.getPlayerElementTime();
2983 -
 2995+
 2996+ // Update any offsets from server seek
 2997+ if( _this.serverSeekTime && _this.supportsURLTimeEncoding ){
 2998+ _this.currentTime = _this.serverSeekTime + _this.getPlayerElementTime()
 2999+ }
 3000+
29843001 // Update the previousTime ( so we can know if the user-javascript changed currentTime )
29853002 _this.previousTime = _this.currentTime;
29863003
@@ -3004,7 +3021,7 @@
30053022 _this.muted = _this.getPlayerElementMuted();
30063023 }
30073024
3008 - //mw.log( 'Monitor:: ' + this.currentTime + ' duration: ' + ( parseInt( this.getDuration() ) + 1 ) + ' is seek: ' + this.seeking );
 3025+ //mw.log( 'Monitor:: ' + this.currentTime + ' duration: ' + ( parseInt( this.getDuration() ) + 1 ) + ' is seeking: ' + this.seeking );
30093026 if ( this.currentTime >= 0 && this.duration ) {
30103027 if ( !this.userSlide && !this.seeking ) {
30113028 if ( parseInt( this.startOffset ) != 0 ) {
@@ -3054,7 +3071,8 @@
30553072 if( ! this.isStopped() ) {
30563073 if( !this.monitorInterval ){
30573074 this.monitorInterval = setInterval( function(){
3058 - _this.monitor();
 3075+ if( _this.monitor )
 3076+ _this.monitor();
30593077 }, this.monitorRate )
30603078 }
30613079 } else {
@@ -3163,9 +3181,9 @@
31643182 } ).show();
31653183
31663184 this.jump_time = options['start'];
3167 - this.seek_time_sec = mw.npt2seconds( options['start'] );
 3185+ this.serverSeekTime = mw.npt2seconds( options['start'] );
31683186 // trim output to
3169 - this.controlBuilder.setStatus( gM( 'mwe-embedplayer-seek_to', mw.seconds2npt( this.seek_time_sec ) ) );
 3187+ this.controlBuilder.setStatus( gM( 'mwe-embedplayer-seek_to', mw.seconds2npt( this.serverSeekTime ) ) );
31703188 mw.log( 'DO update: ' + this.jump_time );
31713189 this.updateThumbTime( rel_start_sec );
31723190 },
@@ -3191,7 +3209,7 @@
31923210 */
31933211 getSrc: function() {
31943212 if( this.mediaElement.selectedSource ){
3195 - return this.mediaElement.selectedSource.getSrc( this.seek_time_sec );
 3213+ return this.mediaElement.selectedSource.getSrc( this.serverSeekTime );
31963214 }
31973215 return false;
31983216 },
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/skins/kskin/mw.PlayerSkinKskin.js
@@ -323,7 +323,7 @@
324324 },
325325
326326 /**
327 - * Show the credit screen (presently specific to kaltura skin )
 327+ * Show the credit screen ( presently specific to kaltura skin )
328328 */
329329 showCredits: function() {
330330 // Set up the shortcuts:
Index: branches/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerKplayer.js
@@ -207,6 +207,16 @@
208208 */
209209 doSeek: function( percentage ) {
210210 var _this = this;
 211+ if ( this.supportsURLTimeEncoding() ){
 212+ // Make sure we could not do a local seek instead:
 213+ if ( !( percentage < this.bufferedPercent && this.playerElement.duration && !this.didSeekJump )) {
 214+ // We support URLTimeEncoding call parent seek:
 215+ this.parent_doSeek( percentage );
 216+ return;
 217+ }
 218+ }
 219+
 220+
211221 if( this.playerElement ) {
212222 var seekTime = percentage * this.getDuration();
213223
Index: branches/MwEmbedStandAlone/modules/Sequencer/Sequencer.i18n.php
@@ -12,10 +12,12 @@
1313
1414 'mwe-sequencer-visual-editor'=> "Visual sequence editor",
1515 'mwe-sequencer-text-editor-warn'=> 'Text XML editor ( not recommended ) ',
 16+ 'mwe-sequencer-restore-text-edit' => '[$1 Restore text editor] ( note this <i>highly</i> recommended that you use the visual editor )',
 17+
1618 'mwe-sequencer-loading-timeline' => 'Loading timeline ...',
1719 'mwe-sequencer-loading-player' => 'Loading player ...',
1820 'mwe-sequencer-loading-menu' => 'Loading menu ...',
19 - 'mwe-sequencer-loading-asset' => 'Loading asset ...',
 21+ 'mwe-sequencer-loading-asset' => 'Loading asset ...',
2022
2123 'mwe-sequencer-no_selected_resource' => '<h3>No resource selected</h3> Select a clip to enable editing.',
2224 'mwe-sequencer-untitled-sequence' => 'Untitled sequence',
@@ -84,11 +86,11 @@
8587 'mwe-sequencer-save_done' => 'Save complete',
8688
8789 'mwe-sequencer-open-summary' => "Enter the name of the sequence you would like to open",
88 -
 90+ 'mwe-sequencer-new-summary' => "Enter the name of the sequence you would like to create",
8991
9092
91 - 'mwe-sequencer-not-published' => 'This sequence has not yet been published. <i>Browser preview is shown</i>. <b>[$1 Review and publish this sequence]</b>.',
92 - 'mwe-sequencer-published-out-of-date' =>'This published sequence is not the most recent version. You can <b>[$1 review and publish]</b> the most recent version.',
 93+ 'mwe-sequencer-not-published' => 'This sequence has not yet been published. Select <i>sequence -> publish</i> in the <b>[$1 sequence editor]</b> to publish this sequence.',
 94+ 'mwe-sequencer-published-out-of-date' =>'This published sequence is not the most recent version. Select <i>sequence -> publish</i> in the <b>[$1 sequence editor]</b> to publish this sequence',
9395
9496 'mwe-sequencer-already-published' => "The most recent version of this sequence is already published",
9597
Index: branches/MwEmbedStandAlone/modules/Sequencer/actions/mw.SequencerActionsSequence.js
@@ -15,8 +15,73 @@
1616 init: function( sequencer ) {
1717 this.sequencer = sequencer;
1818 },
19 -
2019 /**
 20+ * present an new dialog to the user and open the sequence in a new window
 21+ * ( presently very similar to open )
 22+ */
 23+ newSequence : function(){
 24+ var _this = this;
 25+ var $content = $j('<div />').append(
 26+ gM('mwe-sequencer-new-summary' ),
 27+ $j('<input />')
 28+ .css({ 'width': 400 })
 29+ .attr({
 30+ 'id' : 'sequenceNewNameInput',
 31+ 'maxlength': 255
 32+ })
 33+ // Make sure keys press does not affect the sequencer interface
 34+ .sequencerInput( _this.sequencer )
 35+ );
 36+ // XXX todo we should have an autocomplete on sequence name!
 37+
 38+ var buttons = {};
 39+ buttons[ gM('mwe-cancel') ] = function(){ $j( this ).dialog( 'cancel' ) };
 40+
 41+ // For now just support server based open .. ideally we could browse for file
 42+ var $dialog = mw.addDialog({
 43+ 'resizable':'true',
 44+ 'title' : gM('mwe-sequencer-menu-sequence-new-desc'),
 45+ 'content' : $content,
 46+ 'buttons' : buttons,
 47+ 'width' : 450
 48+ });
 49+ // Add a special open button
 50+ $dialog.parent().find( '.ui-dialog-buttonpane' ).prepend(
 51+ $j.button({
 52+ 'icon' : 'document',
 53+ 'text' : gM('mwe-sequencer-menu-sequence-new')
 54+ })
 55+ // Match button layout
 56+ .css({
 57+ 'margin':'0.5em 0.4em 0.5em 0',
 58+ 'padding' : '0.2em 1.4em 0.3em'
 59+ })
 60+ .attr({
 61+ 'id' : 'sequenceOpenButton',
 62+ 'target' : '_new',
 63+ 'href' : '#'
 64+ }).click( function(){
 65+ // Update the link
 66+ $j(this).attr({
 67+ 'href':
 68+ mw.getRemoteSequencerLink(
 69+ mw.escapeQuotesHTML(
 70+ _this.sequencer.getServer().getSequenceEditUrl(
 71+ // ( Sequence: is automatically pre-appended with getSequencePageUrl
 72+ // ( don't use Sequence: in the title )
 73+ $j('#sequenceNewNameInput').val().replace(/Sequence:/i, '')
 74+ )
 75+ )
 76+ )
 77+ });
 78+ // Close the dialog
 79+ $j(this).dialog( 'close' );
 80+ // Follow the link
 81+ return true;
 82+ })
 83+ )
 84+ },
 85+ /**
2186 * present an open dialog to the user, and open the sequence in a new window
2287 */
2388 open: function(){
@@ -412,7 +477,7 @@
413478 if( _this.sequencer.getOption('onExitCallback') ){
414479 // Send a flag of weather the sequence 'changed' or not
415480 _this.sequencer.getOption('onExitCallback')(
416 - _this.sequencer.getServer().hasSequenceBeenSaved()
 481+ _this.sequencer.getServer().hasSequenceBeenSavedOrPublished()
417482 );
418483 }
419484 $j( this ).remove();
Index: branches/MwEmbedStandAlone/modules/Sequencer/actions/mw.SequencerActionsEdit.js
@@ -76,7 +76,7 @@
7777
7878 // Enable the undo option:
7979 this.sequencer.getMenu().enableMenuItem( 'edit', 'undo' );
80 - this.sequencer.getMenu().enableMenuItem( 'sequencer', 'save' );
 80+ this.sequencer.getMenu().enableMenuItem( 'sequence', 'save' );
8181 },
8282
8383 /**
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerMenu.js
@@ -36,7 +36,7 @@
3737 'save_divider': 'divider',
3838 'save' : {
3939 'icon' : 'disk',
40 - 'disabled' : true,
 40+ 'disabled' : false,
4141 'shortCut' : 'ctrl S',
4242 'action' : function( _this ){
4343 mw.log("SequencerMenu::save");
@@ -279,6 +279,9 @@
280280 },
281281
282282 enableMenuItem: function( menuKey, menuItemKey ){
 283+ if( !this.menuConfig[ menuKey ] || !this.menuConfig[ menuKey ][ menuItemKey ] ){
 284+ mw.log("Error: SequencerMenu: " + menuKey + ' ' + menuItemKey + ' is not defined');
 285+ }
283286 this.menuConfig[ menuKey ][ menuItemKey ].disabled = false;
284287 $menuItemTarget = $j('#' + this.getMenuItemId( menuKey, menuItemKey ) );
285288
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerServer.js
@@ -100,11 +100,11 @@
101101 hasLocalChanges: function(){
102102 return ( this.serverSmilXml != this.sequencer.getSmil().getXMLString() );
103103 },
104 - // Check if the sequence was saved in this edit sesssion
105 - hasSequenceBeenSaved: function(){
106 - return this.sequenceSaved;
 104+ // Check if the sequence was saved in this edit session
 105+ hasSequenceBeenSavedOrPublished: function(){
 106+ return this.sequenceSaved || this.sequencePublished
107107 },
108 - // Get a save token, if unable to do so return false
 108+ // Get a save token, if unable to do so return false
109109 getSaveToken: function( callback ){
110110 var _this = this;
111111 if( this.saveToken != null ){
@@ -196,8 +196,9 @@
197197 'prop':'revisions',
198198 'titles' : _this.titleKey,
199199 'rvprop' : 'user|comment|timestamp'
200 - };
 200+ };
201201 mw.getJSON( _this.getApiUrl(), request, function( data ) {
 202+ debugger;
202203 if( data.query && data.pages ){
203204 for( page_id in data.pages ){
204205 var page = data.pages[page_id];
@@ -227,13 +228,8 @@
228229 * Get the sequencer 'edit' url
229230 */
230231 getSequenceEditUrl: function( titleKey ){
231 - if( !titleKey )
232 - titleKey = this.titleKey;
233 - // Check that we have a pagePathUrl config:
234 - if( !this.pagePathUrl ){
235 - return false;
236 - }
237 - return this.pagePathUrl.replace( '$1', 'Sequence:' + titleKey);
 232+ var viewUrl = this.getSequenceViewUrl( titleKey );
 233+ return mw.replaceUrlParams(viewUrl, {'action':'edit'})
238234 },
239235
240236 /**
@@ -262,6 +258,10 @@
263259 callback( _this.getApiUrl(), request );
264260 });
265261 });
 262+ },
 263+ // Setter for sequencePublished
 264+ sequencePublishUploadDone: function(){
 265+ this.sequencePublished = true;
266266 }
267267 }
268268
Index: branches/MwEmbedStandAlone/modules/Sequencer/remotes/mw.MediaWikiRemoteSequencer.js
@@ -11,11 +11,13 @@
1212 "mwe-sequencer-edit-sequence",
1313 "mwe-sequencer-embed-sequence",
1414 "mwe-sequencer-embed-sequence-desc",
15 - "mwe-sequencer-loading-sequencer",
 15+ "mwe-sequencer-loading-sequencer",
1616
1717 "mwe-sequencer-visual-editor",
1818 "mwe-sequencer-text-editor-warn",
 19+ "mwe-sequencer-restore-text-edit",
1920
 21+ "mwe-sequencer-loading-publish-render",
2022
2123 "mwe-sequencer-not-published",
2224 "mwe-sequencer-published-out-of-date"
@@ -55,7 +57,8 @@
5658 this.target = ( options.target )? options.target : this.target;
5759 },
5860
59 - drawUI: function() {
 61+ drawUI: function() {
 62+
6063 // Check page action
6164 if( this.action == 'view' ) {
6265 this.showViewUI();
@@ -101,34 +104,44 @@
102105 },
103106
104107 showEditUI: function(){
105 -
 108+ var _this = this;
106109 $j('#bodyContent').prepend(
107110 // Append switch visual / text editor links
108 - $j('<div />')
 111+ /*$j('<div />')
109112 .append(
110113 $j.button({
111114 'icon' : 'video',
112115 'text' : gM( "mwe-sequencer-visual-editor")
113116 }).click( function(){
114 - $j('#sequencerContainer').show();
115 - $j('#editform').hide();
 117+ $j('#editform').hide();
 118+ $j('#sequencerContainer').show();
116119 }),
117120 $j.button({
118 - 'icon' : 'script'
 121+ 'icon' : 'script',
119122 'text' : gM("mwe-sequencer-text-editor-warn")
120123 }).click(function(){
121124 $j('#sequencerContainer').hide();
122125 $j('#editform').show();
123 - }),
124 - $j('<div />')
125 - .css({
126 - 'width' : '100%',
127 - 'height' : '700px'
128 - })
129 - .attr({
130 - 'id', 'sequencerContainer'
131 - })
 126+ })
 127+ )*/
 128+ ).append(
 129+ $j('<div />')
 130+ .css({
 131+ 'position' : 'relative',
 132+ 'width' : '100%',
 133+ 'height' : '620px'
 134+ })
 135+ .attr({
 136+ 'id': 'sequencerContainer'
 137+ }),
 138+ $j('<div />')
 139+ .append(
 140+ gM("mwe-sequencer-restore-text-edit", $j('<a />').click(function(){
 141+ $j('#sequencerContainer').hide();
 142+ $j('#editform').show();
 143+ }) )
132144 )
 145+ .css( {'cursor': 'pointer', 'font-size':'x-small' })
133146 );
134147 // load the sequence editor with the sequencerContainer target
135148 mw.load( 'Sequencer', function(){
@@ -161,65 +174,73 @@
162175 // no flattened file found
163176 $embedPlayer.append(
164177 $j( '<div />').append(
165 - gM('mwe-sequencer-not-published')
 178+ gM('mwe-sequencer-not-published',
 179+ $j('<a />').click( function(){
 180+ _this.showEditor();
 181+ })
 182+ )
166183 )
167184 .addClass( 'ui-state-highlight' )
168 - )
169 - return ;
170 - }
171 - for( var pageId in data.query.pages) {
172 - var page = data.query.pages[ pageId ];
173 -
174 - // Check that the file has a later revision than the
175 - // page. ( up to date sequences always are later than
176 - // the revision of the page saved ).
177 - if( page.revisions && page.revisions[0] ){
178 - if( page.revisions[0].revid < wgCurRevisionId ){
179 - // flattened file out of date
180 - $embedPlayer.append(
181 - $j('<div />').append(
182 - gM('mwe-sequencer-published-out-of-date')
183 - ).addClass( 'ui-state-highlight' )
184 - )
 185+ )
 186+ } else {
 187+ for( var pageId in data.query.pages) {
 188+ var page = data.query.pages[ pageId ];
 189+
 190+ // Check that the file has a later revision than the
 191+ // page. ( up to date sequences always are later than
 192+ // the revision of the page saved ).
 193+ if( page.revisions && page.revisions[0] ){
 194+ if( page.revisions[0].revid < wgCurRevisionId ){
 195+ // flattened file out of date
 196+ $embedPlayer.append(
 197+ $j('<div />').append(
 198+ gM('mwe-sequencer-published-out-of-date',
 199+ $j('<a />').click( function(){
 200+ _this.showEditor();
 201+ })
 202+ )
 203+ ).addClass( 'ui-state-highlight' )
 204+ )
 205+ }
185206 }
186 - }
187 - if( page.imageinfo && page.imageinfo[0] ){
188 - var imageinfo = page.imageinfo[0];
189 - var duration = 0;
190 - for( var i=0;i< imageinfo.metadata.length; i++){
191 - if( imageinfo.metadata[i].name == 'length' ){
192 - duration = Math.round(
193 - imageinfo.metadata[i].value * 1000
194 - ) / 1000;
 207+ if( page.imageinfo && page.imageinfo[0] ){
 208+ var imageinfo = page.imageinfo[0];
 209+ var duration = 0;
 210+ for( var i=0;i< imageinfo.metadata.length; i++){
 211+ if( imageinfo.metadata[i].name == 'length' ){
 212+ duration = Math.round(
 213+ imageinfo.metadata[i].value * 1000
 214+ ) / 1000;
 215+ }
195216 }
 217+ // Append a player to the embedPlayer target
 218+ // -- special title key sequence name bound
 219+ $embedPlayer.append(
 220+ $j('<video />')
 221+ .attr({
 222+ 'id' : 'embedSequencePlayer',
 223+ 'poster' : imageinfo.thumburl,
 224+ 'durationHint' : duration,
 225+ 'apiTitleKey' : page.title.replace('File:',''),
 226+ })
 227+ .addClass('kskin')
 228+ .css({
 229+ 'width': imageinfo.thumbwidth,
 230+ 'height' : imageinfo.thumbheight
 231+ })
 232+ .append(
 233+ // ogg source
 234+ $j('<source />')
 235+ .attr({
 236+ 'type': 'video/ogg',
 237+ 'src' : imageinfo.url
 238+ })
 239+ )
 240+ )
196241 }
197 - // Append a player to the embedPlayer target
198 - // -- special title key sequence name bound
199 - $embedPlayer.append(
200 - $j('<video />')
201 - .attr({
202 - 'id' : 'embedSequencePlayer',
203 - 'poster' : imageinfo.thumburl,
204 - 'durationHint' : duration,
205 - 'apiTitleKey' : page.title.replace('File:',''),
206 - })
207 - .addClass('kskin')
208 - .css({
209 - 'width': imageinfo.thumbwidth,
210 - 'height' : imageinfo.thumbheight
211 - })
212 - .append(
213 - // ogg source
214 - $j('<source />')
215 - .attr({
216 - 'type': 'video/ogg',
217 - 'src' : imageinfo.url
218 - })
219 - )
220 - )
221 - }
222 - }
223 - var width = ( imageinfo.thumbwidth )?imageinfo.thumbwidth : '400px';
 242+ }
 243+ }
 244+ var width = ( imageinfo && imageinfo.thumbwidth )?imageinfo.thumbwidth : '400px';
224245 // Display embed sequence
225246 $j( _this.target ).empty().append(
226247 $j('<div />')
@@ -294,9 +315,8 @@
295316 )
296317 .css( {'width':'200px', 'margin':'auto'})
297318 )
298 - )
299 - mw.load( 'Sequencer', function(){
300 - var _this = this;
 319+ )
 320+ mw.load( 'Sequencer', function(){
301321 // Send a jquery ui style destroy command ( in case the editor is re-invoked )
302322 $j('#edit_sequence_container').sequencer( 'destroy');
303323 $j('#edit_sequence_container').sequencer( _this.getSequencerConfig() );
Index: branches/MwEmbedStandAlone/remotes/mediaWiki.js
@@ -132,11 +132,12 @@
133133 if( wgAction == 'edit' ){
134134 mwAddCommonStyleSheet();
135135 var body = document.getElementById( 'bodyContent' );
136 - body.innerHTML = "<div class=\"loadingSpinner\"></div>" + body.innerHTML;
 136+ body.innerHTML = "<div class=\"loadingSpinner sequenceLoader\"></div>" + body.innerHTML;
137137 }
138138 loadMwEmbed( [ 'mw.MediaWikiRemoteSequencer' ], function(){
139 - $j('.loadingSpinner').remove();
140 - $j('#editform').hide();
 139+ $j('#editform,.mw-newarticletext').hide();
 140+ $j('.sequenceLoader').hide();
 141+
141142 var remote = new mw.MediaWikiRemoteSequencer({
142143 'action': wgAction,
143144 'title' : wgTitle,

Status & tagging log