r62314 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r62313‎ | r62314 | r62315 >
Date:17:33, 11 February 2010
Author:dale
Status:deferred
Tags:
Comment:
* refactor of upload handling into interfaceDispatch and uploadHandler
* "incomplete / untested" will finish up shortly.
* some firefogg gui updates
Modified paths:
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/loader.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.BaseUploadHandler.js (added) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.BaseUploadInterface.js (deleted) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.Firefogg.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.InterfaceDispatch.js (added) (history)
  • /branches/js2-work/phase3/js/mwEmbed/mwEmbed.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/skins/common/images/pbar-ani.gif (added) (history)
  • /branches/js2-work/phase3/js/mwEmbed/tests/Firefogg_GUI.html (modified) (history)

Diff [purge]

Index: branches/js2-work/phase3/js/mwEmbed/tests/Firefogg_GUI.html
@@ -2,8 +2,8 @@
33 <html><head>
44 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
55 <title>Firefogg - Make Ogg Video in your Browser</title>
6 - <!-- <script type="text/javascript" src="../jsScriptLoader.php?urid=6&class=mwEmbed,window.jQuery,mvBaseUploadInterface,mvFirefogg,mvAdvFirefogg,$j.ui,$j.ui.progressbar,$j.ui.dialog,$j.cookie,$j.ui.accordion,$j.ui.slider,$j.ui.datepicker,$j.ui.draggable"></script> -->
7 - <script type="text/javascript" src="../mwEmbed.js?debug=true"></script>
 6+ <script type="text/javascript" src="../jsScriptLoader.php?class=window.jQuery,mwEmbed&urid=92"></script>
 7+ <!-- <script type="text/javascript" src="../mwEmbed.js?debug=true"></script> -->
