r62347 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r62346‎ | r62347 | r62348 >
Date:00:31, 12 February 2010
Author:dale
Status:deferred
Tags:
Comment:
* improved api proxy of file upload dialog ( still not fully functional )
Modified paths:
  • /branches/js2-work/phase3/js/apiProxyPage.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.Firefogg.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadHandler.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadInterface.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/ApiProxy/mw.ApiProxy.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/remotes/mediaWiki.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/tests/testApiProxy.html (modified) (history)
  • /branches/js2-work/phase3/js/uploadPage.js (modified) (history)

Diff [purge]

Index: branches/js2-work/phase3/js/mwEmbed/tests/testApiProxy.html
@@ -77,16 +77,26 @@
7878 });
7979 }
8080
81 -
8281 function doFileUpload(){
 82+ $j('#file-upload-container').fadeIn( 'slow' );
8383 $j('#browseTarget').html( mw.loading_spinner() );
84 - mw.load( 'ApiProxy', function(){
85 - mw.ApiProxy.browseFile( {
 84+
 85+ mw.load( 'ApiProxy', function(){
 86+ var browserFrame = mw.ApiProxy.browseFile( {
8687 'target' : '#browseTarget',
87 - 'apiUrl' : remote_api_url
88 - },function(){
89 - mw.log( 'brwose file cb' );
90 - });
 88+ 'api_url' : remote_api_url,
 89+ // File Destination Name change callback:
 90+ 'destinationCB' : function( fname ){
 91+ // Update our local target:
 92+ $j('#target-fname').val( fname );
 93+ // Run a destination file name check on the remote target
 94+ $j('#target-fname').doDestCheck( {
 95+ 'api_url' : remote_api_url,
 96+ 'warn_target': '#file-warning'
 97+ } );
 98+
 99+ }
 100+ } );
91101 });
92102
93103 }
@@ -103,9 +113,24 @@
104114 <br><br><br> <a href="#" id="doAppend">Append Msg to Talk page:</a>
105115 <div id="appendTarget"></div>
106116
107 - <br><br><br> <a href="#" id="doFileBrowse">Upload a file to remote:</a>
108 - <div id="browseTarget"></div>
109 -
 117+ <br><br><a href="#" id="doFileBrowse">Upload a file to remote:</a>
 118+ <div id="file-upload-container" style="display:none">
 119+ <div style="background:#FEF;margin:20px;">
 120+ <h3> Local input </h3>
 121+ Target file name: <input id="target-fname" type="text" size="15" />
 122+ <div id="file-warning"></div>
 123+ <BR>
 124+ Target desc: <input type="text" size="20" />
 125+ </div>
 126+ <div style="background:#CEF;margin:20px;">
 127+ <h3> Browse File Served From Remote: </h3>
 128+ <div id="browseTarget"></div>
 129+ </div>
 130+ <div style="background:#FEF;margin:20px;">
 131+ <h3> Local submit </h3>
 132+ <input type="submit" size="10" value="upload" />
 133+ </div>
 134+ </div>
110135 </div>
111136
112137 </body>
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadHandler.js
@@ -48,7 +48,7 @@
4949 // Default upload mode is 'api'
5050 'upload_mode' : 'api',
5151
52 - // Callback for modifing form data on submit
 52+ // Callback for modifying form data on submit
5353 'onsubmit_cb' : null,
5454
5555 // The interface type sent to mw.interface factory
@@ -95,7 +95,7 @@
9696
9797 // If the existing form should be used to post to the api
9898 // Since file selection can't be "moved" we have to use the existing
99 - // form and just submit it to a difrent target
 99+ // form and just submit it to a different target
100100 form_post_override: false,
101101
102102 // http copy by url mode flag
@@ -677,6 +677,8 @@
678678 /**
679679 * Process the result of the form submission, returned to an iframe.
680680 * This is the iframe's onload event.
 681+ *
 682+ * @param {Element} iframe iframe to extract result from
681683 */
682684 processIframeResult: function( iframe ) {
683685 var _this = this;
@@ -703,7 +705,7 @@
704706 response = {};
705707 }
706708 } else {
707 - // response is a xml document
 709+ // Response is a xml document
708710 response = doc;
709711 }
710712 // Process the API result
@@ -964,13 +966,18 @@
965967 * Check the upload destination filename for conflicts and show a conflict
966968 * error message if there is one
967969 */
968 - $.fn.doDestCheck = function( opt ) {
 970+ $.fn.doDestCheck = function( options ) {
969971 var _this = this;
970972 mw.log( 'doDestCheck::' + _this.selector );
971973
972974 // Set up option defaults
973 - if ( !opt.warn_target )
974 - opt.warn_target = '#wpDestFile-warning';
 975+ if ( !options.warn_target ){
 976+ options.warn_target = '#wpDestFile-warning';
 977+ }
 978+
 979+ if( ! options.api_url ){
 980+ options.api_url = mw.getLocalApiUrl();
 981+ }
975982
976983 // Add the wpDestFile-warning row
977984 if ( $j( '#wpDestFile-warning' ).length == 0 ) {
@@ -984,8 +991,8 @@
985992 }
986993 mw.log( 'past dest');
987994 // Remove any existing warning
988 - $j( opt.warn_target ).empty();
989 - mw.log( 'past remove warn:: ' + _this.selector);
 995+ $j( options.warn_target ).empty();
 996+
990997 // Show the AJAX spinner
991998 $j( _this.selector ).after(
992999 $j('<img />')
@@ -994,16 +1001,16 @@
9951002 'src' : stylepath + '/common/images/spinner.gif'
9961003 })
9971004 );
998 - mw.log("added spiner");
 1005+ // Setup the request
9991006 var request = {
10001007 'titles': 'File:' + $j( _this.selector ).val(),
10011008 'prop': 'imageinfo',
10021009 'iiprop': 'url|mime|size',
10031010 'iiurlwidth': 150
1004 - };
 1011+ };
