r71833 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r71832‎ | r71833 | r71834 >
Date:00:48, 28 August 2010
Author:dale
Status:deferred
Tags:
Comment:
improved remote sequencer page edit support ( incomplete commit msg )
Modified paths:
  • /branches/MwEmbedStandAlone/modules/Playlist/mw.Playlist.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Playlist/mw.PlaylistHandlerMediaRss.js (modified) (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.SequencerAddByUrl.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerConfig.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerKeyBindings.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/mw.SequencerTimeline.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/Sequencer/remotes/mw.MediaWikiRemoteSequencer.js (modified) (history)
  • /branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBuffer.js (modified) (history)
  • /branches/MwEmbedStandAlone/mwEmbed.js (modified) (history)
  • /branches/MwEmbedStandAlone/remotes/mediaWiki.js (modified) (history)

Diff [purge]

Index: branches/MwEmbedStandAlone/mwEmbed.js
@@ -47,7 +47,9 @@
4848 mw.validSkins = [ 'mvpcf', 'kskin' ];
4949
5050 // Storage variable for loaded style sheet keys
51 - mw.style = { };
 51+ if( ! mw.style ){
 52+ mw.style = { };
 53+ }
5254
5355 /**
5456 * Configuration System:
Index: branches/MwEmbedStandAlone/modules/Playlist/mw.PlaylistHandlerMediaRss.js
@@ -7,6 +7,9 @@
88 // Set the media rss namespace
99 mediaNS: 'http://search.yahoo.com/mrss/',
1010
 11+ // If playback should continue to the next clip on clip complete
 12+ autoContinue: true,
 13+
1114 init: function ( Playlist ){
1215 this.playlist = Playlist;
1316 },
@@ -21,13 +24,24 @@
2225 callback( this.$rss );
2326 return ;
2427 }
 28+
 29+ // Show an error if a cross domain request:
 30+ if( ! mw.isLocalDomain( this.getSrc() ) ) {
 31+ mw.log("Error: trying to get cross domain playlist source: " + this.getSrc() );
 32+ }
 33+
2534 // Note this only works with local sources
26 - $j.get( mw.absoluteUrl( this.playlist.src ), function( data ){
 35+ $j.get( mw.absoluteUrl( this.getSrc() ), function( data ){
2736 _this.$rss = $j( data );
2837 callback( _this.$rss );
2938 });
3039 },
31 -
 40+ hasMultiplePlaylists: function(){
 41+ return false;
 42+ },
 43+ getSrc: function(){
 44+ return this.playlist.src;
 45+ },
3246 // Get clip count
3347 getClipCount: function(){
3448 if( !this.$rss ){
@@ -71,7 +85,7 @@
7286 getClipPoster: function ( clipIndex ){
7387 var $item = this.$rss.find('item').eq( clipIndex );
7488 var mediaThumb = $item.get(0).getElementsByTagNameNS( this.mediaNS, 'thumbnail' );
75 - mw.log( 'MEDIAthumb: ' + $j( mediaThumb ).attr('url' ) );
 89+ mw.log( 'mw.PlaylistMediaRss::getClipPoster: ' + $j( mediaThumb ).attr('url' ) );
7690 if( mediaThumb && $j( mediaThumb ).attr('url' ) ){
7791 return $j( mediaThumb ).attr('url' );
7892 }
Index: branches/MwEmbedStandAlone/modules/Playlist/mw.Playlist.js
@@ -77,10 +77,10 @@
7878 // Set the target to loadingSpinner:
7979 $j( this.target ).empty().loadingSpinner();
8080
81 - this.loadPlaylistHandler( function( playlistHandler ){
82 - mw.log("mw.Playlist::loaded playlist handler");
 81+ this.loadPlaylistHandler( function( sourceHandler ){
 82+ mw.log("mw.Playlist::loaded playlist set");
8383 // Check if load failed or empty playlist
84 - if( _this.sourceHandler.getClipList().length == 0 ){
 84+ if( sourceHandler.getClipList().length == 0 ){
8585 $j( _this.target ).empty().text( gM('mwe-playlist-empty') )
8686 return ;
8787 }
@@ -88,56 +88,247 @@
8989 // Empty the target and setup player and playerList divs
9090 $j( _this.target )
9191 .empty()
 92+ .css('position', 'relative' )
9293 .append(
9394 $j( '<span />' )
9495 .addClass( 'media-rss-video-player')
9596 .css({
9697 'float' : 'left'
9798 })
98 - ,
99 - $j( '<div />')
100 - .addClass( 'media-rss-video-list-wrapper' )
 99+ ,
 100+ $j( '<div />')
 101+ .addClass( 'media-rss-video-list' )
 102+ .attr('id', _this.id + '_videolist')
 103+ .css({
 104+ 'position' : 'absolute',
 105+ 'z-index' : '1',
 106+ 'overflow' : 'auto',
 107+ 'bottom': '0px',
 108+ 'right' : '0px'
 109+ })
 110+ .hide()
 111+ );
 112+
 113+ // Check if we have multiple playlist and setup the list and bindings
 114+ if( _this.sourceHandler.hasMultiplePlaylists() ){
 115+ var playlistSet = _this.sourceHandler.getPlaylistSet();
 116+
 117+ var $plListContainer =$j('<div />')
 118+ .addClass( 'playlistSet-container ui-state-default ui-widget-header ui-corner-all' )
 119+ .css({
 120+ 'position' : 'absolute',
 121+ 'overflow' : 'hidden',
 122+ 'top' : '3px',
 123+ 'right' : '0px',
 124+ 'height' : '20px'
 125+ })
 126+ .append(
 127+ $j('<div />')
 128+ .addClass( 'playlistSet-list' )
 129+ .css("width", '2000px')
 130+ );
 131+ $j( _this.target ).append( $plListContainer );
 132+
 133+ var $plListSet = $j( _this.target ).find( '.playlistSet-list' );
 134+
 135+ $j.each( playlistSet, function( inx, playlist){
 136+ // add a divider
 137+ if( inx != 0 ){
 138+ $plListSet.append( $j('<span />').text( ' | ') )
 139+ }
 140+ $plListSet.append(
 141+ $j('<a />')
 142+ .attr('href', '#')
 143+ .text( playlist.name )
 144+ .click( function(){
 145+ _this.sourceHandler.setPlaylistIndex( inx );
 146+ $j( _this.target + ' .media-rss-video-list').loadingSpinner();
 147+ _this.loadPlaylist( function(){
 148+ $j( _this.target + ' .media-rss-video-list').empty();
 149+ _this.addMediaList();
 150+ });
 151+ return false;
 152+ })
 153+ .buttonHover()
 154+ )
 155+ });
 156+ // Check playlistSet width and add scroll left / scroll right buttons
 157+ if( $plListSet.width() > $plListContainer.width() ){
 158+ var baseButtonWidth = 24;
 159+ $plListSet.css( {
 160+ 'position': 'absolute',
 161+ 'left' : baseButtonWidth + 'px'
 162+ });
 163+ var $scrollButton = $j('<div />')
 164+ .addClass( 'ui-corner-all ui-state-default' )
101165 .css({
102 - 'position' : 'relative',
103 - 'z-index' : '1',
104 - 'width': '400px',
105 - 'height': '300px',
106 - 'overflow' : 'auto'
 166+ 'position' : 'absolute',
 167+ 'top' : '-1px',
 168+ 'cursor' : 'pointer',
 169+ 'margin' :'0px',
 170+ 'padding' : '2px',
 171+ 'width' : '16px',
 172+ 'height' : '16px'
107173 })
 174+
 175+ var $buttonSpan = $j('<span />')
 176+ .addClass( 'ui-icon' )
 177+ .css('margin', '2px' );
 178+
 179+ var plScrollPos = 0;
 180+ var scrollToListPos = function( pos ){
 181+
 182+ listSetLeft = $plListSet.find('a').eq( pos ).offset().left -
 183+ $plListSet.offset().left ;
 184+
 185+ mw.log("scroll to: " + pos + ' left: ' + listSetLeft);
 186+ $plListSet.animate({'left': -( listSetLeft - baseButtonWidth) + 'px'} );
 187+ }
 188+
 189+ $plListContainer
108190 .append(
109 - $j( '<div />')
110 - .addClass( 'media-rss-video-list' )
111 - .attr('id', _this.id + '_videolist')
 191+ $scrollButton.clone()
 192+ .css('left', '0px')
 193+ .append( $buttonSpan.clone().addClass('ui-icon-circle-arrow-w') )
 194+ .click( function(){
 195+ //slide right
 196+ if( plScrollPos >= 0){
 197+ mw.log("scroll right");
 198+ plScrollPos--
 199+ scrollToListPos( plScrollPos );
 200+ }
 201+ })
 202+ .buttonHover(),
 203+
 204+ $scrollButton.clone()
 205+ .css('right', '0px')
 206+ .append( $buttonSpan.clone().addClass('ui-icon-circle-arrow-e') )
 207+ .click( function(){
 208+ //slide left
 209+ if( plScrollPos < $plListSet.find('a').length-1 ){
 210+ plScrollPos++;
 211+ scrollToListPos( plScrollPos );
 212+ }
 213+ })
 214+ .buttonHover()
112215 )
113 - .hide()
114 - );
 216+ }
 217+ }
115218
116219 // Add the selectable media list
117220 _this.addMediaList();
118221
119222 // Add the player
120 - _this.updatePlayer( _this.clipIndex, function(){
121 -
 223+ _this.updatePlayer( _this.clipIndex, function(){
122224 // Update the list height ( vertical layout )
123 - if( _this.layout == 'vertical' ){
124 - var targetListHeight = ( $j( _this.target ).height() - $j( _this.target + ' .media-rss-video-player' ).height() );
125 - $j( _this.target + ' .media-rss-video-list-wrapper' ).css( {
126 - 'height' : targetListHeight,
 225+ if( _this.layout == 'vertical' ){
 226+ $j( _this.target + ' .media-rss-video-list' ).css( {
 227+ 'top' : $j( _this.target + ' .media-rss-video-player' ).height() + 4,
127228 'width' : '100%'
128229 } )
 230+ // Add space for the multi-playlist selector:
 231+ if( _this.sourceHandler.hasMultiplePlaylists() ){
 232+ // also adjust .playlistSet-container if present
 233+ $j( _this.target + ' .playlistSet-container').css( {
 234+ 'top' : $j( _this.target + ' .media-rss-video-player' ).height() + 4
 235+ })
 236+ $j( _this.target + ' .media-rss-video-list' ).css({
 237+ 'top' : $j( _this.target + ' .media-rss-video-player' ).height() + 26
 238+ })
 239+ }
 240+
129241 } else {
130 - var targetListWidth = ( $j( _this.target ).width() - $j( _this.target + ' .media-rss-video-player' ).width() );
131 - $j( _this.target + ' .media-rss-video-list-wrapper').css( {
132 - 'width' : targetListWidth,
133 - 'height' : '100%'
134 - } )
 242+ // Update horizontal layout
 243+ $j( _this.target + ' .media-rss-video-list').css( {
 244+ 'top' : '0px',
 245+ 'left' : $j( _this.target + ' .media-rss-video-player' ).width() + 4
 246+ } )
 247+ // Add space for the multi-playlist selector:
 248+ if( _this.sourceHandler.hasMultiplePlaylists() ){
 249+ $j( _this.target + ' .playlistSet-container').css( {
 250+ 'left' : $j( _this.target + ' .media-rss-video-player' ).width() + 4
 251+ })
 252+ $j( _this.target + ' .media-rss-video-list').css( {
 253+ 'top' : '26px'
 254+ })
 255+ }
135256 }
 257+ var $videoList = $j( _this.target + ' .media-rss-video-list' );
 258+ $videoList.show()
136259 // show the video list and apply the swipe binding
137260 $j( _this.target ).find('.media-rss-video-list-wrapper').fadeIn();
138261 if( mw.isMobileSafari() ){
 262+ // iScroll is buggy with current version of iPad / iPhone use scroll buttons instead
 263+ /*
139264 document.addEventListener('touchmove', function(e){ e.preventDefault(); });
140265 var myScroll = iScroll( _this.id + '_videolist' );
141266 setTimeout(function () { myScroll.refresh(); }, 0);
 267+ */
 268+ // add space for scroll buttons:
 269+ var curTop = $j( _this.target + ' .media-rss-video-list' ).css('top');
 270+ if(!curTop) curTop = '0px';
 271+ $j( _this.target + ' .media-rss-video-list' ).css( {
 272+ 'position' : 'absolute',
 273+ 'height' : null,
 274+ 'top' : curTop,
 275+ 'bottom' : '30px',
 276+ 'right': '0px'
 277+ })
 278+ if( _this.layout == 'vertical' ){
 279+ $j( _this.target + ' .media-rss-video-list' ).css({
 280+ 'top' : $j( _this.target + ' .media-rss-video-player' ).height()
 281+ })
 282+ }
 283+ // Add scroll buttons:
 284+ $j( _this.target ).append(
 285+ $j( '<div />').css({
 286+ 'position' : 'absolute',
 287+ 'bottom' : '0px',
 288+ 'right': '0px',
 289+ 'height' : '30px',
 290+ 'width' : $j( _this.target + ' .media-rss-video-list').width()
 291+ })
 292+ .append(
 293+ $j.button({
 294+ 'text' : 'scroll down',
 295+ 'icon_id' : 'circle-arrow-s'
 296+ })
 297+ .css('float', 'right')
 298+ .click(function(){
 299+ var clipListCount = $videoList.children().length;
 300+ var clipSize = $videoList.children(':first').height();
 301+ var curTop = $videoList.attr('scrollTop');
 302+
 303+ var targetPos = curTop + (clipSize * 3);
 304+ if( targetPos > clipListCount * clipSize ){
 305+ targetPos = ( clipListCount * ( clipSize -1 ) );
 306+ }
 307+ //mw.log(" animate to: " +curTop + ' + ' + (clipSize * 3) + ' = ' + targetPos );
 308+ $videoList.animate({'scrollTop': targetPos }, 500 );
 309+
 310+ return false;
 311+ }),
 312+ $j.button({
 313+ 'text' : 'scroll up',
 314+ 'icon_id' : 'circle-arrow-n'
 315+ })
 316+ .css('float', 'left')
 317+ .click(function(){
 318+ var clipListCount = $videoList.children().length;
 319+ var clipSize = $videoList.children(':first').height();
 320+ var curTop = $videoList.attr('scrollTop');
 321+
 322+ var targetPos = curTop - (clipSize * 3);
 323+ if( targetPos < 0 ){
 324+ targetPos = 0
 325+ }
 326+ mw.log(" animate to: " +curTop + ' + ' + (clipSize * 3) + ' = ' + targetPos );
 327+ $videoList.animate({'scrollTop': targetPos }, 500 );
 328+
 329+ return false;
 330+ })
 331+ )
 332+ )
142333 }
143334
144335 });
@@ -191,16 +382,15 @@
192383
193384 // Build and output the title
194385 var $title = $j('<div />' )
195 - .addClass( 'playlist-title')
 386+ .addClass( 'playlist-title ui-state-default ui-widget-header ui-corner-all')