88 <style type="text/css" media="all">body {
99 margin: 0;
1010 padding: 0;
@@ -88,10 +88,10 @@
8989 </div>
9090 <br>
9191
92 - <div style="margin-right:auto;margin-left:auto;width:500px;" id="firefogg_app">
 92+ <div style="margin-right:auto;margin-left:auto;width:500px;height:200px;" id="firefogg_app">
9393 </div>
9494
95 - <div style="height:295px"></div>
 95+ <div style="height:300px;"></div>
9696 <center><span style="font:size:80%">Built using <a href="http://firefogg.org">firefogg</a>, <a href="http://www.mediawiki.org/wiki/Media_Projects_Overview#MwEmbed">MwEmbed</a> and <a href="http://jqueryui.com/">jquery.ui</a>. Supports
9797 custom themes via the <a href="http://jqueryui.com/themeroller/developertool/">ThemeRoller Dev Tool</a>
9898 </span>
Index: branches/js2-work/phase3/js/mwEmbed/skins/common/images/pbar-ani.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/js2-work/phase3/js/mwEmbed/skins/common/images/pbar-ani.gif
___________________________________________________________________
Name: svn:mime-type
9999 + application/octet-stream
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.BaseUploadInterface.js
@@ -1,1163 +0,0 @@
2 -/**
3 - * The base upload interface.
4 - *
5 - * Progress bars for http-copy-by-url uploading.
6 - * Ifame upload target
7 - *
8 - * This base upload class is optionally extended by Firefogg
9 - *
10 - */
11 -mw.addMessages({
12 - "mwe-upload-transcode-in-progress" : "Transcode and upload in progress (do not close this window)",
13 - "mwe-upload-in-progress" : "Upload in progress (do not close this window)",
14 - "mwe-upload-transcoded-status" : "Transcoded",
15 - "mwe-uploaded-time-remaining" : "Time remaining: $1",
16 - "mwe-uploaded-status" : "Uploaded",
17 - "mwe-upload-stats-fileprogress" : "$1 of $2",
18 - "mwe-upload_completed" : "Your upload is complete",
19 - "mwe-upload_done" : "<a href=\"$1\">Your upload <i>should be<\/i> accessible<\/a>.",
20 - "mwe-upload-unknown-size" : "Unknown size",
21 - "mwe-cancel-confim" : "Are you sure you want to cancel?",
22 - "mwe-successfulupload" : "Upload successful",
23 - "mwe-uploaderror" : "Upload error",
24 - "mwe-uploadwarning" : "Upload warning",
25 - "mwe-unknown-error" : "Unknown error:",
26 - "mwe-return-to-form" : "Return to form",
27 - "mwe-file-exists-duplicate" : "This file is a duplicate of the following file:",
28 - "mwe-fileexists" : "A file with this name exists already. Please check <b><tt>$1<\/tt><\/b> if you are not sure if you want to change it.",
29 - "mwe-fileexists-thumb" : "<center><b>Existing file<\/b><\/center>",
30 - "mwe-ignorewarning" : "Ignore warning and save file anyway",
31 - "mwe-file-thumbnail-no" : "The filename begins with <b><tt>$1<\/tt><\/b>",
32 - "mwe-go-to-resource" : "Go to resource page",
33 - "mwe-upload-misc-error" : "Unknown upload error",
34 - "mwe-wgfogg_warning_bad_extension" : "You have selected a file with an unsuported extension (<a href=\"http:\/\/commons.wikimedia.org\/wiki\/Commons:Firefogg#Supported_File_Types\">more information<\/a>)."
35 -});
36 -
37 -var default_bui_options = {
38 - // Target api to upload to
39 - 'api_url' : null,
40 -
41 - // The selected form
42 - 'form' : null,
43 -
44 - // Callback for once the upload is done
45 - 'done_upload_cb' : null,
46 -
47 - // A selector for the form target
48 - 'form_selector' : null,
49 -
50 - // Default upload mode is 'api'
51 - 'upload_mode' : 'api',
52 -
53 - // Callback for modifing form data on submit
54 - 'onsubmit_cb' : null
55 -
56 -}
57 -mw.BaseUploadInterface = function( options ) {
58 - return this.init( options );
59 -}
60 -
61 -mw.BaseUploadInterface.prototype = {
62 -
63 - // The form data to be submitted
64 - formData: {},
65 -
66 - // Upload warning session key, for continued uploads
67 - warnings_sessionkey: null,
68 -
69 - // If chunks uploading is supported
70 - chunks_supported: true,
71 -
72 - // If the existing form should be used to post to the api
73 - // Since file selection can't be "moved" we have to use the exising
74 - // form and just submit it to a diffrent target
75 - form_post_override: false,
76 -
77 - // http copy by url mode flag
78 - http_copy_upload : null,
79 -
80 - // If the upload action is done
81 - action_done: false,
82 -
83 - // Edit token for upload
84 - editToken: false,
85 -
86 - // The DOM node for the upload form
87 - form: false,
88 -
89 - // The following are really state of the upload, not the interface.
90 - // we are currently only managing one, so this is okay... for now.
91 - uploadBeginTime: null,
92 -
93 -
94 - /**
95 - * Object initialisation
96 - * @param {Object} options BaseUpload options see default_bui_options
97 - */
98 - init: function( options ) {
99 - if ( !options )
100 - options = {};
101 - $j.extend( this, default_bui_options, options );
102 - mw.log( "init mvBaseUploadInterface:: " + this.api_url );
103 - },
104 -
105 - /**
106 - * Set up the upload form, register onsubmit handler.
107 - * May remap it to use the API field names.
108 - */
109 - setupForm: function() {
110 - mw.log( "Base::setupForm::" );
111 - var _this = this;
112 -
113 - // Set up the local pointer to the edit form:
114 - this.form = this.getForm();
115 -
116 - if ( !this.form ) {
117 - mw.log( "Upload form not found!" );
118 - return;
119 - }
120 -
121 - // Set up the orig_onsubmit if not set:
122 - if ( typeof( this.orig_onsubmit ) == 'undefined' && this.form.onsubmit ) {
123 - this.orig_onsubmit = this.form.onsubmit;
124 - }
125 -
126 - // Set up the submit action:
127 - $j( this.form ).submit( function() {
128 - mw.log( "FORM SUBMIT::" );
129 - var data = $j( this ).serializeArray();
130 - for ( var i = 0; i < data.length; i++ ) {
131 - mw.log( $j( data[i] ).attr('name') + ' : ' + $j(data[i]).val() );
132 - }
133 -
134 - return _this.onSubmit();
135 - } );
136 - },
137 -
138 - /**
139 - * onSubmit handler for the upload form
140 - */
141 - onSubmit: function() {
142 - var _this = this;
143 - mw.log( 'Base::onSubmit:' );
144 - // Run the original onsubmit (if not run yet set flag to avoid excessive chaining)
145 - if ( typeof( this.orig_onsubmit ) == 'function' ) {
146 - if ( ! this.orig_onsubmit() ) {
147 - //error in orig submit return false;
148 - return false;
149 - }
150 - }
151 - // Call the onsubmit_cb option if set:
152 - if( this.onsubmit_cb && typeof this.onsubmit_cb == 'function' ){
153 - this.onsubmit_cb();
154 - }
155 -
156 - // Remap the upload form to the "api" form:
157 - this.remapFormToApi();
158 -
159 - // Check for post action override
160 - if ( this.form_post_override ) {
161 - mw.log( 'form_post_override is true, do ordinary form submit' );
162 - return true;
163 - }
164 -
165 -
166 - // Put into a try catch so we are sure to return false:
167 - try {
168 - // Display a progress dialog
169 - _this.displayProgressOverlay();
170 -
171 - // For some unknown reason we have to drop down the #p-search z-index:
172 - $j( '#p-search' ).css( 'z-index', 1 );
173 -
174 - var _this = this;
175 - _this.detectUploadMode( function( mode ) {
176 - _this.upload_mode = mode;
177 - _this.doUpload();
178 - } );
179 - } catch( e ) {
180 - mw.log( '::error in displayProgressOverlay or doUpload' );
181 - }
182 -
183 - // Don't submit the form we will do the post in ajax
184 - return false;
185 - },
186 -
187 - /**
188 - * Determine the correct upload mode.
189 - *
190 - * If this.upload_mode is autodetect, this runs an API call to find out if MW
191 - * supports uploading. It then sets the upload mode when this call returns.
192 - *
193 - * When done detecting, or if detecting is unnecessary, it calls the callback
194 - * with the upload mode as the first parameter.
195 - *
196 - * @param {Function} callback Function called once upload mode is detected
197 - */
198 - detectUploadMode: function( callback ) {
199 - var _this = this;
200 - mw.log( 'detectUploadMode::' + _this.upload_mode );
201 - //debugger;
202 - // Check the upload mode
203 - if ( _this.upload_mode == 'detect_in_progress' ) {
204 - // Don't send another request, wait for the pending one.
205 - } else if ( !_this.isCopyUpload() ) {
206 - callback( 'post' );
207 - } else if ( _this.upload_mode == 'autodetect' ) {
208 - mw.log( 'detectUploadMode::' + _this.upload_mode + ' api:' + _this.api_url );
209 - if( !_this.api_url ) {
210 - mw.log( 'Error: can\'t autodetect mode without api url' );
211 - return;
212 - }
213 -
214 - // Don't send multiple requests
215 - _this.upload_mode = 'detect_in_progress';
216 -
217 - // FIXME: move this to configuration and avoid this API request
218 - mw.getJSON( _this.api_url, { 'action' : 'paraminfo', 'modules' : 'upload' }, function( data ) {
219 - if ( typeof data.paraminfo == 'undefined'
220 - || typeof data.paraminfo.modules == 'undefined' )
221 - {
222 - return mw.log( 'Error: bad api results' );
223 - }
224 - if ( typeof data.paraminfo.modules[0].classname == 'undefined' ) {
225 - mw.log( 'Autodetect Upload Mode: \'post\' ' );
226 - _this.upload_mode = 'post';
227 - callback( 'post' );
228 - } else {
229 - mw.log( 'Autodetect Upload Mode: api ' );
230 - _this.upload_mode = 'api';
231 - // Check to see if chunks are supported
232 - for ( var i in data.paraminfo.modules[0].parameters ) {
233 - var pname = data.paraminfo.modules[0].parameters[i].name;
234 - if( pname == 'enablechunks' ) {
235 - mw.log( 'this.chunks_supported = true' );
236 - _this.chunks_supported = true;
237 - break;
238 - }
239 - }
240 - callback( 'api' );
241 - }
242 - }
243 - );
244 - } else if ( _this.upload_mode == 'api' ) {
245 - callback( 'api' );
246 - } else if ( _this.upload_mode == 'post' ) {
247 - callback( 'post' );
248 - } else {
249 - mw.log( 'Error: unrecongized upload mode: ' + _this.upload_mode );
250 - }
251 - },
252 -
253 - /**
254 - * Do an upload, with the mode given by this.upload_mode
255 - */
256 - doUpload: function() {
257 - // Note "api" should be called "http_copy_upload" and /post/ should be "form_upload"
258 - this.uploadBeginTime = (new Date()).getTime();
259 - if ( this.upload_mode == 'api' ) {
260 - this.doApiCopyUpload();
261 - } else if ( this.upload_mode == 'post' ) {
262 - this.doPostUpload();
263 - } else {
264 - mw.log( 'Error: unrecongized upload mode: ' + this.upload_mode );
265 - }
266 - },
267 -
268 - /**
269 - * Change the upload form so that when submitted, it sends a request to
270 - * the MW API.
271 - *
272 - * This is rather ugly, but solutions are constrained by the fact that
273 - * file inputs can't be moved around or recreated after the user has
274 - * selected a file in them, which they may well do before DOM ready.
275 - *
276 - * It is also constrained by upload form hacks on commons.
277 - */
278 - remapFormToApi: function() {
279 - var _this = this;
280 - //
281 - mw.log("remapFormToApi:: " + this.api_url + ' form: ' + this.form);
282 -
283 - if ( !this.api_url ){
284 - mw.log( 'Error: no api url target' );
285 - return false;
286 - }
287 - var $form = $j( this.form_selector );
288 -
289 - // Set the form action
290 - try{
291 - $form.attr('action', _this.api_url);
292 - }catch(e){
293 - mw.log("IE for some reason error's out when you change the action")
294 - }
295 -
296 - // Add API action
297 - if ( $form.find( "[name='action']" ).length == 0 ){
298 - $form.append(
299 - $j('<input />')
300 - .attr({
301 - 'type': "hidden",
302 - 'name' : "action",
303 - 'value' : "upload"
304 - })
305 - )
306 - }
307 -
308 - // Add JSON response format
309 - if ( $form.find( "[name='format']" ).length == 0 ){
310 - $form.append(
311 - $j( '<input />' )
312 - .attr({
313 - 'type' : "hidden",
314 - 'name' : "format",
315 - 'value' : "jsonfm"
316 - })
317 - )
318 - }
319 -
320 - // Map a new hidden form
321 - $form.find( "[name='wpUploadFile']" ).attr( 'name', 'file' );
322 - $form.find( "[name='wpDestFile']" ).attr( 'name', 'filename' );
323 - $form.find( "[name='wpUploadDescription']" ).attr( 'name', 'comment' );
324 - $form.find( "[name='wpEditToken']" ).attr( 'name', 'token' );
325 - $form.find( "[name='wpIgnoreWarning']" ).attr( 'name', 'ignorewarnings' );
326 - $form.find( "[name='wpWatchthis']" ).attr( 'name', 'watch' );
327 -
328 - //mw.log( 'comment: ' + $form.find( "[name='comment']" ).val() );
329 - },
330 -
331 - /**
332 - * Returns true if the current form has copy upload selected, false otherwise.
333 - */
334 - isCopyUpload: function() {
335 - if ( $j( '#wpSourceTypeFile' ).length == 0
336 - || $j( '#wpSourceTypeFile' ).get( 0 ).checked )
337 - {
338 - this.http_copy_upload = false;
339 - } else if ( $j('#wpSourceTypeURL').get( 0 ).checked ) {
340 - this.http_copy_upload = true;
341 - }
342 - return this.http_copy_upload;
343 - },
344 -
345 - /**
346 - * Do an upload by submitting the form
347 - */
348 - doPostUpload: function() {
349 - var _this = this;
350 - var $form = $j( _this.form );
351 - mw.log( 'mvBaseUploadInterface.doPostUpload' );
352 - // Issue a normal post request
353 - // Get the token from the page
354 - _this.editToken = $j( "#wpEditToken" ).val();
355 -
356 - // TODO check for sendAsBinary to support Firefox/HTML5 progress on upload
357 -
358 - //Update the progress dialog (no bar without XHR request)
359 - $j( '#upProgressDialog' ).html(
360 - mw.loading_spinner()
361 - );
362 -
363 - // Add the iframe
364 - _this.iframeId = 'f_' + ( $j( 'iframe' ).length + 1 );
365 - //IE only works if you "create element with the name" (not jquery style
366 - var iframe;
367 - try {
368 - iframe = document.createElement( '<iframe name="' + _this.iframeId + '">' );
369 - } catch (ex) {
370 - iframe = document.createElement('iframe');
371 - }
372 -
373 - $j( "body" ).append(
374 - $j( iframe )
375 - .attr({
376 - 'src':'javascript:false;',
377 - 'id':_this.iframeId,
378 - 'name': _this.iframeId
379 - })
380 - .css('display', 'none')
381 - );
382 -
383 -
384 - // Set the form target to the iframe
385 - $form.attr( 'target', _this.iframeId );
386 -
387 - // Set up the completion callback
388 - $j( '#' + _this.iframeId ).load( function() {
389 - _this.processIframeResult( $j( this ).get( 0 ) );
390 - });
391 -
392 - // Do post override
393 - _this.form_post_override = true;
394 -
395 - // Reset the done with action flag
396 - _this.action_done = false;
397 - $form.submit();
398 - },
399 -
400 - /**
401 - * Do an upload by submitting an API request
402 - */
403 - doApiCopyUpload: function() {
404 - mw.log( 'mvBaseUploadInterface.doApiCopyUpload' );
405 - mw.log( 'doHttpUpload (no form submit) ' );
406 -
407 - var httpUpConf = {
408 - 'url' : $j( '#wpUploadFileURL' ).val(),
409 - 'filename' : $j( '#wpDestFile' ).val(),
410 - 'comment' : this.getUploadDescription(),
411 - 'watch' : ( $j( '#wpWatchthis' ).is( ':checked' ) ) ? 'true' : 'false',
412 - 'ignorewarnings': ($j('#wpIgnoreWarning' ).is( ':checked' ) ) ? 'true' : 'false'
413 - }
414 - //check for editToken
415 - this.editToken = $j( "#wpEditToken" ).val();
416 - this.doHttpUpload( httpUpConf );
417 - },
418 -
419 - /**
420 - * Get the upload description, append the licence if avaliable
421 - *
422 - * NOTE: wpUploadDescription should be a configuration option.
423 - *
424 - * @return {String}
425 - * value of wpUploadDescription
426 - */
427 - getUploadDescription: function(){
428 - //Special case of upload.js commons hack:
429 - var comment_value = $j( '#wpUploadDescription' ).val();
430 - if( comment_value == '' ){
431 - comment_value = $j( "[name='wpUploadDescription']").val();
432 - }
433 - //check for licence tag:
434 - },
435 -
436 - /**
437 - * Process the result of the form submission, returned to an iframe.
438 - * This is the iframe's onload event.
439 - */
440 - processIframeResult: function( iframe ) {
441 - var _this = this;
442 - var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document;
443 - // Fix for Opera 9.26
444 - if ( doc.readyState && doc.readyState != 'complete' ) {
445 - return;
446 - }
447 - // Fix for Opera 9.64
448 - if ( doc.body && doc.body.innerHTML == "false" ) {
449 - return;
450 - }
451 - var response;
452 - if ( doc.XMLDocument ) {
453 - // The response is a document property in IE
454 - response = doc.XMLDocument;
455 - } else if ( doc.body ) {
456 - // Get the json string
457 - json = $j( doc.body ).find( 'pre' ).text();
458 - //mw.log( 'iframe:json::' + json_str + "\nbody:" + $j( doc.body ).html() );
459 - if ( json ) {
460 - response = window["eval"]( "(" + json + ")" );
461 - } else {
462 - response = {};
463 - }
464 - } else {
465 - // response is a xml document
466 - response = doc;
467 - }
468 - // Process the API result
469 - _this.processApiResult( response );
470 - },
471 -
472 - /**
473 - * Do a generic action=upload API request and monitor its progress
474 - */
475 - doHttpUpload: function( params ) {
476 - var _this = this;
477 - // Display the progress overlay (again)
478 - _this.displayProgressOverlay();
479 -
480 - // Set the HTTP box to "loading", in case we don't get an update for some time
481 - $j( '#dlbox-centered' ).html( '<h5>' + _this.getProgressTitle() + '</h5>' +
482 - mw.loading_spinner( 'left:40%;top:20%' )
483 - );
484 -
485 - // Set up the request
486 - var request = {
487 - 'action' : 'upload',
488 - 'asyncdownload' : true // Do async download
489 - };
490 -
491 - // Add any parameters specified by the caller
492 - for ( key in params ) {
493 - if ( !request[key] ) {
494 - request[key] = params[key];
495 - }
496 - }
497 -
498 - // Add the edit token (if available)
499 - if( !_this.editToken && _this.api_url ) {
500 - mw.log( 'Error:doHttpUpload: missing token' );
501 - } else {
502 - request['token'] =_this.editToken;
503 - }
504 -
505 - // Reset the done with action flag
506 - _this.action_done = false;
507 -
508 - // Do the api request:
509 - mw.getJSON(_this.api_url, request, function( data ) {
510 - _this.processApiResult( data );
511 - });
512 - },
513 -
514 - /**
515 - * Start periodic checks of the upload status using XHR
516 - */
517 - doAjaxUploadStatus: function() {
518 - var _this = this;
519 -
520 - //set up the progress display for status updates:
521 - this.displayProgressOverlay();
522 - this.upload_status_request = {
523 - 'action' : 'upload',
524 - 'httpstatus' : 'true',
525 - 'sessionkey' : _this.upload_session_key
526 - };
527 - // Add token if present
528 - if ( this.editToken )
529 - this.upload_status_request['token'] = this.editToken;
530 -
531 - // Trigger an initial request (subsequent ones will be done by a timer)
532 - this.onAjaxUploadStatusTimer();
533 - },
534 -
535 - /**
536 - * This is called when the timer which separates XHR requests elapses.
537 - * It starts a new request.
538 - */
539 - onAjaxUploadStatusTimer: function() {
540 - var _this = this;
541 - //do the api request:
542 - mw.getJSON( this.api_url, this.upload_status_request, function ( data ) {
543 - _this.onAjaxUploadStatusResponse( data );
544 - } );
545 - },
546 -
547 - /**
548 - * Called when a response to an upload status query is available.
549 - * Starts the timer for the next upload status check.
550 - */
551 - onAjaxUploadStatusResponse: function( data ) {
552 - var _this = this;
553 - // Check if we are done
554 - if ( data.upload['apiUploadResult'] ) {
555 - //update status to 100%
556 - _this.updateProgress( 1 );
557 - //see if we need JSON
558 - mw.load( [
559 - 'JSON'
560 - ], function() {
561 - var apiResult = {};
562 - try {
563 - apiResult = JSON.parse( data.upload['apiUploadResult'] ) ;
564 - } catch ( e ) {
565 - //could not parse api result
566 - mw.log( 'errro: could not parse apiUploadResult' )
567 - }
568 - _this.processApiResult( apiResult );
569 - });
570 - return ;
571 - }
572 -
573 - // else update status:
574 - if ( data.upload['content_length'] && data.upload['loaded'] ) {
575 - //we have content length we can show percentage done:
576 - var fraction = data.upload['loaded'] / data.upload['content_length'];
577 - //update the status:
578 - _this.updateProgress( fraction );
579 - //special case update the file progress where we have data size:
580 - $j( '#up-status-container' ).html(
581 - gM( 'mwe-upload-stats-fileprogress',
582 - [
583 - mw.lang.formatSize( data.upload['loaded'] ),
584 - mw.lang.formatSize( data.upload['content_length'] )
585 - ]
586 - )
587 - );
588 - } else if( data.upload['loaded'] ) {
589 - _this.updateProgress( 1 );
590 - mw.log( 'just have loaded (no cotent length: ' + data.upload['loaded'] );
591 - //for lack of content-length requests:
592 - $j( '#up-status-container' ).html(
593 - gM( 'mwe-upload-stats-fileprogress',
594 - [
595 - mw.lang.formatSize( data.upload['loaded'] ),
596 - gM( 'mwe-upload-unknown-size' )
597 - ]
598 - )
599 - );
600 - }
601 - if ( _this.api_url == 'proxy' ) {
602 - // Do the updates a bit less often: every 4.2 seconds
603 - var timeout = 4200;
604 - } else {
605 - // We got a result: set timeout to 100ms + your server update
606 - // interval (in our case 2s)
607 - var timeout = 2100;
608 - }
609 - setTimeout(
610 - function() {
611 - _this.onAjaxUploadStatusTimer();
612 - },
613 - timeout );
614 - },
615 -
616 - /**
617 - * Returns true if an action=upload API result was successful, false otherwise
618 - */
619 - isApiSuccess: function( apiRes ) {
620 - if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
621 - return false;
622 - }
623 - if ( apiRes.upload && apiRes.upload.error ) {
624 - return false;
625 - }
626 - if ( apiRes.upload && apiRes.upload.warnings ) {
627 - return false;
628 - }
629 - return true;
630 - },
631 -
632 - /**
633 - * Given the result of an action=upload API request, display the error message
634 - * to the user.
635 - */
636 - showApiError: function( apiRes ) {
637 - var _this = this;
638 - if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
639 - // Generate the error button
640 - var buttons = {};
641 - buttons[ gM( 'mwe-return-to-form' ) ] = function() {
642 - _this.form_post_override = false;
643 - $j( this ).dialog( 'close' );
644 - };
645 -
646 - // NOTE should be refactored to more specialUpload page type error handling
647 -
648 - // Check a few places for the error code
649 - var error_code = 0;
650 - var errorReplaceArg = '';
651 - if ( apiRes.error && apiRes.error.code ) {
652 - error_code = apiRes.error.code;
653 - } else if ( apiRes.upload.code ) {
654 - if ( typeof apiRes.upload.code == 'object' ) {
655 - if ( apiRes.upload.code[0] ) {
656 - error_code = apiRes.upload.code[0];
657 - }
658 - if ( apiRes.upload.code['status'] ) {
659 - error_code = apiRes.upload.code['status'];
660 - if ( apiRes.upload.code['filtered'] )
661 - errorReplaceArg = apiRes.upload.code['filtered'];
662 - }
663 - } else {
664 - apiRes.upload.code;
665 - }
666 - }
667 -
668 - var error_msg = '';
669 - if ( typeof apiRes.error == 'string' )
670 - error_msg = apiRes.error;
671 -
672 - // There are many possible error messages here, so we don't load all
673 - // message text in advance, instead we use mw.getRemoteMsg() for some.
674 - //
675 - // This code is similar to the error handling code formerly in
676 - // SpecialUpload::processUpload()
677 - var error_msg_key = {
678 - '2' : 'largefileserver',
679 - '3' : 'emptyfile',
680 - '4' : 'minlength1',
681 - '5' : 'illegalfilename'
682 - };
683 -
684 - // NOTE:: handle these error types
685 - var error_onlykey = {
686 - '1': 'BEFORE_PROCESSING',
687 - '6': 'PROTECTED_PAGE',
688 - '7': 'OVERWRITE_EXISTING_FILE',
689 - '8': 'FILETYPE_MISSING',
690 - '9': 'FILETYPE_BADTYPE',
691 - '10': 'VERIFICATION_ERROR',
692 - '11': 'UPLOAD_VERIFICATION_ERROR',
693 - '12': 'UPLOAD_WARNING',
694 - '13': 'INTERNAL_ERROR',
695 - '14': 'MIN_LENGTH_PARTNAME'
696 - }
697 -
698 - if ( !error_code || error_code == 'unknown-error' ) {
699 - if ( typeof JSON != 'undefined' ) {
700 - mw.log( 'Error: apiRes: ' + JSON.stringify( apiRes ) );
701 - }
702 - if ( apiRes.upload.error == 'internal-error' ) {
703 - // Do a remote message load
704 - errorKey = apiRes.upload.details[0];
705 - mw.getRemoteMsg( errorKey, function() {
706 - _this.updateProgressWin( gM( 'mwe-uploaderror' ), gM( errorKey ), buttons );
707 -
708 - });
709 - return false;
710 - }
711 -
712 - _this.updateProgressWin(
713 - gM('mwe-uploaderror'),
714 - gM('mwe-unknown-error') + '<br>' + error_msg,
715 - buttons );
716 - return false;
717 - }
718 -
719 - if ( apiRes.error && apiRes.error.info ) {
720 - _this.updateProgressWin( gM( 'mwe-uploaderror' ), apiRes.error.info, buttons );
721 - return false;
722 - }
723 -
724 - if ( typeof error_code == 'number'
725 - && typeof error_msg_key[error_code] == 'undefined' )
726 - {
727 - if ( apiRes.upload.code.finalExt ) {
728 - _this.updateProgressWin(
729 - gM( 'mwe-uploaderror' ),
730 - gM( 'mwe-wgfogg_warning_bad_extension', apiRes.upload.code.finalExt ),
731 - buttons );
732 - } else {
733 - _this.updateProgressWin(
734 - gM( 'mwe-uploaderror' ),
735 - gM( 'mwe-unknown-error' ) + ' : ' + error_code,
736 - buttons );
737 - }
738 - return false;
739 - }
740 -
741 - mw.log( 'get key: ' + error_msg_key[ error_code ] )
742 - mw.getRemoteMsg( error_msg_key[ error_code ], function() {
743 - _this.updateProgressWin(
744 - gM( 'mwe-uploaderror' ),
745 - gM( error_msg_key[ error_code ], errorReplaceArg ),
746 - buttons );
747 - });
748 - mw.log( "api.error" );
749 - return false;
750 - }
751 -
752 - // Check upload.error
753 - if ( apiRes.upload && apiRes.upload.error ) {
754 - mw.log( ' apiRes.upload.error: ' + apiRes.upload.error );
755 - _this.updateProgressWin(
756 - gM( 'mwe-uploaderror' ),
757 - gM( 'mwe-unknown-error' ) + '<br>',
758 - buttons );
759 - return false;
760 - }
761 -
762 - // Check for warnings:
763 - if ( apiRes.upload && apiRes.upload.warnings ) {
764 - var wmsg = '<ul>';
765 - for ( var wtype in apiRes.upload.warnings ) {
766 - var winfo = apiRes.upload.warnings[wtype]
767 - wmsg += '<li>';
768 - switch ( wtype ) {
769 - case 'duplicate':
770 - case 'exists':
771 - if ( winfo[1] && winfo[1].title && winfo[1].title.mTextform ) {
772 - wmsg += gM( 'mwe-file-exists-duplicate' ) + ' ' +
773 - '<b>' + winfo[1].title.mTextform + '</b>';
774 - } else {
775 - //misc error (weird that winfo[1] not present
776 - wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
777 - }
778 - break;
779 - case 'file-thumbnail-no':
780 - wmsg += gM( 'mwe-file-thumbnail-no', winfo );
781 - break;
782 - default:
783 - wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
784 - break;
785 - }
786 - wmsg += '</li>';
787 - }
788 - wmsg += '</ul>';
789 - if ( apiRes.upload.sessionkey )
790 - _this.warnings_sessionkey = apiRes.upload.sessionkey;
791 -
792 - // Create the "ignore warning" button
793 - var buttons = {};
794 - buttons[ gM( 'mwe-ignorewarning' ) ] = function() {
795 - //check if we have a stashed key:
796 - if ( _this.warnings_sessionkey ) {
797 - //set to "loading"
798 - $j( '#upProgressDialog' ).html( mw.loading_spinner() );
799 - //setup request:
800 - var request = {
801 - 'action': 'upload',
802 - 'sessionkey': _this.warnings_sessionkey,
803 - 'ignorewarnings': 1,
804 - 'filename': $j( '#wpDestFile' ).val(),
805 - 'token' : _this.editToken,
806 - 'comment' : $j( '#wpUploadDescription' ).val()
807 - };
808 - //run the upload from stash request
809 - mw.getJSON(_this.api_url, request, function( data ) {
810 - _this.processApiResult( data );
811 - } );
812 - } else {
813 - mw.log( 'No session key re-sending upload' )
814 - //do a stashed upload
815 - $j( '#wpIgnoreWarning' ).attr( 'checked', true );
816 - $j( _this.editForm ).submit();
817 - }
818 - };
819 - // Create the "return to form" button
820 - buttons[ gM( 'mwe-return-to-form' ) ] = function() {
821 - $j( this ).dialog( 'close' );
822 - _this.form_post_override = false;
823 - }
824 - // Show warning
825 - _this.updateProgressWin(
826 - gM( 'mwe-uploadwarning' ),
827 - '<h3>' + gM( 'mwe-uploadwarning' ) + '</h3>' + wmsg + '<p>',
828 - buttons );
829 - return false;
830 - }
831 - // No error!
832 - return true;
833 - },
834 -
835 - /**
836 - * Process the result of an action=upload API request. Display the result
837 - * to the user.
838 - *
839 - * @param {Object} apiRes Api result object
840 - * @return {Boolean}
841 - * false if api error
842 - * true if success & interface has been updated
843 - */
844 - processApiResult: function( apiRes ) {
845 - var _this = this;
846 - mw.log( 'processApiResult::' );
847 -
848 - if ( !_this.isApiSuccess( apiRes ) ) {
849 - // Error detected, show it to the user
850 - _this.showApiError( apiRes );
851 - return false;
852 - }
853 - if ( apiRes.upload && apiRes.upload.upload_session_key ) {
854 - // Async upload, do AJAX status polling
855 - _this.upload_session_key = apiRes.upload.upload_session_key;
856 - _this.doAjaxUploadStatus();
857 - mw.log( "set upload_session_key: " + _this.upload_session_key );
858 - return;
859 - }
860 -
861 - if ( apiRes.upload && apiRes.upload.imageinfo && apiRes.upload.imageinfo.descriptionurl ) {
862 - var url = apiRes.upload.imageinfo.descriptionurl;
863 -
864 - // Upload complete.
865 - // Call the completion callback if available.
866 - if ( _this.done_upload_cb && typeof _this.done_upload_cb == 'function' ) {
867 - mw.log( "call done_upload_cb" );
868 - // This overrides our normal completion handling so we close the
869 - // dialog immediately.
870 - $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
871 - _this.done_upload_cb( apiRes.upload );
872 - return false;
873 - }
874 -
875 - var buttons = {};
876 - // "Return" button
877 - buttons[ gM( 'mwe-return-to-form' ) ] = function() {
878 - $j( this ).dialog( 'destroy' ).remove();
879 - _this.form_post_override = false;
880 - }
881 - // "Go to resource" button
882 - buttons[ gM('mwe-go-to-resource') ] = function() {
883 - window.location = url;
884 - };
885 - _this.action_done = true;
886 - _this.updateProgressWin(
887 - gM( 'mwe-successfulupload' ),
888 - gM( 'mwe-upload_done', url),
889 - buttons );
890 - mw.log( 'apiRes.upload.imageinfo::' + url );
891 - return true;
892 - }
893 - },
894 -
895 - /**
896 - * Update the progress window to display a given message, with a given
897 - * list of buttons below it.
898 - *
899 - * @param title_txt Plain text
900 - * @param msg HTML
901 - * @param buttons See http://docs.jquery.com/UI/Dialog#option-buttons
902 - */
903 - updateProgressWin: function( title_txt, msg, buttons ) {
904 - var _this = this;
905 -
906 - if ( !title_txt )
907 - title_txt = _this.getProgressTitle();
908 -
909 - if ( !msg )
910 - msg = mw.loading_spinner( 'left:40%;top:40px;' );
911 -
912 - if ( !buttons ) {
913 - // If no buttons are specified, add a close button
914 - buttons = {};
915 - buttons[ gM( 'mwe-ok' ) ] = function() {
916 - $j( this ).dialog( 'close' );
917 - };
918 - }
919 -
920 - $j( '#upProgressDialog' ).dialog( 'option', 'title', title_txt );
921 - $j( '#upProgressDialog' ).html( msg );
922 - $j( '#upProgressDialog' ).dialog( 'option', 'buttons', buttons );
923 - },
924 -
925 - /**
926 - * Get the default title of the progress window
927 - */
928 - getProgressTitle: function() {
929 - return gM( 'mwe-upload-in-progress' );
930 - },
931 -
932 - /**
933 - * Get the DOMNode of the form element we are rewriting.
934 - * Returns false if it can't be found.
935 - */
936 - getForm: function() {
937 -
938 - /*debugger;
939 - var cat = this.form_selector;
940 - var forms = document.getElementsByTagName('form');
941 - mw.log('got ' + forms.length + ' foms ');
942 - for( var i in forms ){
943 - var fish = forms[ i ];
944 - mw.log( 'fish: ' + fish.id );
945 - }
946 - var cat = $j( this.form_selector ).get(0);
947 - mw.log( 'getForm::' + cat.id );
948 - */
949 - if ( this.form_selector && $j( this.form_selector ).length != 0 ) {
950 - return $j( this.form_selector ).get( 0 );
951 - } else {
952 - mw.log( "mvBaseUploadInterface.getForm(): no form_selector" );
953 - return false;
954 - }
955 - },
956 -
957 - /**
958 - * Update the progress bar to a given completion fraction (between 0 and 1)
959 - * XXX This progress bar is used for encoding AND for upload... may need to fix that
960 - */
961 - updateProgress: function( fraction ) {
962 - var _this = this;
963 -
964 - $j( '#up-progressbar' ).progressbar( 'value', parseInt( fraction * 100 ) );
965 - $j( '#up-pstatus' ).html( parseInt( fraction * 100 ) + '% - ' );
966 -
967 - if (_this.uploadBeginTime) {
968 - var elapsedMilliseconds = ( new Date() ).getTime() - _this.uploadBeginTime;
969 - if (fraction > 0.0 && elapsedMilliseconds > 0) { // or some other minimums for good data
970 - var fractionPerMillisecond = fraction / elapsedMilliseconds;
971 - var remainingSeconds = parseInt( ( ( 1.0 - fraction ) / fractionPerMillisecond ) / 1000 );
972 - $j( '#up-etr' ).html( gM( 'mwe-uploaded-time-remaining', mw.seconds2npt(remainingSeconds) ) );
973 - }
974 - }
975 -
976 - },
977 -
978 - /**
979 - * Show a dialog box reporting upload progress and status
980 - */
981 - displayProgressOverlay: function() {
982 - var _this = this;
983 - // Remove the old instance if present
984 - if( $j( '#upProgressDialog' ).length != 0 ) {
985 - $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
986 - }
987 - // Add a new one
988 - $j( 'body' ).append( '<div id="upProgressDialog" ></div>' );
989 -
990 - $j( '#upProgressDialog' ).dialog( {
991 - title: _this.getProgressTitle(),
992 - bgiframe: true,
993 - modal: true,
994 - draggable: true,
995 - width: 400,
996 - heigh: 200,
997 - beforeclose: function( event, ui ) {
998 - // If the upload is not complete, ask the user if they want to cancel
999 - if ( event.button == 0 && _this.action_done === false ) {
1000 - _this.onCancel( this );
1001 - return false;
1002 - } else {
1003 - // Complete already, allow close
1004 - return true;
1005 - }
1006 - },
1007 - buttons: _this.getCancelButton()
1008 - } );
1009 - mw.log( 'upProgressDialog::dialog done' );
1010 -
1011 - $j( '#upProgressDialog' ).html(
1012 - '<div id="up-pbar-container" style="width:90%;height:15px;" >' +
1013 - '<div id="up-progressbar" style="height:15px;"></div>' +
1014 - '<div id="up-status-container">' +
1015 - '<span id="up-pstatus">0% - </span> ' +
1016 - '<span id="up-status-state">' + gM( 'mwe-uploaded-status' ) + '</span> ' +
1017 - '</div>' +
1018 - '<div id="up-etr">' + gM( 'mwe-uploaded-time-remaining', '' ) + '</div>' +
1019 - '</div>'
1020 - );
1021 - // Open the empty progress window
1022 - $j( '#upProgressDialog' ).dialog( 'open' );
1023 -
1024 - // Create progress bar
1025 - $j( '#up-progressbar' ).progressbar({
1026 - value: 0
1027 - });
1028 - },
1029 -
1030 - /**
1031 - * Get a standard cancel button in the jQuery.ui dialog format
1032 - */
1033 - getCancelButton: function() {
1034 - var _this = this;
1035 - mw.log( 'f: getCancelButton()' );
1036 - var cancelBtn = [];
1037 - cancelBtn[ gM( 'mwe-cancel' ) ] = function() {
1038 - $j( dlElm ).dialog( 'close' );
1039 - };
1040 - return cancelBtn;
1041 - },
1042 -
1043 - /**
1044 - * UI cancel button handler.
1045 - * Show a dialog box asking the user whether they want to cancel an upload.
1046 - * @param Element dialogElement Dialog element to be canceled
1047 - */
1048 - onCancel: function( dialogElement ) {
1049 - //confirm:
1050 - if ( confirm( gM( 'mwe-cancel-confim' ) ) ) {
1051 - // NOTE: (cancel the encode / upload)
1052 - $j( dialogElement ).dialog( 'close' );
1053 - }
1054 - }
1055 -
1056 -};
1057 -
1058 -// jQuery plugins
1059 -
1060 -( function( $ ) {
1061 - /**
1062 - * Check the upload destination filename for conflicts and show a conflict
1063 - * error message if there is one
1064 - */
1065 - $.fn.doDestCheck = function( opt ) {
1066 - var _this = this;
1067 - mw.log( 'doDestCheck::' + _this.selector );
1068 -
1069 - // Set up option defaults
1070 - if ( !opt.warn_target )
1071 - opt.warn_target = '#wpDestFile-warning';
1072 -
1073 - // Add the wpDestFile-warning row
1074 - if ( $j( '#wpDestFile-warning' ).length == 0 ) {
1075 - $j( '#mw-htmlform-options tr:last' )
1076 - .after(
1077 - $j('<tr />' )
1078 - .append( '<td />' )
1079 - .append( '<td />' )
1080 - .attr('id', 'wpDestFile-warning')
1081 - );
1082 - }
1083 - mw.log( 'past dest');
1084 - // Remove any existing warning
1085 - $j( opt.warn_target ).empty();
1086 - mw.log( 'past remove warn:: ' + _this.selector);
1087 - // Show the AJAX spinner
1088 - $j( _this.selector ).after(
1089 - $j('<img />')
1090 - .attr({
1091 - 'id' : "mw-spinner-wpDestFile",
1092 - 'src' : stylepath + '/common/images/spinner.gif'
1093 - })
1094 - );
1095 - mw.log("added spiner");
1096 - var request = {
1097 - 'titles': 'File:' + $j( _this.selector ).val(),
1098 - 'prop': 'imageinfo',
1099 - 'iiprop': 'url|mime|size',
1100 - 'iiurlwidth': 150
1101 - };
1102 -
1103 - // Do the destination check ( on the local wiki )
1104 - mw.getJSON( request, function( data ) {
1105 - // Remove spinner
1106 - $j( '#mw-spinner-wpDestFile' ).remove();
1107 -
1108 - if ( !data || !data.query || !data.query.pages ) {
1109 - // Ignore a null result
1110 - return;
1111 - }
1112 -
1113 - if ( data.query.pages[-1] ) {
1114 - // No conflict found
1115 - return;
1116 - }
1117 - for ( var page_id in data.query.pages ) {
1118 - if ( !data.query.pages[ page_id ].imageinfo ) {
1119 - continue;
1120 - }
1121 -
1122 - // Conflict found, show warning
1123 - if ( data.query.normalized ) {
1124 - var ntitle = data.query.normalized[0].to;
1125 - } else {
1126 - var ntitle = data.query.pages[ page_id ].title
1127 - }
1128 - var img = data.query.pages[ page_id ].imageinfo[0];
1129 - $j( '#wpDestFile-warning' ).html(
1130 - gM( 'mwe-fileexists', ntitle ) +
1131 - '<div class="thumb tright">' +
1132 - '<div ' +
1133 - 'style="width: ' + ( parseInt( img.thumbwidth ) + 2 ) + 'px;" ' +
1134 - 'class="thumbinner">' +
1135 - '<a ' +
1136 - 'title="' + ntitle + '" ' +
1137 - 'class="image" ' +
1138 - 'href="' + img.descriptionurl + '">' +
1139 - '<img ' +
1140 - 'width="' + img.thumbwidth + '" ' +
1141 - 'height="' + img.thumbheight + '" ' +
1142 - 'border="0" ' +
1143 - 'class="thumbimage" ' +
1144 - 'src="' + img.thumburl + '" ' +
1145 - 'alt="' + ntitle + '"/>' +
1146 - '</a>' +
1147 - '<div class="thumbcaption">' +
1148 - '<div class="magnify">' +
1149 - '<a title="' + gM('thumbnail-more') + '" class="internal" ' +
1150 - 'href="' + img.descriptionurl +'">' +
1151 - '<img width="15" height="11" alt="" ' +
1152 - 'src="' + stylepath + "/common/images/magnify-clip.png\" />" +
1153 - '</a>' +
1154 - '</div>' +
1155 - gM( 'mwe-fileexists-thumb' ) +
1156 - '</div>' +
1157 - '</div>' +
1158 - '</div>'
1159 - );
1160 - }
1161 - }
1162 - );
1163 - }
1164 -})( jQuery );
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/loader.js
@@ -1,126 +1,129 @@
22 /*
33 * Loader for libAddMedia module:
44 */
5 -mw.addMessages( {
6 - "mwe-loading-add-media-wiz" : "Loading add media wizard"
7 -});
85
9 -// Add class file paths ( From ROOT )
10 -mw.addClassFilePaths( {
11 - "$j.fn.dragDropFile" : "modules/AddMedia/jquery.dragDropFile.js",
12 - "$j.fn.simpleUploadForm": "modules/AddMedia/jquery.simpleUploadForm.js",
 6+// Scope everythign in "mw" ( keeps the global namespace clean )
 7+( function( mw ) {
 8+
 9+ mw.addMessages( {
 10+ "mwe-loading-add-media-wiz" : "Loading add media wizard"
 11+ });
1312
14 - "mw.BaseUploadInterface": "modules/AddMedia/mw.BaseUploadInterface.js",
15 - "mw.Firefogg" : "modules/AddMedia/mw.Firefogg.js",
16 - "mw.FirefoggGUI" : "modules/AddMedia/mw.FirefoggGUI.js",
17 - "mw.FirefoggRender" : "modules/libSequencer/mw.FirefoggRender.js",
18 - "mw.RemoteSearchDriver" : "modules/AddMedia/mw.RemoteSearchDriver.js",
 13+ // Add class file paths ( From ROOT )
 14+ mw.addClassFilePaths( {
 15+ "$j.fn.dragDropFile" : "modules/AddMedia/jquery.dragDropFile.js",
 16+ "$j.fn.simpleUploadForm": "modules/AddMedia/jquery.simpleUploadForm.js",
 17+
 18+ "mw.BaseUploadHandler": "modules/AddMedia/mw.BaseUploadHandler.js",
 19+ "mw.Firefogg" : "modules/AddMedia/mw.Firefogg.js",
 20+ "mw.FirefoggGUI" : "modules/AddMedia/mw.FirefoggGUI.js",
 21+ "mw.FirefoggRender" : "modules/libSequencer/mw.FirefoggRender.js",
 22+ "mw.RemoteSearchDriver" : "modules/AddMedia/mw.RemoteSearchDriver.js",
 23+ "mw.InterfaceDispatch" : "modules/AddMedia/mw.InterfaceDispatch.js",
 24+
 25+ "baseRemoteSearch" : "modules/AddMedia/searchLibs/baseRemoteSearch.js",
 26+ "mediaWikiSearch" : "modules/AddMedia/searchLibs/mediaWikiSearch.js",
 27+ "metavidSearch" : "modules/AddMedia/searchLibs/metavidSearch.js",
 28+ "archiveOrgSearch" : "modules/AddMedia/searchLibs/archiveOrgSearch.js",
 29+ "flickrSearch" : "modules/AddMedia/searchLibs/flickrSearch.js",
 30+ "baseRemoteSearch" : "modules/AddMedia/searchLibs/baseRemoteSearch.js",
 31+ "kalturaSearch" : "modules/AddMedia/searchLibs/kalturaSearch.js"
 32+ });
1933
20 - "baseRemoteSearch" : "modules/AddMedia/searchLibs/baseRemoteSearch.js",
21 - "mediaWikiSearch" : "modules/AddMedia/searchLibs/mediaWikiSearch.js",
22 - "metavidSearch" : "modules/AddMedia/searchLibs/metavidSearch.js",
23 - "archiveOrgSearch" : "modules/AddMedia/searchLibs/archiveOrgSearch.js",
24 - "flickrSearch" : "modules/AddMedia/searchLibs/flickrSearch.js",
25 - "baseRemoteSearch" : "modules/AddMedia/searchLibs/baseRemoteSearch.js",
26 - "kalturaSearch" : "modules/AddMedia/searchLibs/kalturaSearch.js"
27 -});
28 -
29 -/**
30 -* Note: We should move relevant parts of these style sheets to the addMedia/css folder
31 -* phase 2: We should separate out sheet sets per sub-module:
32 -*/
33 -
34 -//Setup the addMediaWizard module
35 -mw.addModuleLoader( 'AddMedia.addMediaWizard', function( callback ){
36 - // Load all the required libs:
37 - var request = [
38 - [ 'mw.RemoteSearchDriver',
39 - '$j.cookie',
40 - '$j.fn.textSelection',
41 - '$j.browserTest',
42 - '$j.ui'
43 - ], [
44 - '$j.ui.resizable',
45 - '$j.ui.draggable',
46 - '$j.ui.dialog',
47 - '$j.ui.tabs',
48 - '$j.ui.sortable'
49 - ]
50 - ];
51 - mw.load( request , function() {
52 - callback( 'AddMedia.addMediaWizard' );
53 - } );
54 -});
55 -
56 -/*
57 -* Upload interface loader:
58 -*/
59 -
60 -mw.addModuleLoader( 'AddMedia.baseUploadInterface', function( callback ){
61 - mw.load( [
 34+ /**
 35+ * Note: We should move relevant parts of these style sheets to the addMedia/css folder
 36+ * phase 2: We should separate out sheet sets per sub-module:
 37+ */
 38+
 39+ //Setup the addMediaWizard module
 40+ mw.addModuleLoader( 'AddMedia.addMediaWizard', function( callback ){
 41+ // Load all the required libs:
 42+ var request = [
 43+ [ 'mw.RemoteSearchDriver',
 44+ '$j.cookie',
 45+ '$j.fn.textSelection',
 46+ '$j.browserTest',
 47+ '$j.ui'
 48+ ], [
 49+ '$j.ui.resizable',
 50+ '$j.ui.draggable',
 51+ '$j.ui.dialog',
 52+ '$j.ui.tabs',
 53+ '$j.ui.sortable'
 54+ ]
 55+ ];
 56+ mw.load( request , function() {
 57+ callback( 'AddMedia.addMediaWizard' );
 58+ } );
 59+ });
 60+
 61+ //Set a variable for the base upload interface for easy inclution
 62+ var baseUploadlibs = [
6263 [
63 - 'mw.BaseUploadInterface',
 64+ 'mw.BaseUploadHandler',
 65+ 'mw.InterfaceDispatch',
6466 '$j.ui'
6567 ],
6668 [
6769 '$j.ui.progressbar',
68 - '$j.ui.dialog'
 70+ '$j.ui.dialog',
 71+ '$j.ui.draggable'
6972 ]
70 - ], function() {
71 - callback( 'AddMedia.baseUploadInterface' );
72 - });
73 -});
74 -
75 -/**
76 - * The Firefogg loaders
77 - *
78 - * Includes both firefogg & firefogg "GUI" which share some loading logic:
79 - */
80 -var mwBaseFirefoggReq = [
81 - [
82 - 'mw.BaseUploadInterface',
83 - 'mw.Firefogg',
84 - '$j.ui'
85 - ],
86 - [
87 - '$j.ui.progressbar',
88 - '$j.ui.dialog',
89 - '$j.ui.draggable'
90 - ]
91 -];
92 -
93 -mw.addModuleLoader( 'AddMedia.firefogg', function( callback ){
 73+ ];
9474
95 - //Load firefogg libs
96 - mw.load( mwBaseFirefoggReq, function() {
97 - callback( 'AddMedia.firefogg' );
 75+ /*
 76+ * Upload interface loader:
 77+ */
 78+
 79+ mw.addModuleLoader( 'AddMedia.BaseUploadHandler', function( callback ){
 80+ mw.load( baseUploadlibs , function() {
 81+ callback( 'AddMedia.BaseUploadHandler' );
 82+ });
9883 });
99 -} );
100 -
101 -mw.addModuleLoader( 'AddMedia.FirefoggGUI', function( callback ){
10284
103 - //Clone the array:
104 - var request = mwBaseFirefoggReq.slice( 0 ) ;
105 - //Add firefogg gui classes to a new "request" var:
106 - request.push( [
107 - 'mw.FirefoggGUI',
108 - '$j.cookie',
109 - '$j.ui.accordion',
110 - '$j.ui.slider',
111 - '$j.ui.datepicker'
112 - ] );
 85+ /**
 86+ * The Firefogg loaders
 87+ *
 88+ * Includes both firefogg & firefogg "GUI" which share some loading logic:
 89+ */
11390
114 - mw.load( request, function() {
115 - callback( 'AddMedia.FirefoggGUI' );
 91+ var mwBaseFirefoggReq = baseUploadlibs.slice( 0 )
 92+ mwBaseFirefoggReq[0].push('mw.Firefogg');
 93+
 94+ mw.addModuleLoader( 'AddMedia.firefogg', function( callback ){
 95+
 96+ //Load firefogg libs
 97+ mw.load( mwBaseFirefoggReq, function() {
 98+ callback( 'AddMedia.firefogg' );
 99+ });
 100+ } );
 101+
 102+ mw.addModuleLoader( 'AddMedia.FirefoggGUI', function( callback ){
 103+
 104+ //Clone the array:
 105+ var request = mwBaseFirefoggReq.slice( 0 ) ;
 106+ //Add firefogg gui classes to a new "request" var:
 107+ request.push( [
 108+ 'mw.FirefoggGUI',
 109+ '$j.cookie',
 110+ '$j.ui.accordion',
 111+ '$j.ui.slider',
 112+ '$j.ui.datepicker'
 113+ ] );
 114+
 115+ mw.load( request, function() {
 116+ callback( 'AddMedia.FirefoggGUI' );
 117+ });
 118+ } );
 119+
 120+ mw.addModuleLoader( 'AddMedia.firefoggRender', function( callback ){
 121+ mw.load( [
 122+ 'mw.BaseUploadHandler',
 123+ 'mw.Firefogg',
 124+ 'mw.FirefoggRender'
 125+ ], function() {
 126+ callback( 'AddMedia.firefoggRender' );
 127+ });
116128 });
117 -} );
118129
119 -mw.addModuleLoader( 'AddMedia.firefoggRender', function( callback ){
120 - mw.load( [
121 - 'mw.BaseUploadInterface',
122 - 'mw.Firefogg',
123 - 'mw.FirefoggRender'
124 - ], function() {
125 - callback( 'AddMedia.firefoggRender' );
126 - });
127 -});
\ No newline at end of file
 130+} )( window.mw );
\ No newline at end of file
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.Firefogg.js
@@ -115,7 +115,7 @@
116116 mw.Firefogg = function( options ) {
117117 return this.init( options );
118118 };
119 -mw.Firefogg.prototype = { // extends mw.BaseUploadInterface
 119+mw.Firefogg.prototype = { // extends mw.BaseUploadHandler
120120 min_firefogg_version: '1.1.0',
121121 default_encoder_settings: { // NOTE: allow the server to set these
122122 'maxSize' : '400',
@@ -152,9 +152,9 @@
153153 }
154154 }
155155
156 - // Inherit from mw.BaseUploadInterface (unless we're in only_firefogg mode)
 156+ // Inherit from mw.BaseUploadHandler (unless we're in only_firefogg mode)
157157 if ( !this.only_firefogg ) {
158 - var myBUI = new mw.BaseUploadInterface( options );
 158+ var myBUI = new mw.BaseUploadHandler( options );
159159
160160 // Prefix conflicting members with pe_
161161 for ( var i in myBUI ) {
@@ -413,7 +413,7 @@
414414 },
415415
416416 /**
417 - * Display an upload progress overlay. Overrides the function in mw.BaseUploadInterface.
 417+ * Display an upload progress overlay. Overrides the function in mw.BaseUploadHandler.
418418 */
419419 displayProgressOverlay: function() {
420420 this.pe_displayProgressOverlay();
@@ -561,7 +561,7 @@
562562 /**
563563 * Get the DOMNode of the form element we are rewriting.
564564 * Returns false if it can't be found.
565 - * Overrides mw.BaseUploadInterface.getForm().
 565+ * Overrides mw.BaseUploadHandler.getForm().
566566 */
567567 getForm: function() {
568568 if ( this.form_selector ) {
@@ -826,7 +826,7 @@
827827
828828 /**
829829 * Do an upload, with the mode given by this.upload_mode
830 - * XXX should probably be dispatched from baseUploadInterface doUpload instead
 830+ * XXX should probably be dispatched from BaseUploadHandler doUpload instead
831831 */
832832 doUpload: function() {
833833 var _this = this;
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.BaseUploadHandler.js
@@ -0,0 +1,847 @@
 2+/**
 3+ * The base upload interface.
 4+ *
 5+ * Progress bars for http-copy-by-url uploading.
 6+ * Ifame upload target
 7+ *
 8+ * This base upload class is optionally extended by Firefogg
 9+ *
 10+ */
 11+mw.addMessages({
 12+ "mwe-upload-transcode-in-progress" : "Transcode and upload in progress (do not close this window)",
 13+ "mwe-upload-in-progress" : "Upload in progress (do not close this window)",
 14+ "mwe-upload-transcoded-status" : "Transcoded",
 15+ "mwe-uploaded-time-remaining" : "Time remaining: $1",
 16+ "mwe-uploaded-status" : "Uploaded",
 17+ "mwe-upload-stats-fileprogress" : "$1 of $2",
 18+ "mwe-upload_completed" : "Your upload is complete",
 19+ "mwe-upload_done" : "<a href=\"$1\">Your upload <i>should be<\/i> accessible<\/a>.",
 20+ "mwe-upload-unknown-size" : "Unknown size",
 21+ "mwe-cancel-confim" : "Are you sure you want to cancel?",
 22+ "mwe-successfulupload" : "Upload successful",
 23+ "mwe-uploaderror" : "Upload error",
 24+ "mwe-uploadwarning" : "Upload warning",
 25+ "mwe-unknown-error" : "Unknown error:",
 26+ "mwe-return-to-form" : "Return to form",
 27+ "mwe-file-exists-duplicate" : "This file is a duplicate of the following file:",
 28+ "mwe-fileexists" : "A file with this name exists already. Please check <b><tt>$1<\/tt><\/b> if you are not sure if you want to change it.",
 29+ "mwe-fileexists-thumb" : "<center><b>Existing file<\/b><\/center>",
 30+ "mwe-ignorewarning" : "Ignore warning and save file anyway",
 31+ "mwe-file-thumbnail-no" : "The filename begins with <b><tt>$1<\/tt><\/b>",
 32+ "mwe-go-to-resource" : "Go to resource page",
 33+ "mwe-upload-misc-error" : "Unknown upload error",
 34+ "mwe-wgfogg_warning_bad_extension" : "You have selected a file with an unsuported extension (<a href=\"http:\/\/commons.wikimedia.org\/wiki\/Commons:Firefogg#Supported_File_Types\">more information<\/a>)."
 35+});
 36+
 37+var default_bui_options = {
 38+ // Target api to upload to
 39+ 'api_url' : null,
 40+
 41+ // The selected form
 42+ 'form' : null,
 43+
 44+ // Callback for once the upload is done
 45+ 'done_upload_cb' : null,
 46+
 47+ // A selector for the form target
 48+ 'form_selector' : null,
 49+
 50+ // Default upload mode is 'api'
 51+ 'upload_mode' : 'api',
 52+
 53+ // Callback for modifing form data on submit
 54+ 'onsubmit_cb' : null,
 55+
 56+ // The interface type sent to mw.interfaceDispatch factory
 57+ // can be 'dialog', 'iframe', 'inline'
 58+ 'interface_type' : 'dialog'
 59+
 60+}
 61+mw.BaseUploadHandler = function( options ) {
 62+ return this.init( options );
 63+}
 64+
 65+mw.BaseUploadHandler.prototype = {
 66+
 67+ // The form data to be submitted
 68+ formData: {},
 69+
 70+ // Upload warning session key, for continued uploads
 71+ warnings_sessionkey: null,
 72+
 73+ // If chunks uploading is supported
 74+ chunks_supported: true,
 75+
 76+ // If the existing form should be used to post to the api
 77+ // Since file selection can't be "moved" we have to use the exising
 78+ // form and just submit it to a diffrent target
 79+ form_post_override: false,
 80+
 81+ // http copy by url mode flag
 82+ http_copy_upload : null,
 83+
 84+ // If the upload action is done
 85+ action_done: false,
 86+
 87+ // Edit token for upload
 88+ editToken: false,
 89+
 90+ // The DOM node for the upload form
 91+ form: false,
 92+
 93+ // The following are really state of the upload, not the interface.
 94+ // we are currently only managing one, so this is okay... for now.
 95+ uploadBeginTime: null,
 96+
 97+
 98+ /**
 99+ * Object initialisation
 100+ * @param {Object} options BaseUpload options see default_bui_options
 101+ */
 102+ init: function( options ) {
 103+ if ( !options )
 104+ options = {};
 105+ $j.extend( this, default_bui_options, options );
 106+ this.interfaceDispatch = mw.InterfaceDispatch.factory( this.interface_type );
 107+
 108+ mw.log( "init mvBaseUploadHandler:: " + this.api_url );
 109+ },
 110+
 111+ /**
 112+ * Set up the upload form, register onsubmit handler.
 113+ * May remap it to use the API field names.
 114+ */
 115+ setupForm: function() {
 116+ mw.log( "Base::setupForm::" );
 117+ var _this = this;
 118+
 119+ // Set up the local pointer to the edit form:
 120+ this.form = this.getForm();
 121+
 122+ if ( !this.form ) {
 123+ mw.log( "Upload form not found!" );
 124+ return;
 125+ }
 126+
 127+ // Set up the orig_onsubmit if not set:
 128+ if ( typeof( this.orig_onsubmit ) == 'undefined' && this.form.onsubmit ) {
 129+ this.orig_onsubmit = this.form.onsubmit;
 130+ }
 131+
 132+ // Set up the submit action:
 133+ $j( this.form ).submit( function() {
 134+ mw.log( "FORM SUBMIT::" );
 135+ var data = $j( this ).serializeArray();
 136+ for ( var i = 0; i < data.length; i++ ) {
 137+ mw.log( $j( data[i] ).attr('name') + ' : ' + $j(data[i]).val() );
 138+ }
 139+
 140+ return _this.onSubmit();
 141+ } );
 142+ },
 143+
 144+ /**
 145+ * onSubmit handler for the upload form
 146+ */
 147+ onSubmit: function() {
 148+ var _this = this;
 149+ mw.log( 'Base::onSubmit:' );
 150+ // Run the original onsubmit (if not run yet set flag to avoid excessive chaining)
 151+ if ( typeof( this.orig_onsubmit ) == 'function' ) {
 152+ if ( ! this.orig_onsubmit() ) {
 153+ //error in orig submit return false;
 154+ return false;
 155+ }
 156+ }
 157+ // Call the onsubmit_cb option if set:
 158+ if( this.onsubmit_cb && typeof this.onsubmit_cb == 'function' ){
 159+ this.onsubmit_cb();
 160+ }
 161+
 162+ // Remap the upload form to the "api" form:
 163+ this.remapFormToApi();
 164+
 165+ // Check for post action override
 166+ if ( this.form_post_override ) {
 167+ mw.log( 'form_post_override is true, do ordinary form submit' );
 168+ return true;
 169+ }
 170+
 171+
 172+ // Put into a try catch so we are sure to return false:
 173+ try {
 174+ // Startup interface dispatch dialog
 175+ this.interfaceDispatch.setup();
 176+ //this.displayProgressOverlay
 177+
 178+
 179+ // For some unknown reason we have to drop down the #p-search z-index:
 180+ $j( '#p-search' ).css( 'z-index', 1 );
 181+
 182+ var _this = this;
 183+ _this.detectUploadMode( function( mode ) {
 184+ _this.upload_mode = mode;
 185+ _this.doUpload();
 186+ } );
 187+ } catch( e ) {
 188+ mw.log( '::error in interfaceDispatch or doUpload ' + e );
 189+ }
 190+
 191+ // Don't submit the form we will do the post in ajax
 192+ return false;
 193+ },
 194+
 195+ /**
 196+ * Determine the correct upload mode.
 197+ *
 198+ * If this.upload_mode is autodetect, this runs an API call to find out if MW
 199+ * supports uploading. It then sets the upload mode when this call returns.
 200+ *
 201+ * When done detecting, or if detecting is unnecessary, it calls the callback
 202+ * with the upload mode as the first parameter.
 203+ *
 204+ * @param {Function} callback Function called once upload mode is detected
 205+ */
 206+ detectUploadMode: function( callback ) {
 207+ var _this = this;
 208+ mw.log( 'detectUploadMode::' + _this.upload_mode );
 209+ //debugger;
 210+ // Check the upload mode
 211+ if ( _this.upload_mode == 'detect_in_progress' ) {
 212+ // Don't send another request, wait for the pending one.
 213+ } else if ( !_this.isCopyUpload() ) {
 214+ callback( 'post' );
 215+ } else if ( _this.upload_mode == 'autodetect' ) {
 216+ mw.log( 'detectUploadMode::' + _this.upload_mode + ' api:' + _this.api_url );
 217+ if( !_this.api_url ) {
 218+ mw.log( 'Error: can\'t autodetect mode without api url' );
 219+ return;
 220+ }
 221+
 222+ // Don't send multiple requests
 223+ _this.upload_mode = 'detect_in_progress';
 224+
 225+ // FIXME: move this to configuration and avoid this API request
 226+ mw.getJSON( _this.api_url, { 'action' : 'paraminfo', 'modules' : 'upload' }, function( data ) {
 227+ if ( typeof data.paraminfo == 'undefined'
 228+ || typeof data.paraminfo.modules == 'undefined' )
 229+ {
 230+ return mw.log( 'Error: bad api results' );
 231+ }
 232+ if ( typeof data.paraminfo.modules[0].classname == 'undefined' ) {
 233+ mw.log( 'Autodetect Upload Mode: \'post\' ' );
 234+ _this.upload_mode = 'post';
 235+ callback( 'post' );
 236+ } else {
 237+ mw.log( 'Autodetect Upload Mode: api ' );
 238+ _this.upload_mode = 'api';
 239+ // Check to see if chunks are supported
 240+ for ( var i in data.paraminfo.modules[0].parameters ) {
 241+ var pname = data.paraminfo.modules[0].parameters[i].name;
 242+ if( pname == 'enablechunks' ) {
 243+ mw.log( 'this.chunks_supported = true' );
 244+ _this.chunks_supported = true;
 245+ break;
 246+ }
 247+ }
 248+ callback( 'api' );
 249+ }
 250+ }
 251+ );
 252+ } else if ( _this.upload_mode == 'api' ) {
 253+ callback( 'api' );
 254+ } else if ( _this.upload_mode == 'post' ) {
 255+ callback( 'post' );
 256+ } else {
 257+ mw.log( 'Error: unrecongized upload mode: ' + _this.upload_mode );
 258+ }
 259+ },
 260+
 261+ /**
 262+ * Do an upload, with the mode given by this.upload_mode
 263+ */
 264+ doUpload: function() {
 265+ // Note "api" should be called "http_copy_upload" and /post/ should be "form_upload"
 266+ this.uploadBeginTime = (new Date()).getTime();
 267+ if ( this.upload_mode == 'api' ) {
 268+ this.doApiCopyUpload();
 269+ } else if ( this.upload_mode == 'post' ) {
 270+ this.doPostUpload();
 271+ } else {
 272+ mw.log( 'Error: unrecongized upload mode: ' + this.upload_mode );
 273+ }
 274+ },
 275+
 276+ /**
 277+ * Change the upload form so that when submitted, it sends a request to
 278+ * the MW API.
 279+ *
 280+ * This is rather ugly, but solutions are constrained by the fact that
 281+ * file inputs can't be moved around or recreated after the user has
 282+ * selected a file in them, which they may well do before DOM ready.
 283+ *
 284+ * It is also constrained by upload form hacks on commons.
 285+ */
 286+ remapFormToApi: function() {
 287+ var _this = this;
 288+ //
 289+ mw.log("remapFormToApi:: " + this.api_url + ' form: ' + this.form);
 290+
 291+ if ( !this.api_url ){
 292+ mw.log( 'Error: no api url target' );
 293+ return false;
 294+ }
 295+ var $form = $j( this.form_selector );
 296+
 297+ // Set the form action
 298+ try{
 299+ $form.attr('action', _this.api_url);
 300+ }catch(e){
 301+ mw.log("IE for some reason error's out when you change the action")
 302+ }
 303+
 304+ // Add API action
 305+ if ( $form.find( "[name='action']" ).length == 0 ){
 306+ $form.append(
 307+ $j('<input />')
 308+ .attr({
 309+ 'type': "hidden",
 310+ 'name' : "action",
 311+ 'value' : "upload"
 312+ })
 313+ )
 314+ }
 315+
 316+ // Add JSON response format
 317+ if ( $form.find( "[name='format']" ).length == 0 ){
 318+ $form.append(
 319+ $j( '<input />' )
 320+ .attr({
 321+ 'type' : "hidden",
 322+ 'name' : "format",
 323+ 'value' : "jsonfm"
 324+ })
 325+ )
 326+ }
 327+
 328+ // Map a new hidden form
 329+ $form.find( "[name='wpUploadFile']" ).attr( 'name', 'file' );
 330+ $form.find( "[name='wpDestFile']" ).attr( 'name', 'filename' );
 331+ $form.find( "[name='wpUploadDescription']" ).attr( 'name', 'comment' );
 332+ $form.find( "[name='wpEditToken']" ).attr( 'name', 'token' );
 333+ $form.find( "[name='wpIgnoreWarning']" ).attr( 'name', 'ignorewarnings' );
 334+ $form.find( "[name='wpWatchthis']" ).attr( 'name', 'watch' );
 335+
 336+ //mw.log( 'comment: ' + $form.find( "[name='comment']" ).val() );
 337+ },
 338+
 339+ /**
 340+ * Returns true if the current form has copy upload selected, false otherwise.
 341+ */
 342+ isCopyUpload: function() {
 343+ if ( $j( '#wpSourceTypeFile' ).length == 0
 344+ || $j( '#wpSourceTypeFile' ).get( 0 ).checked )
 345+ {
 346+ this.http_copy_upload = false;
 347+ } else if ( $j('#wpSourceTypeURL').get( 0 ).checked ) {
 348+ this.http_copy_upload = true;
 349+ }
 350+ return this.http_copy_upload;
 351+ },
 352+
 353+ /**
 354+ * Do an upload by submitting the form
 355+ */
 356+ doPostUpload: function() {
 357+ var _this = this;
 358+ var $form = $j( _this.form );
 359+ mw.log( 'mvBaseUploadHandler.doPostUpload' );
 360+ // Issue a normal post request
 361+ // Get the token from the page
 362+ _this.editToken = $j( "#wpEditToken" ).val();
 363+
 364+ // TODO check for sendAsBinary to support Firefox/HTML5 progress on upload
 365+
 366+ this.interfaceDispatch.setLoading();
 367+
 368+ // Add the iframe
 369+ _this.iframeId = 'f_' + ( $j( 'iframe' ).length + 1 );
 370+ //IE only works if you "create element with the name" (not jquery style
 371+ var iframe;
 372+ try {
 373+ iframe = document.createElement( '<iframe name="' + _this.iframeId + '">' );
 374+ } catch (ex) {
 375+ iframe = document.createElement('iframe');
 376+ }
 377+
 378+ $j( "body" ).append(
 379+ $j( iframe )
 380+ .attr({
 381+ 'src':'javascript:false;',
 382+ 'id':_this.iframeId,
 383+ 'name': _this.iframeId
 384+ })
 385+ .css('display', 'none')
 386+ );
 387+
 388+
 389+ // Set the form target to the iframe
 390+ $form.attr( 'target', _this.iframeId );
 391+
 392+ // Set up the completion callback
 393+ $j( '#' + _this.iframeId ).load( function() {
 394+ _this.processIframeResult( $j( this ).get( 0 ) );
 395+ });
 396+
 397+ // Do post override
 398+ _this.form_post_override = true;
 399+
 400+ $form.submit();
 401+ },
 402+
 403+ /**
 404+ * Do an upload by submitting an API request
 405+ */
 406+ doApiCopyUpload: function() {
 407+ mw.log( 'mvBaseUploadHandler.doApiCopyUpload' );
 408+ mw.log( 'doHttpUpload (no form submit) ' );
 409+
 410+ var httpUpConf = {
 411+ 'url' : $j( '#wpUploadFileURL' ).val(),
 412+ 'filename' : $j( '#wpDestFile' ).val(),
 413+ 'comment' : this.getUploadDescription(),
 414+ 'watch' : ( $j( '#wpWatchthis' ).is( ':checked' ) ) ? 'true' : 'false',
 415+ 'ignorewarnings': ($j('#wpIgnoreWarning' ).is( ':checked' ) ) ? 'true' : 'false'
 416+ }
 417+ //check for editToken
 418+ this.editToken = $j( "#wpEditToken" ).val();
 419+ this.doHttpUpload( httpUpConf );
 420+ },
 421+
 422+ /**
 423+ * Get the upload description, append the licence if avaliable
 424+ *
 425+ * NOTE: wpUploadDescription should be a configuration option.
 426+ *
 427+ * @return {String}
 428+ * value of wpUploadDescription
 429+ */
 430+ getUploadDescription: function(){
 431+ //Special case of upload.js commons hack:
 432+ var comment_value = $j( '#wpUploadDescription' ).val();
 433+ if( comment_value == '' ){
 434+ comment_value = $j( "[name='wpUploadDescription']").val();
 435+ }
 436+ //check for licence tag:
 437+ },
 438+
 439+ /**
 440+ * Process the result of the form submission, returned to an iframe.
 441+ * This is the iframe's onload event.
 442+ */
 443+ processIframeResult: function( iframe ) {
 444+ var _this = this;
 445+ var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document;
 446+ // Fix for Opera 9.26
 447+ if ( doc.readyState && doc.readyState != 'complete' ) {
 448+ return;
 449+ }
 450+ // Fix for Opera 9.64
 451+ if ( doc.body && doc.body.innerHTML == "false" ) {
 452+ return;
 453+ }
 454+ var response;
 455+ if ( doc.XMLDocument ) {
 456+ // The response is a document property in IE
 457+ response = doc.XMLDocument;
 458+ } else if ( doc.body ) {
 459+ // Get the json string
 460+ json = $j( doc.body ).find( 'pre' ).text();
 461+ //mw.log( 'iframe:json::' + json_str + "\nbody:" + $j( doc.body ).html() );
 462+ if ( json ) {
 463+ response = window["eval"]( "(" + json + ")" );
 464+ } else {
 465+ response = {};
 466+ }
 467+ } else {
 468+ // response is a xml document
 469+ response = doc;
 470+ }
 471+ // Process the API result
 472+ _this.processApiResult( response );
 473+ },
 474+
 475+ /**
 476+ * Do a generic action=upload API request and monitor its progress
 477+ */
 478+ doHttpUpload: function( params ) {
 479+ var _this = this;
 480+ // Get a clean setup of the interface dispatch
 481+ this.interfaceDispatch.setup();
 482+
 483+ //_this.displayProgressOverlay();
 484+
 485+ // Set the interface dispatch to loading ( in case we don't get an update for some time )
 486+ this.interfaceDispatch.setLoading();
 487+
 488+ // Set up the request
 489+ var request = {
 490+ 'action' : 'upload',
 491+ 'asyncdownload' : true // Do async download
 492+ };
 493+
 494+ // Add any parameters specified by the caller
 495+ for ( key in params ) {
 496+ if ( !request[key] ) {
 497+ request[key] = params[key];
 498+ }
 499+ }
 500+
 501+ // Add the edit token (if available)
 502+ if( !_this.editToken && _this.api_url ) {
 503+ mw.log( 'Error:doHttpUpload: missing token' );
 504+ } else {
 505+ request['token'] =_this.editToken;
 506+ }
 507+
 508+ // Reset the done with action flag
 509+ _this.action_done = false;
 510+
 511+ // Do the api request:
 512+ mw.getJSON(_this.api_url, request, function( data ) {
 513+ _this.processApiResult( data );
 514+ });
 515+ },
 516+
 517+ /**
 518+ * Start periodic checks of the upload status using XHR
 519+ */
 520+ doAjaxUploadStatus: function() {
 521+ var _this = this;
 522+
 523+ // Set up intterface dispatch to display for status updates:
 524+ this.interfaceDispatch.setup();
 525+ //this.displayProgressOverlay();
 526+
 527+ this.upload_status_request = {
 528+ 'action' : 'upload',
 529+ 'httpstatus' : 'true',
 530+ 'sessionkey' : _this.upload_session_key
 531+ };
 532+ // Add token if present
 533+ if ( this.editToken )
 534+ this.upload_status_request['token'] = this.editToken;
 535+
 536+ // Trigger an initial request (subsequent ones will be done by a timer)
 537+ this.onAjaxUploadStatusTimer();
 538+ },
 539+
 540+ /**
 541+ * This is called when the timer which separates XHR requests elapses.
 542+ * It starts a new request.
 543+ */
 544+ onAjaxUploadStatusTimer: function() {
 545+ var _this = this;
 546+ //do the api request:
 547+ mw.getJSON( this.api_url, this.upload_status_request, function ( data ) {
 548+ _this.onAjaxUploadStatusResponse( data );
 549+ } );
 550+ },
 551+
 552+ /**
 553+ * Called when a response to an upload status query is available.
 554+ * Starts the timer for the next upload status check.
 555+ */
 556+ onAjaxUploadStatusResponse: function( data ) {
 557+ var _this = this;
 558+ // Check if we are done
 559+ if ( data.upload['apiUploadResult'] ) {
 560+ //update status to 100%
 561+ _this.updateProgress( 1 );
 562+ //see if we need JSON
 563+ mw.load( [
 564+ 'JSON'
 565+ ], function() {
 566+ var apiResult = {};
 567+ try {
 568+ apiResult = JSON.parse( data.upload['apiUploadResult'] ) ;
 569+ } catch ( e ) {
 570+ //could not parse api result
 571+ mw.log( 'errro: could not parse apiUploadResult' )
 572+ }
 573+ _this.processApiResult( apiResult );
 574+ });
 575+ return ;
 576+ }
 577+
 578+ // else update status:
 579+ if ( data.upload['content_length'] && data.upload['loaded'] ) {
 580+ //we have content length we can show percentage done:
 581+ var fraction = data.upload['loaded'] / data.upload['content_length'];
 582+ //update the status:
 583+ _this.updateProgress( fraction );
 584+ //special case update the file progress where we have data size:
 585+ $j( '#up-status-container' ).html(
 586+ gM( 'mwe-upload-stats-fileprogress',
 587+ [
 588+ mw.lang.formatSize( data.upload['loaded'] ),
 589+ mw.lang.formatSize( data.upload['content_length'] )
 590+ ]
 591+ )
 592+ );
 593+ } else if( data.upload['loaded'] ) {
 594+ _this.updateProgress( 1 );
 595+ mw.log( 'just have loaded (no cotent length: ' + data.upload['loaded'] );
 596+ //for lack of content-length requests:
 597+ $j( '#up-status-container' ).html(
 598+ gM( 'mwe-upload-stats-fileprogress',
 599+ [
 600+ mw.lang.formatSize( data.upload['loaded'] ),
 601+ gM( 'mwe-upload-unknown-size' )
 602+ ]
 603+ )
 604+ );
 605+ }
 606+ if ( _this.api_url == 'proxy' ) {
 607+ // Do the updates a bit less often: every 4.2 seconds
 608+ var timeout = 4200;
 609+ } else {
 610+ // We got a result: set timeout to 100ms + your server update
 611+ // interval (in our case 2s)
 612+ var timeout = 2100;
 613+ }
 614+ setTimeout(
 615+ function() {
 616+ _this.onAjaxUploadStatusTimer();
 617+ },
 618+ timeout );
 619+ },
 620+
 621+ /**
 622+ * Returns true if an action=upload API result was successful, false otherwise
 623+ */
 624+ isApiSuccess: function( apiRes ) {
 625+ if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
 626+ return false;
 627+ }
 628+ if ( apiRes.upload && apiRes.upload.error ) {
 629+ return false;
 630+ }
 631+ if ( apiRes.upload && apiRes.upload.warnings ) {
 632+ return false;
 633+ }
 634+ return true;
 635+ },
 636+
 637+
 638+ /**
 639+ * Process the result of an action=upload API request. Display the result
 640+ * to the user.
 641+ *
 642+ * @param {Object} apiRes Api result object
 643+ * @return {Boolean}
 644+ * false if api error
 645+ * true if success & interface has been updated
 646+ */
 647+ processApiResult: function( apiRes ) {
 648+ var _this = this;
 649+ mw.log( 'processApiResult::' );
 650+
 651+ if ( !_this.isApiSuccess( apiRes ) ) {
 652+ // Error detected, show it to the user
 653+ _this.interfaceDispatch.showApiError( apiRes );
 654+ return false;
 655+ }
 656+ if ( apiRes.upload && apiRes.upload.upload_session_key ) {
 657+ // Async upload, do AJAX status polling
 658+ _this.upload_session_key = apiRes.upload.upload_session_key;
 659+ _this.doAjaxUploadStatus();
 660+ mw.log( "set upload_session_key: " + _this.upload_session_key );
 661+ return;
 662+ }
 663+
 664+ if ( apiRes.upload && apiRes.upload.imageinfo && apiRes.upload.imageinfo.descriptionurl ) {
 665+ var url = apiRes.upload.imageinfo.descriptionurl;
 666+
 667+ // Upload complete.
 668+ // Call the completion callback if available.
 669+ if ( _this.done_upload_cb && typeof _this.done_upload_cb == 'function' ) {
 670+ mw.log( "call done_upload_cb" );
 671+ // This overrides our normal completion handling so we close the
 672+ // dialog immediately.
 673+ $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
 674+ _this.done_upload_cb( apiRes.upload );
 675+ return false;
 676+ }
 677+
 678+ var buttons = {};
 679+ // "Return" button
 680+ buttons[ gM( 'mwe-return-to-form' ) ] = function() {
 681+ $j( this ).dialog( 'destroy' ).remove();
 682+ _this.form_post_override = false;
 683+ }
 684+ // "Go to resource" button
 685+ buttons[ gM('mwe-go-to-resource') ] = function() {
 686+ window.location = url;
 687+ };
 688+ _this.action_done = true;
 689+ _this.updateProgressWin(
 690+ gM( 'mwe-successfulupload' ),
 691+ gM( 'mwe-upload_done', url),
 692+ buttons );
 693+ mw.log( 'apiRes.upload.imageinfo::' + url );
 694+ return true;
 695+ }
 696+ },
 697+
 698+ /**
 699+ * Get the default title of the progress window
 700+ */
 701+ getProgressTitle: function() {
 702+ return gM( 'mwe-upload-in-progress' );
 703+ },
 704+
 705+ /**
 706+ * Get the DOMNode of the form element we are rewriting.
 707+ * Returns false if it can't be found.
 708+ */
 709+ getForm: function() {
 710+
 711+ if ( this.form_selector && $j( this.form_selector ).length != 0 ) {
 712+ return $j( this.form_selector ).get( 0 );
 713+ } else {
 714+ mw.log( "mvBaseUploadHandler.getForm(): no form_selector" );
 715+ return false;
 716+ }
 717+ },
 718+
 719+ /**
 720+ * Update the progress bar to a given completion fraction (between 0 and 1)
 721+ * XXX This progress bar is used for encoding AND for upload... may need to fix that
 722+ */
 723+ updateProgress: function( fraction ) {
 724+ var _this = this;
 725+
 726+ $j( '#up-progressbar' ).progressbar( 'value', parseInt( fraction * 100 ) );
 727+ $j( '#up-pstatus' ).html( parseInt( fraction * 100 ) + '% - ' );
 728+
 729+ if (_this.uploadBeginTime) {
 730+ var elapsedMilliseconds = ( new Date() ).getTime() - _this.uploadBeginTime;
 731+ if (fraction > 0.0 && elapsedMilliseconds > 0) { // or some other minimums for good data
 732+ var fractionPerMillisecond = fraction / elapsedMilliseconds;
 733+ var remainingSeconds = parseInt( ( ( 1.0 - fraction ) / fractionPerMillisecond ) / 1000 );
 734+ $j( '#up-etr' ).html( gM( 'mwe-uploaded-time-remaining', mw.seconds2npt(remainingSeconds) ) );
 735+ }
 736+ }
 737+
 738+ }
 739+
 740+};
 741+
 742+// jQuery plugins
 743+
 744+( function( $ ) {
 745+ /**
 746+ * Check the upload destination filename for conflicts and show a conflict
 747+ * error message if there is one
 748+ */
 749+ $.fn.doDestCheck = function( opt ) {
 750+ var _this = this;
 751+ mw.log( 'doDestCheck::' + _this.selector );
 752+
 753+ // Set up option defaults
 754+ if ( !opt.warn_target )
 755+ opt.warn_target = '#wpDestFile-warning';
 756+
 757+ // Add the wpDestFile-warning row
 758+ if ( $j( '#wpDestFile-warning' ).length == 0 ) {
 759+ $j( '#mw-htmlform-options tr:last' )
 760+ .after(
 761+ $j('<tr />' )
 762+ .append( '<td />' )
 763+ .append( '<td />' )
 764+ .attr('id', 'wpDestFile-warning')
 765+ );
 766+ }
 767+ mw.log( 'past dest');
 768+ // Remove any existing warning
 769+ $j( opt.warn_target ).empty();
 770+ mw.log( 'past remove warn:: ' + _this.selector);
 771+ // Show the AJAX spinner
 772+ $j( _this.selector ).after(
 773+ $j('<img />')
 774+ .attr({
 775+ 'id' : "mw-spinner-wpDestFile",
 776+ 'src' : stylepath + '/common/images/spinner.gif'
 777+ })
 778+ );
 779+ mw.log("added spiner");
 780+ var request = {
 781+ 'titles': 'File:' + $j( _this.selector ).val(),
 782+ 'prop': 'imageinfo',
 783+ 'iiprop': 'url|mime|size',
 784+ 'iiurlwidth': 150
 785+ };
 786+
 787+ // Do the destination check ( on the local wiki )
 788+ mw.getJSON( request, function( data ) {
 789+ // Remove spinner
 790+ $j( '#mw-spinner-wpDestFile' ).remove();
 791+
 792+ if ( !data || !data.query || !data.query.pages ) {
 793+ // Ignore a null result
 794+ return;
 795+ }
 796+
 797+ if ( data.query.pages[-1] ) {
 798+ // No conflict found
 799+ return;
 800+ }
 801+ for ( var page_id in data.query.pages ) {
 802+ if ( !data.query.pages[ page_id ].imageinfo ) {
 803+ continue;
 804+ }
 805+
 806+ // Conflict found, show warning
 807+ if ( data.query.normalized ) {
 808+ var ntitle = data.query.normalized[0].to;
 809+ } else {
 810+ var ntitle = data.query.pages[ page_id ].title
 811+ }
 812+ var img = data.query.pages[ page_id ].imageinfo[0];
 813+ $j( '#wpDestFile-warning' ).html(
 814+ gM( 'mwe-fileexists', ntitle ) +
 815+ '<div class="thumb tright">' +
 816+ '<div ' +
 817+ 'style="width: ' + ( parseInt( img.thumbwidth ) + 2 ) + 'px;" ' +
 818+ 'class="thumbinner">' +
 819+ '<a ' +
 820+ 'title="' + ntitle + '" ' +
 821+ 'class="image" ' +
 822+ 'href="' + img.descriptionurl + '">' +
 823+ '<img ' +
 824+ 'width="' + img.thumbwidth + '" ' +
 825+ 'height="' + img.thumbheight + '" ' +
 826+ 'border="0" ' +
 827+ 'class="thumbimage" ' +
 828+ 'src="' + img.thumburl + '" ' +
 829+ 'alt="' + ntitle + '"/>' +
 830+ '</a>' +
 831+ '<div class="thumbcaption">' +
 832+ '<div class="magnify">' +
 833+ '<a title="' + gM('thumbnail-more') + '" class="internal" ' +
 834+ 'href="' + img.descriptionurl +'">' +
 835+ '<img width="15" height="11" alt="" ' +
 836+ 'src="' + stylepath + "/common/images/magnify-clip.png\" />" +
 837+ '</a>' +
 838+ '</div>' +
 839+ gM( 'mwe-fileexists-thumb' ) +
 840+ '</div>' +
 841+ '</div>' +
 842+ '</div>'
 843+ );
 844+ }
 845+ }
 846+ );
 847+ }
 848+})( jQuery );
Property changes on: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.BaseUploadHandler.js
___________________________________________________________________
Name: svn:mergeinfo
1849 + /branches/REL1_15/phase3/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js:51646
/branches/sqlite/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js:58211-58321
Name: svn:eol-style
2850 + native
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.InterfaceDispatch.js
@@ -0,0 +1,402 @@
 2+/**
 3+* This Interface dispatcher handles interface updates for upload dialogs
 4+*
 5+* Initial dispatch handlers include:
 6+*
 7+* Inline dispatch
 8+* Dispatches updates to an inline html target
 9+*
 10+* Dialog dispatch
 11+* There is only one upload and it results in dialogs taking up the full screen
 12+*
 13+* Iframe hash dispatch
 14+* Dispatches updates to an iframe target for upload proxy
 15+*
 16+* Simple Methods setLoading, setInterfacePrompt, setup, setProgress, close
 17+*/
 18+
 19+/**
 20+ * Base UploadInterfaceDispatch object (extened by
 21+ */
 22+mw.InterfaceDispatch = {
 23+ factory : function( interfaceType ){
 24+ switch( interfaceType ){
 25+ case 'dialog':
 26+ default:
 27+ return new mw.DialogDispatch( );
 28+ break;
 29+ }
 30+ }
 31+};
 32+
 33+/**
 34+ * Dialog Dispatch
 35+ */
 36+mw.DialogDispatch = function( ) {
 37+ return this;
 38+}
 39+mw.DialogDispatch.prototype = {
 40+
 41+ setup: function( options ){
 42+ var _this = this;
 43+ // Remove the old instance if present
 44+ if( $j( '#upProgressDialog' ).length != 0 ) {
 45+ $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
 46+ }
 47+ // Add a new one
 48+ $j( 'body' ).append(
 49+ $j( '<div />')
 50+ .attr( 'id', "upProgressDialog" )
 51+ );
 52+ //if( typeof options == 'undefined' ){
 53+ // options.title = 'temp title';
 54+ //}
 55+ $j( '#upProgressDialog' ).dialog( {
 56+ title : 'temp',
 57+ bgiframe: true,
 58+ modal: true,
 59+ draggable: true,
 60+ width: 400,
 61+ heigh: 200,
 62+ beforeclose: function( event, ui ) {
 63+ // If the upload is not complete, ask the user if they want to cancel
 64+ if ( event.button == 0 && _this.action_done === false ) {
 65+ _this.onCancel( this );
 66+ return false;
 67+ } else {
 68+ // Complete already, allow close
 69+ return true;
 70+ }
 71+ },
 72+ buttons: _this.getCancelButton()
 73+ } );
 74+ mw.log( 'upProgressDialog::dialog done' );
 75+
 76+ var $progressContainer = $j('<div />')
 77+ .attr('id', 'up-pbar-container')
 78+ .css({
 79+ 'height' : '15px'
 80+ });
 81+ // add the progress bar
 82+ $progressContainer.append(
 83+ $j('<div />')
 84+ .attr('id', 'up-progressbar')
 85+ .css({
 86+ 'height' : '15px'
 87+ })
 88+ );
 89+ // Add the status container
 90+ $progressContainer.append( $j('<span />' )
 91+ .attr( 'id', 'up-status-container')
 92+ .css( 'float', 'left' )
 93+ .append(
 94+ $j( '<span />' )
 95+ .attr( 'id' , 'up-pstatus')
 96+ .text( '0% -' ),
 97+
 98+ $j( '<span />' )
 99+ .attr( 'id', 'up-status-state' )
 100+ .text( gM( 'mwe-uploaded-status' ) )
 101+ )
 102+ );
 103+ // Add the estimated time remaining
 104+ $progressContainer.append(
 105+ $j('<span />')
 106+ .attr( 'id', 'up-etr' )
 107+ .css( 'float', 'right' )
 108+ .text( gM( 'mwe-uploaded-time-remaining', '' ) )
 109+ )
 110+ // Add the status container to dialog div
 111+ $j( '#upProgressDialog' ).empty().append( $progressContainer );
 112+
 113+ // Open the empty progress window
 114+ $j( '#upProgressDialog' ).dialog( 'open' );
 115+
 116+ // Create progress bar
 117+ $j( '#up-progressbar' ).progressbar({
 118+ value: 0
 119+ });
 120+ },
 121+
 122+ /**
 123+ * UI cancel button handler.
 124+ * Show a dialog box asking the user whether they want to cancel an upload.
 125+ * @param Element dialogElement Dialog element to be canceled
 126+ */
 127+ onCancel: function( dialogElement ) {
 128+ //confirm:
 129+ if ( confirm( gM( 'mwe-cancel-confim' ) ) ) {
 130+ // NOTE: (cancel the encode / upload)
 131+ $j( dialogElement ).dialog( 'close' );
 132+ }
 133+ },
 134+ /**
 135+ * Set the dialog to loading
 136+ * @param optional loadingText text to set dialog to.
 137+ */
 138+ setLoading: function( loadingText ){
 139+ this.action_done = false;
 140+ //Update the progress dialog (no bar without XHR request)
 141+ $j( '#upProgressDialog' ).loadingSpinner();
 142+ },
 143+
 144+ /**
 145+ * Set the interface with a "title", "msg text" and buttons prompts
 146+ * list of buttons below it.
 147+ *
 148+ * @param title_txt Plain text
 149+ * @param msg HTML
 150+ * @param buttons See http://docs.jquery.com/UI/Dialog#option-buttons
 151+ */
 152+ setInterfacePrompt: function( title_txt, msg, buttons ) {
 153+ var _this = this;
 154+
 155+ if ( !title_txt )
 156+ title_txt = _this.getProgressTitle();
 157+
 158+ if ( !msg )
 159+ msg = mw.loading_spinner( 'left:40%;top:40px;' );
 160+
 161+ if ( !buttons ) {
 162+ // If no buttons are specified, add a close button
 163+ buttons = {};
 164+ buttons[ gM( 'mwe-ok' ) ] = function() {
 165+ $j( this ).dialog( 'close' );
 166+ };
 167+ }
 168+ $j( '#upProgressDialog' ).dialog( 'option', 'title', title_txt );
 169+ $j( '#upProgressDialog' ).html( msg );
 170+ $j( '#upProgressDialog' ).dialog( 'option', 'buttons', buttons );
 171+ },
 172+
 173+ /**
 174+ * Set the dialog to "done"
 175+ */
 176+ setDone: function(){
 177+ this.action_done = true;
 178+ },
 179+
 180+ /**
 181+ * Given the result of an action=upload API request, display the error message
 182+ * to the user.
 183+ *
 184+ * @param
 185+ */
 186+ showApiError: function( apiRes ) {
 187+ var _this = this;
 188+ if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
 189+ // Generate the error button
 190+
 191+ var buttons = {};
 192+ buttons[ gM( 'mwe-return-to-form' ) ] = function() {
 193+ _this.form_post_override = false;
 194+ $j( this ).dialog( 'close' );
 195+ };
 196+
 197+ // Check a few places for the error code
 198+ var error_code = 0;
 199+ var errorReplaceArg = '';
 200+ if ( apiRes.error && apiRes.error.code ) {
 201+ error_code = apiRes.error.code;
 202+ } else if ( apiRes.upload.code ) {
 203+ if ( typeof apiRes.upload.code == 'object' ) {
 204+ if ( apiRes.upload.code[0] ) {
 205+ error_code = apiRes.upload.code[0];
 206+ }
 207+ if ( apiRes.upload.code['status'] ) {
 208+ error_code = apiRes.upload.code['status'];
 209+ if ( apiRes.upload.code['filtered'] )
 210+ errorReplaceArg = apiRes.upload.code['filtered'];
 211+ }
 212+ } else {
 213+ apiRes.upload.code;
 214+ }
 215+ }
 216+
 217+ var error_msg = '';
 218+ if ( typeof apiRes.error == 'string' )
 219+ error_msg = apiRes.error;
 220+
 221+ // There are many possible error messages here, so we don't load all
 222+ // message text in advance, instead we use mw.getRemoteMsg() for some.
 223+ //
 224+ // This code is similar to the error handling code formerly in
 225+ // SpecialUpload::processUpload()
 226+ var error_msg_key = {
 227+ '2' : 'largefileserver',
 228+ '3' : 'emptyfile',
 229+ '4' : 'minlength1',
 230+ '5' : 'illegalfilename'
 231+ };
 232+
 233+ // NOTE:: handle these error types
 234+ var error_onlykey = {
 235+ '1': 'BEFORE_PROCESSING',
 236+ '6': 'PROTECTED_PAGE',
 237+ '7': 'OVERWRITE_EXISTING_FILE',
 238+ '8': 'FILETYPE_MISSING',
 239+ '9': 'FILETYPE_BADTYPE',
 240+ '10': 'VERIFICATION_ERROR',
 241+ '11': 'UPLOAD_VERIFICATION_ERROR',
 242+ '12': 'UPLOAD_WARNING',
 243+ '13': 'INTERNAL_ERROR',
 244+ '14': 'MIN_LENGTH_PARTNAME'
 245+ }
 246+
 247+ if ( !error_code || error_code == 'unknown-error' ) {
 248+ if ( typeof JSON != 'undefined' ) {
 249+ mw.log( 'Error: apiRes: ' + JSON.stringify( apiRes ) );
 250+ }
 251+ if ( apiRes.upload.error == 'internal-error' ) {
 252+ // Do a remote message load
 253+ errorKey = apiRes.upload.details[0];
 254+ mw.getRemoteMsg( errorKey, function() {
 255+ _this.setInterfacePrompt( gM( 'mwe-uploaderror' ), gM( errorKey ), buttons );
 256+
 257+ });
 258+ return false;
 259+ }
 260+
 261+ _this.setInterfacePrompt(
 262+ gM('mwe-uploaderror'),
 263+ gM('mwe-unknown-error') + '<br>' + error_msg,
 264+ buttons );
 265+ return false;
 266+ }
 267+
 268+ if ( apiRes.error && apiRes.error.info ) {
 269+ _this.setInterfacePrompt( gM( 'mwe-uploaderror' ), apiRes.error.info, buttons );
 270+ return false;
 271+ }
 272+
 273+ if ( typeof error_code == 'number'
 274+ && typeof error_msg_key[error_code] == 'undefined' )
 275+ {
 276+ if ( apiRes.upload.code.finalExt ) {
 277+ _this.setInterfacePrompt(
 278+ gM( 'mwe-uploaderror' ),
 279+ gM( 'mwe-wgfogg_warning_bad_extension', apiRes.upload.code.finalExt ),
 280+ buttons );
 281+ } else {
 282+ _this.setInterfacePrompt(
 283+ gM( 'mwe-uploaderror' ),
 284+ gM( 'mwe-unknown-error' ) + ' : ' + error_code,
 285+ buttons );
 286+ }
 287+ return false;
 288+ }
 289+
 290+ mw.log( 'get key: ' + error_msg_key[ error_code ] )
 291+ mw.getRemoteMsg( error_msg_key[ error_code ], function() {
 292+ _this.setInterfacePrompt(
 293+ gM( 'mwe-uploaderror' ),
 294+ gM( error_msg_key[ error_code ], errorReplaceArg ),
 295+ buttons );
 296+ });
 297+ mw.log( "api.error" );
 298+ return false;
 299+ }
 300+
 301+ // Check upload.error
 302+ if ( apiRes.upload && apiRes.upload.error ) {
 303+ mw.log( ' apiRes.upload.error: ' + apiRes.upload.error );
 304+ _this.setInterfacePrompt(
 305+ gM( 'mwe-uploaderror' ),
 306+ gM( 'mwe-unknown-error' ) + '<br>',
 307+ buttons );
 308+ return false;
 309+ }
 310+
 311+ // Check for warnings:
 312+ if ( apiRes.upload && apiRes.upload.warnings ) {
 313+ var wmsg = '<ul>';
 314+ for ( var wtype in apiRes.upload.warnings ) {
 315+ var winfo = apiRes.upload.warnings[wtype]
 316+ wmsg += '<li>';
 317+ switch ( wtype ) {
 318+ case 'duplicate':
 319+ case 'exists':
 320+ if ( winfo[1] && winfo[1].title && winfo[1].title.mTextform ) {
 321+ wmsg += gM( 'mwe-file-exists-duplicate' ) + ' ' +
 322+ '<b>' + winfo[1].title.mTextform + '</b>';
 323+ } else {
 324+ //misc error (weird that winfo[1] not present
 325+ wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
 326+ }
 327+ break;
 328+ case 'file-thumbnail-no':
 329+ wmsg += gM( 'mwe-file-thumbnail-no', winfo );
 330+ break;
 331+ default:
 332+ wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
 333+ break;
 334+ }
 335+ wmsg += '</li>';
 336+ }
 337+ wmsg += '</ul>';
 338+ if ( apiRes.upload.sessionkey )
 339+ _this.warnings_sessionkey = apiRes.upload.sessionkey;
 340+
 341+ // Create the "ignore warning" button
 342+ var buttons = {};
 343+ buttons[ gM( 'mwe-ignorewarning' ) ] = function() {
 344+ //check if we have a stashed key:
 345+ if ( _this.warnings_sessionkey ) {
 346+ //set to "loading"
 347+ $j( '#upProgressDialog' ).html( mw.loading_spinner() );
 348+ //setup request:
 349+ var request = {
 350+ 'action': 'upload',
 351+ 'sessionkey': _this.warnings_sessionkey,
 352+ 'ignorewarnings': 1,
 353+ 'filename': $j( '#wpDestFile' ).val(),
 354+ 'token' : _this.editToken,
 355+ 'comment' : $j( '#wpUploadDescription' ).val()
 356+ };
 357+ //run the upload from stash request
 358+ mw.getJSON(_this.api_url, request, function( data ) {
 359+ _this.processApiResult( data );
 360+ } );
 361+ } else {
 362+ mw.log( 'No session key re-sending upload' )
 363+ //do a stashed upload
 364+ $j( '#wpIgnoreWarning' ).attr( 'checked', true );
 365+ $j( _this.editForm ).submit();
 366+ }
 367+ };
 368+ // Create the "return to form" button
 369+ buttons[ gM( 'mwe-return-to-form' ) ] = function() {
 370+ $j( this ).dialog( 'close' );
 371+ _this.form_post_override = false;
 372+ }
 373+ // Show warning
 374+ _this.setInterfacePrompt(
 375+ gM( 'mwe-uploadwarning' ),
 376+ $j('<div />')
 377+ .append(
 378+ $j( '<h3 />' )
 379+ .text( gM( 'mwe-uploadwarning' ) ),
 380+
 381+ $j('<span />')
 382+ .html( wmsg )
 383+ ),
 384+ buttons );
 385+ return false;
 386+ }
 387+ // No error!
 388+ return true;
 389+ },
 390+ /**
 391+ * Get a standard cancel button in the jQuery.ui dialog format
 392+ */
 393+ getCancelButton: function() {
 394+ var _this = this;
 395+ mw.log( 'f: getCancelButton()' );
 396+ var cancelBtn = [];
 397+ cancelBtn[ gM( 'mwe-cancel' ) ] = function() {
 398+ $j( dlElm ).dialog( 'close' );
 399+ };
 400+ return cancelBtn;
 401+ }
 402+}
 403+
Property changes on: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.InterfaceDispatch.js
___________________________________________________________________
Name: svn:executable
1404 + *
Index: branches/js2-work/phase3/js/mwEmbed/mwEmbed.js
@@ -1733,7 +1733,7 @@
17341734
17351735 /**
17361736 * Get a loading spinner html
1737 - * NOTE: this is depreciated use jQuery binding "loadingSpinner" instead
 1737+ * NOTE: this is depreciated use jQuery binding $j(target).loadingSpinner()" instead
17381738 *
17391739 * @param {String} [Optional] style Style string to apply to the spinner
17401740 */

Status & tagging log