10051012
10061013 // Do the destination check ( on the local wiki )
1007 - mw.getJSON( request, function( data ) {
 1014+ mw.getJSON( options.api_url, request, function( data ) {
10081015 // Remove spinner
10091016 $j( '#mw-spinner-wpDestFile' ).remove();
10101017
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadInterface.js
@@ -15,13 +15,13 @@
1616 */
1717
1818 /**
19 - * Base UploadInterfaceDispatch object (extened by
 19+ * Base UploadInterface object
2020 */
2121 mw.UploadInterface = {
2222 factory : function( interfaceType ){
2323 switch( interfaceType ){
2424 case 'iframe':
25 - return new mw.iframeInterface();
 25+ return new mw.iframeInterface( );
2626 break;
2727 case 'dialog':
2828 default:
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.Firefogg.js
@@ -370,7 +370,7 @@
371371 }
372372
373373 // If Firefogg is not available, just show a "please install" message
374 - if ( !_this.getFirefogg() ) {
 374+ if ( ! _this.getFirefogg() ) {
375375 if ( !this.target_please_install ) {
376376 $j( this.selector ).after( this.getControlHtml( 'target_please_install' ) );
377377 this.target_please_install = this.selector + ' ~ .target_please_install';
Index: branches/js2-work/phase3/js/mwEmbed/modules/ApiProxy/mw.ApiProxy.js
@@ -7,8 +7,7 @@
88 * The framework ~will eventually~ support a request approval system for per-user domain approval
99 * and a central blacklisting of domains controlled by the site
1010 *
11 -*
12 -* if the browser supports it we can pass msgs with the postMessage API
 11+* if the browser supports it we should pass msgs with postMessage API
1312 * http://ejohn.org/blog/cross-window-messaging/
1413 *
1514 * NOTE: it would be nice if this supported multiple proxy targets (ie to a bright widgets future)
@@ -61,6 +60,12 @@
6261
6362 // The url for the last api request target.
6463 var currentApiUrl = null;
 64+
 65+ // Time we should wait for proxy page callback
 66+ // ( note this time starts form when the page is "done"
 67+ // loading so it should only be the time need to load some
 68+ // cached js for the callback)
 69+ var proxyPageLoadTimeout = 10000;
6570
6671 /**
6772 * Takes a requestQuery, executes the query and then calls the callback
@@ -111,9 +116,10 @@
112117 }
113118
114119 // Special callback to frameProxyOk flag
115 - // (only used to test the proxy connection)
116 - if ( resultObject.state == 'ok' )
 120+ // (only used to quickly test the proxy connection)
 121+ if ( resultObject.state == 'ok' ){
117122 return ;
 123+ }
118124
119125 // Pass the result object to the callback:
120126 proxyCallback( resultObject );
@@ -126,16 +132,73 @@
127133 * @param {Function} callback Function to host the
128134 */
129135 $.browseFile = function( options ){
 136+
 137+ // Set frame proxy ok state flag:
 138+ frameProxyOk = false;
 139+
 140+ if( ! options ){
 141+ options = {};
 142+ }
 143+
130144 if( ! options.target ){
131 - mw.log( "Error: no target for file browse" ) ;
 145+ mw.log( "Error: no target for file browse iframe" ) ;
132146 return false;
133147 }
134 - if( ! options.apiUrl ){
135 - mw.log( "Error: no api url to target" );
 148+ if( ! options.api_url ){
 149+ mw.log( "Error: no api url to target" );
 150+ return false;
136151 }
137 - $j( options.target ).html(
138 -
 152+ //update the current apiUrl:
 153+ currentApiUrl = options.api_url;
 154+
 155+ if( ! options.width ){
 156+ options.width = 270;
 157+ }
 158+ if( ! options.height ){
 159+ options.height = 27;
 160+ }
 161+ var iFrameName = ( options.iframeName ) ? options.iframeName : 'fileBrowse_' + $j('iframe').length;
 162+ // Setup an object to be packaged into the frame
 163+ var hashPack ={
 164+ 'clientFrame' : getClientFrame(),
 165+ 'browseFile' : true
 166+ };
 167+
 168+ // Set to host file browse rewrite position
 169+ // NOTE we can't use jQuery buildout for iframes because IE throws away attributes
 170+ $j( options.target ).html(
 171+ '<iframe ' +
 172+ 'style="display:none;border:none;overflow:hidden;width:'+ parseInt( options.width ) + 'px;height:' + parseInt( options.height ) +'px;" '+
 173+ 'id="' + escape( iFrameName ) + '" name="' + escape( iFrameName ) + '" ' +
 174+ 'src="' + getServerBrowseFileFrame( options.api_url ) +
 175+ '#' + escape( JSON.stringify( hashPack ) ) + '">' +
 176+ '</iframe>'
139177 );
 178+ // add a loading spinner
 179+ $j( options.target ).append(
 180+ $j('<div />').loadingSpinner()
 181+ );
 182+
 183+ // add an onLoad hook:
 184+ $j( '#' + iFrameName ).get( 0 ).onload = function() {
 185+ // Add a 10 second timeout for setting up the nested child callback (after page load)
 186+ setTimeout( function() {
 187+ if ( !frameProxyOk ) {
 188+ // we timmed out no api proxy (should make sure the user is "logged in")
 189+ mw.log( "Error:: api proxy timeout are we logged in? mwEmbed is on?" );
 190+ proxyNotReadyDialog();
 191+ }
 192+ }, proxyPageLoadTimeout );
 193+ };
 194+
 195+ // Setup the proxy callback to display the upload unhide the iframe upload form
 196+ proxyCallback = function( iframeData ){
 197+ //hide the loading spinner
 198+ $j( options.target ).find('.loading_spinner').fadeOut('fast');
 199+ mw.log("iframe ready callback");
 200+ $j( '#' + iFrameName ).fadeIn( 'fast' );
 201+ }
 202+
140203 }
141204
142205 /**
@@ -146,20 +209,25 @@
147210 *
148211 */
149212 $.server = function( proxyConfig, callback ) {
150 - //Validate the server request:
 213+ // Validate the server request:
151214 if( validateIframeRequest( proxyConfig ) ){
 215+ var clientRequest = getClientRequest();
 216+
 217+ // Inform the client frame that we passed validation
 218+ outputResultsFrame( clientRequest.clientFrame, 'nested_ok', { 'state':'ok' } );
152219 // Process request type
153 - if( proxyConfig['browserFile'] ){
154 - doBrowseFile();
 220+ if( clientRequest['browseFile'] ){
 221+ mw.log( "DO BROWSE FILE" );
 222+ serverBrowseFile( proxyConfig );
155223 return ;
156224 }
157 - // Else do a normal api request :
 225+ // Else do a normal api request :
158226 return doApiRequest();
159227 }
160228 }
161229
162230 /**
163 - * local scoped helper functions:
 231+ * Local scoped helper functions:
164232 */
165233
166234 /**
@@ -170,15 +238,36 @@
171239 }
172240
173241 /**
174 - * Get the server Frame path per requested Api url (prsently hard coded to MediaWiki:ApiProxy per /remotes/medaiWiki.js
 242+ * Get the server Frame path per requested Api url (presently hard coded to MediaWiki:ApiProxy per /remotes/medaiWiki.js )
 243+ *
 244+ * NOTE: we can switch this for a real proxy entry point once we set that up on the server.
 245+ *
 246+ * NOTE: we add the gadget incase the user has not enabled the gadget on the project they want to iframe to.
 247+ * ( there is no cost if they do already have the gadget on )
175248 */
176 - function getServerFrame( ){
177 - var parsedUrl = mw.parseUri( currentApiUrl );
178 - return parsedUrl.protocol + '://' + parsedUrl.authority + '/w/index.php/MediaWiki:ApiProxy';
 249+ var gadgetWithJS = 'withJS=MediaWiki:Gadget-mwEmbed.js';
 250+ function getServerFrame( apiUrl ){
 251+ // Set to local scope currentApiUrl if unset by argument
 252+ if( !apiUrl){
 253+ apiUrl = currentApiUrl;
 254+ }
 255+ var parsedUrl = mw.parseUri( apiUrl );
 256+ return parsedUrl.protocol + '://' + parsedUrl.authority + '/w/index.php/MediaWiki:ApiProxy?' + gadgetWithJS;
179257 }
 258+ /**
 259+ * Same as getServerFrame but for browse file interface
 260+ */
 261+ function getServerBrowseFileFrame( apiUrl ){
 262+ // Set to local scope currentApiUrl if unset by argument
 263+ if( !apiUrl){
 264+ apiUrl = currentApiUrl;
 265+ }
 266+ var parsedUrl = mw.parseUri( apiUrl );
 267+ return parsedUrl.protocol + '://' + parsedUrl.authority + '/w/index.php/MediaWiki:ApiProxyBrowserFile?' + gadgetWithJS;
 268+ }
180269
181270 /**
182 - * Does the frame proxy
 271+ * Do the frame proxy
183272 * Writes an iframe with a hashed value of the requestQuery
184273 *
185274 * @param {Object} requestQuery The api request object
@@ -186,7 +275,7 @@
187276 function doFrameProxy ( requestQuery ) {
188277
189278 var hashPack = {
190 - // Client domain:
 279+ // Client domain frame ( will be approved by the server before sending and reciving msgs )
191280 'clientFrame' : getClientFrame(),
192281 'request' : requestQuery
193282 }
@@ -217,7 +306,7 @@
218307 mw.log( "Error:: api proxy timeout are we logged in? mwEmbed is on?" );
219308 proxyNotReadyDialog();
220309 }
221 - }, 10000 );
 310+ }, proxyPageLoadTimeout );
222311 }
223312 }
224313
@@ -355,13 +444,78 @@
356445 }
357446
358447 /**
359 - * setup the browse file proxy.
 448+ * Setup the browse file proxy on the "server"
360449 *
361450 * Sets the page content to browser file
362451 */
363 - function doBrowseFile(){
 452+ function serverBrowseFile( proxyConfig ){
 453+ //check for fw ( file width )
 454+ if( ! proxyConfig.fileWidth ){
 455+ proxyConfig.fileWidth = 200;
 456+ }
 457+ //Build a form with bindings similar to uploadPage.js ( but only the browse button )
 458+ $j('body').html(
 459+ $j('<form />')
 460+ .attr( {
 461+ 'name' : "mw-upload-form",
 462+ 'id' : "mw-upload-form",
 463+ 'enctype' : "multipart/form-data",
 464+ 'method' : "post",
 465+ // Submit to the local domain
 466+ 'action' : mw.getLocalApiUrl()
 467+ } )
 468+ .append(
 469+ //Add a single "browse for file" button
 470+ $j('<input />')
 471+ .attr({
 472+ 'type' : "file",
 473+ 'name' : "wpUploadFile",
 474+ 'id' : "wpUploadFile"
 475+ })
 476+ .css({
 477+ 'width' : proxyConfig.fileWidth
 478+ })
 479+ )
 480+ );
364481
365 - }
 482+ // Local function to call once frame is ready:
 483+ function clientFrameReady( status ){
 484+ var clientRequest = getClientRequest();
 485+ // Inform the client frame that we passed validation
 486+ outputResultsFrame( clientRequest.clientFrame, 'browse_file', status );
 487+ }
 488+
 489+ // load the mw.upload library with iframe interface (similar to uploadPage.js)
 490+
 491+ // If wgEnableFirefogg is not boolean false, set to true
 492+ if ( typeof wgEnableFirefogg == 'undefined' ){
 493+ wgEnableFirefogg = true;
 494+ }
 495+
 496+ if( wgEnableFirefogg ){
 497+ mw.load( 'AddMedia.firefogg', function(){
 498+ $j( '#wpUploadFile' ).firefogg( {
 499+ // Set the interface type
 500+ 'interface_type' : 'iframe'
 501+ });
 502+ // Update status
 503+ clientFrameReady( { 'firefogg' : 'ok' } );
 504+ });
 505+ } else {
 506+ mw.load( 'AddMedia.UploadHandler', function(){
 507+ $j( mwUploadFormSelector ).uploadHandler({
 508+ // Set the interface type
 509+ 'interface_type' : 'iframe'
 510+ });
 511+ clientFrameReady();
 512+ });
 513+ }
 514+
 515+
 516+
 517+
 518+
 519+ };
366520
367521 /**
368522 * Outputs the result object to the client domain
@@ -372,15 +526,18 @@
373527 */
374528 function outputResultsFrame( clientFrame, nestName, resultObj ) {
375529 $j( '#nested_push' ).remove();
376 - // Setup the nested iframe proxy that points back to top domain:
 530+ // Setup the nested iframe proxy that points back to top domain
 531+ // (can use jQuery buildout since we don't need to refrence this frame again)
377532 $j( 'body' ).append(
378533 $j('<iframe>').attr({
379534 'id' : nestName,
380535 'name' : nestName,
381536 'src' : clientFrame + '#' + escape( JSON.stringify( resultObj ) )
382 - })
 537+ })
 538+ .css({
 539+ 'display': 'none'
 540+ })
383541 );
384 - }
385 -
386 -
 542+ };
 543+
387544 } )( window.mw.ApiProxy );
Index: branches/js2-work/phase3/js/mwEmbed/remotes/mediaWiki.js
@@ -125,6 +125,7 @@
126126 if ( wgPageName == 'MediaWiki:ApiProxyBrowserFile' ) {
127127 var wgEnableIframeApiProxy = true;
128128 loadMwEmbed( [ 'mw.proxy' ], function() {
 129+ mwApiProxyConfig = {};
129130 mwApiProxyConfig[ 'browserFile' ] = true;
130131 mw.load( mwEmbedHostPath + '/apiProxyPage.js?' + mwGetReqArgs() );
131132 } );
Index: branches/js2-work/phase3/js/apiProxyPage.js
@@ -24,6 +24,8 @@
2525
2626 // User white_list should also be checked and configured at runtime.
2727 mw.ready( function() {
 28+ //Do a setTimeout to 0 to call after other zero delay async events
 29+ // ( once everyone is doing buildout withthin mwsetup priror to .ready this won't be needed. )
2830 mw.load( 'ApiProxy', function(){
2931
3032 //Clear out the page content ( not needed for iframe proxy )
Index: branches/js2-work/phase3/js/uploadPage.js
@@ -4,6 +4,7 @@
55 */
66
77 var mwUploadFormSelector = '#mw-upload-form';
 8+
89 // Set up the upload form bindings once all DOM manipulation is done
910 var mwUploadHelper = {
1011 init: function() {
@@ -16,11 +17,14 @@
1718 mw.load( 'AddMedia.firefogg', function(){
1819 // Set up the upload handler to Firefogg. Should work with the HTTP uploads too.
1920 $j( '#wpUploadFile' ).firefogg( {
20 - // An API URL (we won't submit directly to action of the form)
21 - 'api_url': wgServer + wgScriptPath + '/api.php',
 21+
 22+ // An API URL (default is getLocalApiUrl but set here for clarity )
 23+ 'api_url': mw.getLocalApiUrl(),
 24+
2225 // MediaWiki API supports chunk uploads:
2326 'enable_chunks' : true,
2427
 28+ // Set the interface type
2529 'interface_type' : 'dialog',
2630
2731 'form_selector': mwUploadFormSelector,
@@ -69,6 +73,7 @@
7074 }
7175 } );
7276 },
 77+
7378 /**
7479 * Set the upload radio buttons
7580 *
@@ -82,8 +87,10 @@
8388 $j( '#wpUploadFileURL' ).attr( 'disabled', set );
8489
8590 },
 91+
8692 /**
8793 * Fill in a destination file-name based on a source asset name.
 94+ * @param {Element} targetElm Target element to get destination name from
8895 */
8996 doDestinationFill: function( targetElm ) {
9097 mw.log( "doDestinationFill" )
@@ -102,6 +109,7 @@
103110 } else {
104111 fname = path.substring( backslash + 1, 10000 );
105112 }
 113+
106114 // URLs are less likely to have a useful extension. Don't include them in the extension check.
107115 if ( wgFileExtensions && $j( targetElm ).attr( 'id' ) != 'wpUploadFileURL' ) {
108116 var found = false;
@@ -132,7 +140,6 @@
133141 }
134142 }
135143
136 -
137144 mw.ready( function() {
138145 mwUploadHelper.init();
139146 } );
\ No newline at end of file

Status & tagging log