196387 .css( {
 388+ 'top' : '0px',
197389 'height' : _this.titleHeight,
198 - 'font-size' : '85%',
199390 'width' : playerSize.width
200391 } )
201392 .text(
202393 _this.sourceHandler.getClipTitle( clipIndex )
203394 )
204 - .addClass( 'ui-state-default ui-widget-header' )
205395
206396 $j( _this.target + ' .media-rss-video-player' ).find('.playlist-title').remove( );
207397 $j( _this.target + ' .media-rss-video-player' ).prepend( $title );
@@ -281,25 +471,27 @@
282472
283473 // Update the video tag with the embedPlayer
284474 $j.embedPlayers( function(){
285 - // Setup ondone playing binding to play next clip
286 - $j( '#mrss_' + _this.id + '_' + _this.clipIndex ).unbind('ended').bind( 'ended', function(event, onDoneActionObject ){
287 - // Play next clip
288 - if( _this.clipIndex + 1 < _this.sourceHandler.getClipCount() ){
289 - // Update the onDone action object to not run the base control done:
290 - onDoneActionObject.runBaseControlDone = false;
291 - _this.clipIndex++;
292 -
293 - // update the player and play the next clip
294 - _this.updatePlayer( _this.clipIndex, function(){
295 - _this.play();
296 - })
297 -
298 - } else {
299 - mw.log("Reached end of playlist run normal end action" );
300 - // Update the onDone action object to not run the base control done:
301 - onDoneActionObject.runBaseControlDone = true;
302 - }
303 - })
 475+ // Setup ondone playing binding to play next clip (if autoContinue is true )
 476+ if( _this.sourceHandler.autoContinue == true ){
 477+ $j( '#mrss_' + _this.id + '_' + _this.clipIndex ).unbind('ended').bind( 'ended', function(event, onDoneActionObject ){
 478+ // Play next clip
 479+ if( _this.clipIndex + 1 < _this.sourceHandler.getClipCount() ){
 480+ // Update the onDone action object to not run the base control done:
 481+ onDoneActionObject.runBaseControlDone = false;
 482+ _this.clipIndex++;
 483+
 484+ // update the player and play the next clip
 485+ _this.updatePlayer( _this.clipIndex, function(){
 486+ _this.play();
 487+ })
 488+
 489+ } else {
 490+ mw.log("Reached end of playlist run normal end action" );
 491+ // Update the onDone action object to not run the base control done:
 492+ onDoneActionObject.runBaseControlDone = true;
 493+ }
 494+ })
 495+ }
304496 // Run the callback if its set
305497 if( callback ){
306498 callback();
@@ -345,7 +537,7 @@
346538 'alt' : _this.sourceHandler.getClipTitle( inx ),
347539 'src' : _this.sourceHandler.getClipPoster( inx )
348540 })
349 - .css( 'width', _this.itemThumbWidth )
 541+ .css( 'width', _this.itemThumbWidth + 'px')
350542 ),
351543 $j( '<td />')
352544 .text( _this.sourceHandler.getClipTitle( inx ) ),
Index: branches/MwEmbedStandAlone/modules/SmilPlayer/mw.SmilBuffer.js
@@ -162,7 +162,9 @@
163163 switch( this.smil.getRefType( smilElement ) ){
164164 case 'video':
165165 var vid = $j( '#' + this.smil.getPageDomId( smilElement ) ).get(0);
166 -
 166+ if( !vid ){
 167+ break;
 168+ }
167169 // The load request does not work very well instead .play() then .pause() and seek when on display
168170 // vid.load();
169171
@@ -170,10 +172,8 @@
171173 if( vid.paused && this.getVideoPercetLoaded( smilElement ) == 0 ){
172174 // Issue the load / play request
173175 vid.play();
174 - vid.volume = 0;
175 -
176 - // XXX seek to clipBegin if provided ( we don't need to load before that point )
177 -
 176+ vid.volume = 0;
 177+ // XXX seek to clipBegin if provided ( we don't need to load before that point )
178178 } else {
179179 //mw.log("loadElement:: pause video: " + this.smil.getPageDomId( smilElement ));
180180 // else we have some percentage loaded pause playback
Index: branches/MwEmbedStandAlone/modules/Sequencer/Sequencer.i18n.php
@@ -9,6 +9,9 @@
1010 $messages = array();
1111 $messages['en'] = array(
1212 'mwe-sequencer-loading-sequencer' => 'Loading sequencer ...',
 13+
 14+ 'mwe-sequencer-visual-editor'=> "Visual sequence editor",
 15+ 'mwe-sequencer-text-editor-warn'=> 'Text XML editor ( not recommended ) ',
1316 'mwe-sequencer-loading-timeline' => 'Loading timeline ...',
1417 'mwe-sequencer-loading-player' => 'Loading player ...',
1518 'mwe-sequencer-loading-menu' => 'Loading menu ...',
@@ -76,12 +79,14 @@
7780
7881 'mwe-sequencer-save-no-changes' => 'There are no new edits to save',
7982 'mwe-sequencer-save-summary' => 'Please enter a short summary of changes:',
80 - 'mwe-sequencer-edit_cancel' => 'Cancel sequence edit',
81 -
 83+ 'mwe-sequencer-edit_cancel' => 'Cancel sequence edit',
8284 'mwe-sequencer-saving_wait' => 'Save in progress (please wait)',
8385 'mwe-sequencer-save_done' => 'Save complete',
8486
 87+ 'mwe-sequencer-open-summary' => "Enter the name of the sequence you would like to open",
 88+
8589
 90+
8691 '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>.',
8792 '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.',
8893
Index: branches/MwEmbedStandAlone/modules/Sequencer/actions/mw.SequencerActionsSequence.js
@@ -15,6 +15,72 @@
1616 init: function( sequencer ) {
1717 this.sequencer = sequencer;
1818 },
 19+
 20+ /**
 21+ * present an open dialog to the user, and open the sequence in a new window
 22+ */
 23+ open: function(){
 24+ var _this = this;
 25+ var $content = $j('<div />').append(
 26+ gM('mwe-sequencer-open-summary' ),
 27+ $j('<input />')
 28+ .css({ 'width': 400 })
 29+ .attr({
 30+ 'id' : 'sequenceOpenNameInput',
 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-open-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' : 'folder-open',
 53+ 'text' : gM('mwe-sequencer-menu-sequence-open')
 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().getSequenceViewUrl(
 71+ // ( Sequence: is automatically pre-appended with getSequencePageUrl
 72+ // ( don't use Sequence: in the title )
 73+ $j('#sequenceOpenNameInput').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+ },
1985 save: function(){
2086 var _this = this;
2187 var $dialog = mw.addDialog({
@@ -66,7 +132,6 @@
67133 );
68134 // Remove buttons while loading
69135 $dialog.dialog( "option", "buttons", {} );
70 - $dialog.dialog( "option", "title", gM('mwe-sequencer-saving_wait' ) );
71136
72137 _this.sequencer.getServer().save(
73138 /* Save summary */
@@ -194,8 +259,7 @@
195260 .text("%"),
196261 $j('<div />').attr( 'id', 'firefoggProgressbar')
197262
198 - );
199 - $j('<div />').attr( 'id', 'firefoggProgressbar')
 263+ );
200264 // Embed the player and continue application flow
201265 $j('#publishVideoTarget').embedPlayer({
202266 'controls' : false
@@ -212,9 +276,10 @@
213277 progressPrecent +
214278 '%'
215279 )
216 - $j("#firefoggProgressbar").progressbar(
217 - "option", "value", Math.round( progress * 100 )
218 - );
 280+ mw.log( "set progrees to: " + Math.round( progress * 100 ) );
 281+ $j("#firefoggProgressbar").progressbar({
 282+ "value" : Math.round( progress * 100 )
 283+ });
219284 },
220285 'doneRenderCallback': function( fogg ){
221286 _this.uploadRenderedVideo( $dialog, fogg );
@@ -281,7 +346,7 @@
282347 uploadDone: function($dialog, apiResult){
283348 var _this = this;
284349 // Check the api response
285 - if ( apiResult.error || ( apiResult.upload &&
 350+ if ( !apiResult || apiResult.error || ( apiResult.upload &&
286351 ( apiResult.upload.result == "Failure" || apiResult.upload.error ) ) ) {
287352
288353 $dialog.dialog( 'option', 'title', gM('mwe-sequencer-publishing-error' ) );
@@ -292,12 +357,20 @@
293358
294359 // Success link to the sequence page / ok closes dialog
295360 $dialog.dialog( 'option', 'title', gM('mwe-sequencer-publishing-success' ) );
 361+ var button = {};
 362+ button[ gM('mwe-ok') ] = function(){
 363+ $j( this ).dialog('close')
 364+ };
 365+ $dialog.dialog( 'option', 'button', button );
 366+ // for some reason we lose button height :( (jquery bug ? )
 367+ $dialog.parent().css( 'height', $dialog.height() + 100 );
 368+
296369 $dialog.empty().html( gM('mwe-sequencer-publishing-success-desc',
297370 $j('<a />')
298371 .attr({
299372 'target': '_new',
300373 'href': wgArticlePath.replace( '$1', 'File:' +_this.sequencer.getServer().getVideoFileName() )
301 - })
 374+ })
302375 ) );
303376 // Update the buttons
304377 var buttons = {};
Index: branches/MwEmbedStandAlone/modules/Sequencer/actions/mw.SequencerActionsEdit.js
@@ -17,15 +17,15 @@
1818 editStack : [],
1919
2020 // Store the edit index
21 - editIndex : 0,
 21+ editIndex : 0,
2222
23 - // The numbers of undos supported
24 - numberOfUndos : mw.getConfig( 'Sequencer.numberOfUndos' ),
25 -
2623 init: function( sequencer ) {
2724 this.sequencer = sequencer;
2825 },
29 -
 26+ // return the configured numbers of undos supported
 27+ getNumberOfUndos: function(){
 28+ return mw.getConfig( 'Sequencer.NumberOfUndos' );
 29+ },
3030 selectAll: function(){
3131 // Select all the items in the timeline
3232 $target = this.sequencer.getTimeline().getTimelineContainer();
@@ -60,9 +60,15 @@
6161 this.editStack = this.editStack.splice(0, this.editIndex);
6262 }
6363
 64+ // Shift the undo index if we have hit our max undo size
 65+ if( this.editStack.length > this.getNumberOfUndos() ){
 66+ this.editStack = this.editStack.splice(0, 1 );
 67+ }
 68+
6469 // @@TODO could save space to just compute the diff in JS and store that
6570 // ie: http://code.google.com/p/google-diff-match-patch/
6671 // ( instead of the full xml text with "key-pages" every 10 edits or something like that.
 72+ // ( should non-block compress in workerThread / need workerThread architecture )
6773 this.editStack.push( currentXML );
6874
6975 // Update the editIndex
@@ -70,6 +76,7 @@
7177
7278 // Enable the undo option:
7379 this.sequencer.getMenu().enableMenuItem( 'edit', 'undo' );
 80+ this.sequencer.getMenu().enableMenuItem( 'sequencer', 'save' );
7481 },
7582
7683 /**
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerMenu.js
@@ -36,6 +36,7 @@
3737 'save_divider': 'divider',
3838 'save' : {
3939 'icon' : 'disk',
 40+ 'disabled' : true,
4041 'shortCut' : 'ctrl S',
4142 'action' : function( _this ){
4243 mw.log("SequencerMenu::save");
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerConfig.js
@@ -13,9 +13,16 @@
1414 mw.setDefaultConfig({
1515 // If the sequencer should attribute kaltura
1616 "Sequencer.KalturaAttribution" : true,
17 -
 17+
 18+ // If a the sequencer should open new windows
 19+ "Sequencer.SpawnNewWindows" : true,
 20+
 21+ // If a the sequencer should include withJS=MediaWiki:mwEmbed in created urls
 22+ // ( save gards ) against users that are 'trying' the
 23+ "Sequencer.WithJsMwEmbedUrlHelper" : true,
 24+
1825 // The size of the undo stack
19 - "Sequencer.numberOfUndos" : 100,
 26+ "Sequencer.NumberOfUndos" : 100,
2027
2128 // Default image duration
2229 "Sequencer.AddMediaImageDuration" : 2,
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerServer.js
@@ -26,6 +26,9 @@
2727 // The sequence title key for api queries
2828 titleKey: null,
2929
 30+ // The Url path the the sequence page with $1 where the title should be
 31+ pagePathUrl: null,
 32+
3033 // Stores the most recent version of the sequence xml from the server
3134 serverSmilXml: null,
3235
@@ -42,12 +45,20 @@
4346
4447 // NOTE this should trigger an apiHandler once we have more than one api backend
4548 if( serverConfig ){
 49+
4650 if( serverConfig.type )
4751 this.apiType = serverConfig.type;
 52+
4853 if( serverConfig.url )
4954 this.apiUrl = serverConfig.url;
 55+
5056 if( serverConfig.titleKey )
5157 this.titleKey = serverConfig.titleKey;
 58+
 59+ if( serverConfig.pagePathUrl ){
 60+ this.pagePathUrl = serverConfig.pagePathUrl;
 61+ }
 62+
5263 }
5364 if( this.isConfigured() ){
5465 mw.log("Error: Sequencer server needs a full serverConfig to be initialized")
@@ -200,6 +211,32 @@
201212 });
202213 },
203214 /**
 215+ * Get the sequence description page url
 216+ * @param {String} Optional Sequence title key
 217+ */
 218+ getSequenceViewUrl: function( titleKey ){
 219+ if( !titleKey )
 220+ titleKey = this.titleKey;
 221+ // Check that we have a pagePathUrl config:
 222+ if( !this.pagePathUrl ){
 223+ return false;
 224+ }
 225+ return this.pagePathUrl.replace( '$1', 'Sequence:' + titleKey);
 226+ },
 227+ /**
 228+ * Get the sequencer 'edit' url
 229+ */
 230+ 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);
 238+ },
 239+
 240+ /**
204241 * Get the video file name for saving the flat video asset to the server
205242 * @return {String}
206243 */
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerTimeline.js
@@ -212,14 +212,21 @@
213213
214214 // Add global TrackClipInterface bindings:
215215 var keyBindings = this.sequencer.getKeyBindings();
216 - keyBindings.bindEvent({
217 - 'escape': function(){
218 - _this.getTimelineContainer().find( '.selectedClip' ).removeClass( 'selectedClip' );
219 - },
220 - 'delete': function(){
 216+ $j( keyBindings ).bind('escape', function(){
 217+ // If a clips are selected deselect
 218+ var selectedClips = _this.getTimelineContainer().find( '.selectedClip' )
 219+ if( selectedClips.length ){
 220+ selectedClips.removeClass( 'selectedClip' );
 221+ return;
 222+ }
 223+ // Else trigger an exit request
 224+ _this.sequencer.getActionsSequence().exit();
 225+ // stop event propagation
 226+ return false;
 227+ });
 228+ $j( keyBindings ).bind('delete', function(){
221229 _this.removeSelectedClips();
222 - }
223 - })
 230+ });
224231 },
225232
226233 getTrackSetId:function( trackIndex ){
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerKeyBindings.js
@@ -25,37 +25,12 @@
2626 // set of key flags:
2727 shiftDown: false,
2828 ctrlDown: false,
29 -
 29+ /* events */
 30+
3031 init: function( sequencer ){
3132 this.sequencer = sequencer;
3233 this.setupKeyBindigs()
3334 },
34 -
35 - bindEvent: function( eventType, callback){
36 - if( typeof eventType == 'object' ){
37 - for( var i in eventType ){
38 - this.bindEvent( i, eventType[i] );
39 - }
40 - }
41 - switch( eventType ){
42 - case 'copy':
43 - this.copyEvent = callback;
44 - break;
45 - case 'cut':
46 - this.cutEvent = callback;
47 - break;
48 - case 'paste' :
49 - this.pasteEvent = callback;
50 - break;
51 - case 'escape' :
52 - this.escapeEvent = callback;
53 - break;
54 - case 'delete':
55 - this.deleteEvent = callback;
56 - break;
57 - }
58 - return this;
59 - },
6035 onFocus: function( ){
6136 this.inputFocus = true;
6237 },
@@ -74,14 +49,14 @@
7550 _this.ctrlDown = true;
7651
7752 if ( ( e.which == 67 && _this.ctrlDown ) && !_this.inputFocus )
78 - _this.copyEvent();
 53+ $j( _this ).trigger( 'copy ');
7954
8055 if ( ( e.which == 88 && _this.ctrlDown ) && !_this.inputFocus )
81 - _this.cutEvent();
 56+ $j( _this ).trigger( 'cut ');
8257
8358 // Paste cips on v + ctrl while not focused on a text area:
8459 if ( ( e.which == 86 && _this.ctrlDown ) && !_this.inputFocus )
85 - _this.pasteEvent();
 60+ $j( _this ).trigger( 'paste ');
8661
8762 } );
8863 $j( window ).keyup( function( e ) {
@@ -95,12 +70,12 @@
9671
9772 // Escape key ( deselect )
9873 if ( e.which == 27 )
99 - _this.escapeEvent();
 74+ $j( _this ).trigger( 'escape' );
10075
10176
10277 // Backspace or Delete key while not focused on a text area:
10378 if ( ( e.which == 8 || e.which == 46 ) && !_this.inputFocus )
104 - _this.deleteEvent();
 79+ $j( _this ).trigger( 'delete' );
10580 } );
10681 }
10782
Index: branches/MwEmbedStandAlone/modules/Sequencer/mw.SequencerAddByUrl.js
@@ -28,7 +28,7 @@
2929 * @param {Object} remoteSearchDriver The remote search driver
3030 */
3131 addByUrlDialog: function( remoteSearchDriver, url ){
32 - // see if the asset matches the key type of any enabled content provider:
 32+ // See if the asset matches the detailsUrl key type of any enabled content provider:
3333 $j.each( remoteSearchDriver.getEnabledProviders(), function(providerName, provider){
3434
3535 });
Index: branches/MwEmbedStandAlone/modules/Sequencer/remotes/mw.MediaWikiRemoteSequencer.js
@@ -13,10 +13,34 @@
1414 "mwe-sequencer-embed-sequence-desc",
1515 "mwe-sequencer-loading-sequencer",
1616
 17+ "mwe-sequencer-visual-editor",
 18+ "mwe-sequencer-text-editor-warn",
 19+
 20+
1721 "mwe-sequencer-not-published",
1822 "mwe-sequencer-published-out-of-date"
1923 ]);
2024
 25+/* exported functions */
 26+
 27+/**
 28+ * Special wrapper for sequence links when in 'extension' mode
 29+ * there is no need for js rewrite helpers
 30+ *
 31+ * @param {String} url The url to be wrapped
 32+ */
 33+mw.getRemoteSequencerLink = function( url ){
 34+ if( mw.getConfig( 'Sequencer.WithJsMwEmbedUrlHelper' ) ){
 35+ if( url.indexOf('?') == -1){
 36+ url+='?'
 37+ } else {
 38+ url+='&'
 39+ }
 40+ url+='withJS=MediaWiki:MwEmbed.js';
 41+ }
 42+ return url;
 43+},
 44+
2145 mw.MediaWikiRemoteSequencer = function( options ) {
2246 return this.init( options );
2347 };
@@ -29,14 +53,17 @@
3054 this.action = ( options.action )? options.action : this.action;
3155 this.title = ( options.title )? options.title : this.title;
3256 this.target = ( options.target )? options.target : this.target;
33 - },
 57+ },
3458
3559 drawUI: function() {
3660 // Check page action
3761 if( this.action == 'view' ) {
3862 this.showViewUI();
3963 }
40 - },
 64+ if( this.action == 'edit' ){
 65+ this.showEditUI();
 66+ }
 67+ },
4168 /**
4269 * Check page for sequence
4370 * if not present give link to "create" one.
@@ -72,9 +99,48 @@
73100 _this.displayPlayerEmbed();
74101 }
75102 },
 103+
 104+ showEditUI: function(){
 105+
 106+ $j('#bodyContent').prepend(
 107+ // Append switch visual / text editor links
 108+ $j('<div />')
 109+ .append(
 110+ $j.button({
 111+ 'icon' : 'video',
 112+ 'text' : gM( "mwe-sequencer-visual-editor")
 113+ }).click( function(){
 114+ $j('#sequencerContainer').show();
 115+ $j('#editform').hide();
 116+ }),
 117+ $j.button({
 118+ 'icon' : 'script'
 119+ 'text' : gM("mwe-sequencer-text-editor-warn")
 120+ }).click(function(){
 121+ $j('#sequencerContainer').hide();
 122+ $j('#editform').show();
 123+ }),
 124+ $j('<div />')
 125+ .css({
 126+ 'width' : '100%',
 127+ 'height' : '700px'
 128+ })
 129+ .attr({
 130+ 'id', 'sequencerContainer'
 131+ })
 132+ )
 133+ );
 134+ // load the sequence editor with the sequencerContainer target
 135+ mw.load( 'Sequencer', function(){
 136+ $j('#sequencerContainer').sequencer( _this.getSequencerConfig() );
 137+ });
 138+ },
 139+
 140+
76141 getSequenceFileKey: function( wgPageName ){
77142 return 'File:' + wgPageName.replace( 'Sequence:', 'Sequence-') + '.ogv';
78143 },
 144+
79145 displayPlayerEmbed: function(){
80146 var _this = this;
81147 // load the embedPlayer module:
@@ -88,6 +154,7 @@
89155 'iiurlwidth': '400',
90156 'redirects' : true // automatically follow redirects
91157 };
 158+
92159 var $embedPlayer = $j('<div />');
93160 mw.getJSON( request, function( data ){
94161 if(!data.query || !data.query.pages || data.query.pages[-1]){
@@ -152,13 +219,14 @@
153220 )
154221 }
155222 }
 223+ var width = ( imageinfo.thumbwidth )?imageinfo.thumbwidth : '400px';
156224 // Display embed sequence
157225 $j( _this.target ).empty().append(
158226 $j('<div />')
159227 .addClass( 'sequencer-player')
160228 .css( {
161229 'float' : 'left',
162 - 'width' : imageinfo.thumbwidth
 230+ 'width' : width
163231 })
164232 .append(
165233 $embedPlayer
@@ -194,7 +262,7 @@
195263 ),
196264
197265 // Add a clear both to give content body height
198 - $j('<div />').css({'clear': 'both'})
 266+ $j('<div />').css( { 'clear': 'both' } )
199267 )
200268 // Rewrite the player
201269 $j('#embedSequencePlayer').embedPlayer();
@@ -226,38 +294,42 @@
227295 )
228296 .css( {'width':'200px', 'margin':'auto'})
229297 )
230 - )
231 -
232 - mw.load( 'Sequencer', function(){
233 - // Send a jquery ui style destroy command
 298+ )
 299+ mw.load( 'Sequencer', function(){
 300+ var _this = this;
 301+ // Send a jquery ui style destroy command ( in case the editor is re-invoked )
234302 $j('#edit_sequence_container').sequencer( 'destroy');
235 - $j('#edit_sequence_container').sequencer({
236 - // The title for this sequence:
237 - title : _this.getTitle(),
238 - // If the sequence is new
239 - newSequence : ( wgArticleId == 0 ),
240 - // Server config:
241 - server: {
242 - 'type' : 'mediaWiki',
243 - 'url' : _this.getApiUrl(),
244 - 'titleKey' : wgPageName,
245 - },
246 - // Set the add media wizard to only include commons:
247 - addMedia : {
248 - 'enabled_providers':[ 'wiki_commons' ],
249 - 'default_query' : _this.getTitle()
250 - },
251 - // Function called on sequence exit
252 - onExitCallback: function( sequenceHasChanged ){
253 - if( sequenceHasChanged ){
254 - window.location.reload();
255 - }
256 - // else do nothing
257 - }
258 - });
 303+ $j('#edit_sequence_container').sequencer( _this.getSequencerConfig() );
259304 });
260305 },
261 -
 306+ getSequencerConfig: function(){
 307+ var _this = this;
 308+ return {
 309+ // The title for this sequence:
 310+ title : _this.getTitle(),
 311+ // If the sequence is new
 312+ newSequence : ( wgArticleId == 0 ),
 313+ // Server config:
 314+ server: {
 315+ 'type' : 'mediaWiki',
 316+ 'url' : _this.getApiUrl(),
 317+ 'titleKey' : wgPageName,
 318+ 'pagePathUrl' : wgServer + wgArticlePath
 319+ },
 320+ // Set the add media wizard to only include commons:
 321+ addMedia : {
 322+ 'enabled_providers':[ 'wiki_commons' ],
 323+ 'default_query' : _this.getTitle()
 324+ },
 325+ // Function called on sequence exit
 326+ onExitCallback: function( sequenceHasChanged ){
 327+ if( sequenceHasChanged ){
 328+ window.location.reload();
 329+ }
 330+ // else do nothing
 331+ }
 332+ }
 333+ },
262334 getApiTitleKey: function(){
263335 return wgTitle;
264336 },
Index: branches/MwEmbedStandAlone/remotes/mediaWiki.js
@@ -12,7 +12,10 @@
1313 window.console.log( 'mwEmbed:remote: ' + mwRemoteVersion );
1414 }
1515
16 -
 16+// Make sure mw exists::
 17+if( typeof window.mw == 'undefined'){
 18+ window.mw = {};
 19+}
1720 // Setup up request Params:
1821 var reqParts = urlparts[1].substring( 1 ).split( '&' );
1922 var mwReqParam = { };
@@ -64,7 +67,6 @@
6568 }
6669 }
6770
68 -
6971 // Use wikibits onLoad hook: ( since we don't have js2 / mw object loaded )
7072 addOnloadHook( function() {
7173 doPageSpecificRewrite();
@@ -82,7 +84,7 @@
8385 window.ranMwRewrites = 'done';
8486
8587 // Add media wizard
86 - if ( wgAction == 'edit' || wgAction == 'submit' ) {
 88+ if ( ( wgAction == 'edit' && wgPageName.indexOf( "Sequence:" ) ) || wgAction == 'submit' ) {
8789 loadMwEmbed( [
8890 'mw.RemoteSearchDriver',
8991 'mw.ClipEdit',
@@ -120,12 +122,21 @@
121123 }
122124
123125 // Remote Sequencer
124 - if( wgPageName.indexOf( "Sequence:" ) === 0 ){
 126+ if( wgPageName.indexOf( "Sequence:" ) === 0 ){
125127 //console.log( 'spl: ' + typeof mwSetPageToLoading );
126128 // If on a view page set content to "loading"
127 - if( wgAction == 'view' ){
128 - mwSetPageToLoading();
 129+ if( wgAction == 'view' || wgAction == 'edit' ){
 130+ if( wgAction == 'view' ){
 131+ mwSetPageToLoading();
 132+ }
 133+ if( wgAction == 'edit' ){
 134+ mwAddCommonStyleSheet();
 135+ var body = document.getElementById( 'bodyContent' );
 136+ body.innerHTML = "<div class=\"loadingSpinner\"></div>" + body.innerHTML;
 137+ }
129138 loadMwEmbed( [ 'mw.MediaWikiRemoteSequencer' ], function(){
 139+ $j('.loadingSpinner').remove();
 140+ $j('#editform').hide();
130141 var remote = new mw.MediaWikiRemoteSequencer({
131142 'action': wgAction,
132143 'title' : wgTitle,
@@ -211,12 +222,21 @@
212223 * Sets the mediaWiki content to "loading"
213224 */
214225 function mwSetPageToLoading(){
215 - importStylesheetURI( mwEmbedHostPath + '/skins/mvpcf/EmbedPlayer.css?' + mwGetReqArgs() );
 226+ mwAddCommonStyleSheet();
216227 var body = document.getElementById('bodyContent');
217228 var oldBodyHTML = body.innerHTML;
218 - body.innerHTML = '<div class="loadingSpinner"></div>';
 229+ body.innerHTML = '<div class="loadingSpinner"></div>';
219230 return oldBodyHTML;
220231 }
 232+function mwAddCommonStyleSheet(){
 233+ importStylesheetURI( mwEmbedHostPath + '/skins/common/mw.style.mwCommon.css?' + mwGetReqArgs() );
 234+ // Set the style to defined ( so that when mw won't load the style sheet again)
 235+ if( !mw.style ){
 236+ mw.style = { 'mwCommon' : true };
 237+ } else {
 238+ mw.style['mwCommon'] = true;
 239+ }
 240+}
221241 /**
222242 * Similar to the player loader in /modules/embedPlayer/loader.js
223243 * ( front-loaded to avoid extra requests )

Status & tagging log