r62315 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r62314‎ | r62315 | r62316 >
Date:19:44, 11 February 2010
Author:dale
Status:deferred
Tags:
Comment:
* tested refactor separation of uploadInterface and uploadHandler
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 (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 (deleted) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadHandler.js (added) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadInterface.js (added) (history)

Diff [purge]

Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.BaseUploadHandler.js
@@ -1,847 +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 - // 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 );
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.InterfaceDispatch.js
@@ -1,402 +0,0 @@
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 -
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadHandler.js
@@ -0,0 +1,1040 @@
 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-in-progress" : "Upload in progress (do not close this window)",
 13+ "mwe-upload-transcoded-status" : "Transcoded",
 14+ "mwe-uploaded-time-remaining" : "Time remaining: $1",
 15+ "mwe-uploaded-status" : "Uploaded",
 16+ "mwe-upload-stats-fileprogress" : "$1 of $2",
 17+ "mwe-upload_completed" : "Your upload is complete",
 18+ "mwe-upload_done" : "<a href=\"$1\">Your upload <i>should be<\/i> accessible<\/a>.",
 19+ "mwe-upload-unknown-size" : "Unknown size",
 20+ "mwe-cancel-confim" : "Are you sure you want to cancel?",
 21+ "mwe-successfulupload" : "Upload successful",
 22+ "mwe-uploaderror" : "Upload error",
 23+ "mwe-uploadwarning" : "Upload warning",
 24+ "mwe-unknown-error" : "Unknown error:",
 25+ "mwe-return-to-form" : "Return to form",
 26+ "mwe-file-exists-duplicate" : "This file is a duplicate of the following file:",
 27+ "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.",
 28+ "mwe-fileexists-thumb" : "<center><b>Existing file<\/b><\/center>",
 29+ "mwe-ignorewarning" : "Ignore warning and save file anyway",
 30+ "mwe-file-thumbnail-no" : "The filename begins with <b><tt>$1<\/tt><\/b>",
 31+ "mwe-go-to-resource" : "Go to resource page",
 32+ "mwe-upload-misc-error" : "Unknown upload error",
 33+ "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>)."
 34+});
 35+
 36+var default_bui_options = {
 37+ // Target api to upload to
 38+ 'api_url' : null,
 39+
 40+ // The selected form
 41+ 'form' : null,
 42+
 43+ // Callback for once the upload is done
 44+ 'done_upload_cb' : null,
 45+
 46+ // A selector for the form target
 47+ 'form_selector' : null,
 48+
 49+ // Default upload mode is 'api'
 50+ 'upload_mode' : 'api',
 51+
 52+ // Callback for modifing form data on submit
 53+ 'onsubmit_cb' : null,
 54+
 55+ // The interface type sent to mw.interface factory
 56+ // can be 'dialog', 'iframe', 'inline'
 57+ 'interface_type' : 'dialog'
 58+
 59+}
 60+mw.UploadHandler = function( options ) {
 61+ return this.init( options );
 62+}
 63+
 64+mw.UploadHandler.prototype = {
 65+
 66+ // The form data to be submitted
 67+ formData: {},
 68+
 69+ // Upload warning session key, for continued uploads
 70+ warnings_sessionkey: null,
 71+
 72+ // If chunks uploading is supported
 73+ chunks_supported: true,
 74+
 75+ // If the existing form should be used to post to the api
 76+ // Since file selection can't be "moved" we have to use the existing
 77+ // form and just submit it to a difrent target
 78+ form_post_override: false,
 79+
 80+ // http copy by url mode flag
 81+ http_copy_upload : null,
 82+
 83+ // If the upload action is done
 84+ action_done: false,
 85+
 86+ // Edit token for upload
 87+ editToken: false,
 88+
 89+ // The DOM node for the upload form
 90+ form: false,
 91+
 92+ // The following are really state of the upload, not the interface.
 93+ // we are currently only managing one, so this is okay... for now.
 94+ uploadBeginTime: null,
 95+
 96+
 97+ /**
 98+ * Object initialization
 99+ * @param {Object} options BaseUpload options see default_bui_options
 100+ */
 101+ init: function( options ) {
 102+ if ( !options )
 103+ options = {};
 104+ $j.extend( this, default_bui_options, options );
 105+
 106+ // Setup the interfaceDispatch handler
 107+ this.interface = mw.UploadInterface.factory( this.interface_type );
 108+
 109+ mw.log( "init mvBaseUploadHandler:: " + this.api_url );
 110+ },
 111+
 112+ /**
 113+ * Set up the upload form, register onsubmit handler.
 114+ * May remap it to use the API field names.
 115+ */
 116+ setupForm: function() {
 117+ mw.log( "Base::setupForm::" );
 118+ var _this = this;
 119+
 120+ // Set up the local pointer to the edit form:
 121+ this.form = this.getForm();
 122+
 123+ if ( !this.form ) {
 124+ mw.log( "Upload form not found!" );
 125+ return;
 126+ }
 127+
 128+ // Set up the orig_onsubmit if not set:
 129+ if ( typeof( this.orig_onsubmit ) == 'undefined' && this.form.onsubmit ) {
 130+ this.orig_onsubmit = this.form.onsubmit;
 131+ }
 132+
 133+ // Set up the submit action:
 134+ $j( this.form ).submit( function() {
 135+ mw.log( "FORM SUBMIT::" );
 136+ var data = $j( this ).serializeArray();
 137+ for ( var i = 0; i < data.length; i++ ) {
 138+ mw.log( $j( data[i] ).attr('name') + ' : ' + $j(data[i]).val() );
 139+ }
 140+
 141+ return _this.onSubmit();
 142+ } );
 143+ },
 144+
 145+ /**
 146+ * onSubmit handler for the upload form
 147+ */
 148+ onSubmit: function() {
 149+ var _this = this;
 150+ mw.log( 'Base::onSubmit:' );
 151+ // Run the original onsubmit (if not run yet set flag to avoid excessive chaining)
 152+ if ( typeof( this.orig_onsubmit ) == 'function' ) {
 153+ if ( ! this.orig_onsubmit() ) {
 154+ //error in orig submit return false;
 155+ return false;
 156+ }
 157+ }
 158+ // Call the onsubmit_cb option if set:
 159+ if( this.onsubmit_cb && typeof this.onsubmit_cb == 'function' ){
 160+ this.onsubmit_cb();
 161+ }
 162+
 163+ // Remap the upload form to the "api" form:
 164+ this.remapFormToApi();
 165+
 166+ // Check for post action override
 167+ if ( this.form_post_override ) {
 168+ mw.log( 'form_post_override is true, do ordinary form submit' );
 169+ return true;
 170+ }
 171+
 172+
 173+ // Put into a try catch so we are sure to return false:
 174+ try {
 175+ // Startup interface dispatch dialog
 176+ this.interface.setup( {'title': gM('mwe-upload-in-progress') } );
 177+ //this.displayProgressOverlay
 178+
 179+
 180+ // For some unknown reason we have to drop down the #p-search z-index:
 181+ $j( '#p-search' ).css( 'z-index', 1 );
 182+
 183+ var _this = this;
 184+ _this.detectUploadMode( function( mode ) {
 185+ _this.upload_mode = mode;
 186+ _this.doUpload();
 187+ } );
 188+ } catch( e ) {
 189+ mw.log( '::error in interfaceDispatch or doUpload ' + e );
 190+ }
 191+
 192+ // Don't submit the form we will do the post in ajax
 193+ return false;
 194+ },
 195+
 196+ /**
 197+ * Determine the correct upload mode.
 198+ *
 199+ * If this.upload_mode is autodetect, this runs an API call to find out if MW
 200+ * supports uploading. It then sets the upload mode when this call returns.
 201+ *
 202+ * When done detecting, or if detecting is unnecessary, it calls the callback
 203+ * with the upload mode as the first parameter.
 204+ *
 205+ * @param {Function} callback Function called once upload mode is detected
 206+ */
 207+ detectUploadMode: function( callback ) {
 208+ var _this = this;
 209+ mw.log( 'detectUploadMode::' + _this.upload_mode );
 210+ //debugger;
 211+ // Check the upload mode
 212+ if ( _this.upload_mode == 'detect_in_progress' ) {
 213+ // Don't send another request, wait for the pending one.
 214+ } else if ( !_this.isCopyUpload() ) {
 215+ callback( 'post' );
 216+ } else if ( _this.upload_mode == 'autodetect' ) {
 217+ mw.log( 'detectUploadMode::' + _this.upload_mode + ' api:' + _this.api_url );
 218+ if( !_this.api_url ) {
 219+ mw.log( 'Error: can\'t autodetect mode without api url' );
 220+ return;
 221+ }
 222+
 223+ // Don't send multiple requests
 224+ _this.upload_mode = 'detect_in_progress';
 225+
 226+ // FIXME: move this to configuration and avoid this API request
 227+ mw.getJSON( _this.api_url, { 'action' : 'paraminfo', 'modules' : 'upload' }, function( data ) {
 228+ if ( typeof data.paraminfo == 'undefined'
 229+ || typeof data.paraminfo.modules == 'undefined' )
 230+ {
 231+ return mw.log( 'Error: bad api results' );
 232+ }
 233+ if ( typeof data.paraminfo.modules[0].classname == 'undefined' ) {
 234+ mw.log( 'Autodetect Upload Mode: \'post\' ' );
 235+ _this.upload_mode = 'post';
 236+ callback( 'post' );
 237+ } else {
 238+ mw.log( 'Autodetect Upload Mode: api ' );
 239+ _this.upload_mode = 'api';
 240+ // Check to see if chunks are supported
 241+ for ( var i in data.paraminfo.modules[0].parameters ) {
 242+ var pname = data.paraminfo.modules[0].parameters[i].name;
 243+ if( pname == 'enablechunks' ) {
 244+ mw.log( 'this.chunks_supported = true' );
 245+ _this.chunks_supported = true;
 246+ break;
 247+ }
 248+ }
 249+ callback( 'api' );
 250+ }
 251+ }
 252+ );
 253+ } else if ( _this.upload_mode == 'api' ) {
 254+ callback( 'api' );
 255+ } else if ( _this.upload_mode == 'post' ) {
 256+ callback( 'post' );
 257+ } else {
 258+ mw.log( 'Error: unrecongized upload mode: ' + _this.upload_mode );
 259+ }
 260+ },
 261+
 262+ /**
 263+ * Do an upload, with the mode given by this.upload_mode
 264+ */
 265+ doUpload: function() {
 266+ // Note "api" should be called "http_copy_upload" and /post/ should be "form_upload"
 267+ this.uploadBeginTime = (new Date()).getTime();
 268+ if ( this.upload_mode == 'api' ) {
 269+ this.doApiCopyUpload();
 270+ } else if ( this.upload_mode == 'post' ) {
 271+ this.doPostUpload();
 272+ } else {
 273+ mw.log( 'Error: unrecongized upload mode: ' + this.upload_mode );
 274+ }
 275+ },
 276+
 277+ /**
 278+ * Change the upload form so that when submitted, it sends a request to
 279+ * the MW API.
 280+ *
 281+ * This is rather ugly, but solutions are constrained by the fact that
 282+ * file inputs can't be moved around or recreated after the user has
 283+ * selected a file in them, which they may well do before DOM ready.
 284+ *
 285+ * It is also constrained by upload form hacks on commons.
 286+ */
 287+ remapFormToApi: function() {
 288+ var _this = this;
 289+ //
 290+ mw.log("remapFormToApi:: " + this.api_url + ' form: ' + this.form);
 291+
 292+ if ( !this.api_url ){
 293+ mw.log( 'Error: no api url target' );
 294+ return false;
 295+ }
 296+ var $form = $j( this.form_selector );
 297+
 298+ // Set the form action
 299+ try{
 300+ $form.attr('action', _this.api_url);
 301+ }catch(e){
 302+ mw.log("IE for some reason error's out when you change the action")
 303+ }
 304+
 305+ // Add API action
 306+ if ( $form.find( "[name='action']" ).length == 0 ){
 307+ $form.append(
 308+ $j('<input />')
 309+ .attr({
 310+ 'type': "hidden",
 311+ 'name' : "action",
 312+ 'value' : "upload"
 313+ })
 314+ )
 315+ }
 316+
 317+ // Add JSON response format
 318+ if ( $form.find( "[name='format']" ).length == 0 ){
 319+ $form.append(
 320+ $j( '<input />' )
 321+ .attr({
 322+ 'type' : "hidden",
 323+ 'name' : "format",
 324+ 'value' : "jsonfm"
 325+ })
 326+ )
 327+ }
 328+
 329+ // Map a new hidden form
 330+ $form.find( "[name='wpUploadFile']" ).attr( 'name', 'file' );
 331+ $form.find( "[name='wpDestFile']" ).attr( 'name', 'filename' );
 332+ $form.find( "[name='wpUploadDescription']" ).attr( 'name', 'comment' );
 333+ $form.find( "[name='wpEditToken']" ).attr( 'name', 'token' );
 334+ $form.find( "[name='wpIgnoreWarning']" ).attr( 'name', 'ignorewarnings' );
 335+ $form.find( "[name='wpWatchthis']" ).attr( 'name', 'watch' );
 336+
 337+ //mw.log( 'comment: ' + $form.find( "[name='comment']" ).val() );
 338+ },
 339+
 340+ /**
 341+ * Given the result of an action=upload API request, display the error message
 342+ * to the user.
 343+ *
 344+ * @param {Object} apiRes The result object
 345+ */
 346+ showApiError: function( apiRes ) {
 347+ var _this = this;
 348+ if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
 349+ // Generate the error button
 350+
 351+ var buttons = {};
 352+ buttons[ gM( 'mwe-return-to-form' ) ] = function() {
 353+ _this.form_post_override = false;
 354+ $j( this ).dialog( 'close' );
 355+ };
 356+
 357+ // Check a few places for the error code
 358+ var error_code = 0;
 359+ var errorReplaceArg = '';
 360+ if ( apiRes.error && apiRes.error.code ) {
 361+ error_code = apiRes.error.code;
 362+ } else if ( apiRes.upload.code ) {
 363+ if ( typeof apiRes.upload.code == 'object' ) {
 364+ if ( apiRes.upload.code[0] ) {
 365+ error_code = apiRes.upload.code[0];
 366+ }
 367+ if ( apiRes.upload.code['status'] ) {
 368+ error_code = apiRes.upload.code['status'];
 369+ if ( apiRes.upload.code['filtered'] )
 370+ errorReplaceArg = apiRes.upload.code['filtered'];
 371+ }
 372+ } else {
 373+ apiRes.upload.code;
 374+ }
 375+ }
 376+
 377+ var error_msg = '';
 378+ if ( typeof apiRes.error == 'string' )
 379+ error_msg = apiRes.error;
 380+
 381+ // There are many possible error messages here, so we don't load all
 382+ // message text in advance, instead we use mw.getRemoteMsg() for some.
 383+ //
 384+ // This code is similar to the error handling code formerly in
 385+ // SpecialUpload::processUpload()
 386+ var error_msg_key = {
 387+ '2' : 'largefileserver',
 388+ '3' : 'emptyfile',
 389+ '4' : 'minlength1',
 390+ '5' : 'illegalfilename'
 391+ };
 392+
 393+ // NOTE:: handle these error types
 394+ var error_onlykey = {
 395+ '1': 'BEFORE_PROCESSING',
 396+ '6': 'PROTECTED_PAGE',
 397+ '7': 'OVERWRITE_EXISTING_FILE',
 398+ '8': 'FILETYPE_MISSING',
 399+ '9': 'FILETYPE_BADTYPE',
 400+ '10': 'VERIFICATION_ERROR',
 401+ '11': 'UPLOAD_VERIFICATION_ERROR',
 402+ '12': 'UPLOAD_WARNING',
 403+ '13': 'INTERNAL_ERROR',
 404+ '14': 'MIN_LENGTH_PARTNAME'
 405+ }
 406+
 407+ if ( !error_code || error_code == 'unknown-error' ) {
 408+ if ( typeof JSON != 'undefined' ) {
 409+ mw.log( 'Error: apiRes: ' + JSON.stringify( apiRes ) );
 410+ }
 411+ if ( apiRes.upload.error == 'internal-error' ) {
 412+ // Do a remote message load
 413+ errorKey = apiRes.upload.details[0];
 414+ mw.getRemoteMsg( errorKey, function() {
 415+ _this.interface.setPrompt( gM( 'mwe-uploaderror' ), gM( errorKey ), buttons );
 416+
 417+ });
 418+ return false;
 419+ }
 420+
 421+ _this.interface.setPrompt(
 422+ gM('mwe-uploaderror'),
 423+ gM('mwe-unknown-error') + '<br>' + error_msg,
 424+ buttons );
 425+ return false;
 426+ }
 427+
 428+ if ( apiRes.error && apiRes.error.info ) {
 429+ _this.interface.setPrompt( gM( 'mwe-uploaderror' ), apiRes.error.info, buttons );
 430+ return false;
 431+ }
 432+
 433+ if ( typeof error_code == 'number'
 434+ && typeof error_msg_key[error_code] == 'undefined' )
 435+ {
 436+ if ( apiRes.upload.code.finalExt ) {
 437+ _this.interface.setPrompt(
 438+ gM( 'mwe-uploaderror' ),
 439+ gM( 'mwe-wgfogg_warning_bad_extension', apiRes.upload.code.finalExt ),
 440+ buttons );
 441+ } else {
 442+ _this.interface.setPrompt(
 443+ gM( 'mwe-uploaderror' ),
 444+ gM( 'mwe-unknown-error' ) + ' : ' + error_code,
 445+ buttons );
 446+ }
 447+ return false;
 448+ }
 449+
 450+ mw.log( 'get key: ' + error_msg_key[ error_code ] )
 451+ mw.getRemoteMsg( error_msg_key[ error_code ], function() {
 452+ _this.interface.setPrompt(
 453+ gM( 'mwe-uploaderror' ),
 454+ gM( error_msg_key[ error_code ], errorReplaceArg ),
 455+ buttons );
 456+ });
 457+ mw.log( "api.error" );
 458+ return false;
 459+ }
 460+
 461+ // Check upload.error
 462+ if ( apiRes.upload && apiRes.upload.error ) {
 463+ mw.log( ' apiRes.upload.error: ' + apiRes.upload.error );
 464+ _this.interface.setPrompt(
 465+ gM( 'mwe-uploaderror' ),
 466+ gM( 'mwe-unknown-error' ) + '<br>',
 467+ buttons );
 468+ return false;
 469+ }
 470+
 471+ // Check for warnings:
 472+ if ( apiRes.upload && apiRes.upload.warnings ) {
 473+ var wmsg = '<ul>';
 474+ for ( var wtype in apiRes.upload.warnings ) {
 475+ var winfo = apiRes.upload.warnings[wtype]
 476+ wmsg += '<li>';
 477+ switch ( wtype ) {
 478+ case 'duplicate':
 479+ case 'exists':
 480+ if ( winfo[1] && winfo[1].title && winfo[1].title.mTextform ) {
 481+ wmsg += gM( 'mwe-file-exists-duplicate' ) + ' ' +
 482+ '<b>' + winfo[1].title.mTextform + '</b>';
 483+ } else {
 484+ //misc error (weird that winfo[1] not present
 485+ wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
 486+ }
 487+ break;
 488+ case 'file-thumbnail-no':
 489+ wmsg += gM( 'mwe-file-thumbnail-no', winfo );
 490+ break;
 491+ default:
 492+ wmsg += gM( 'mwe-upload-misc-error' ) + ' ' + wtype;
 493+ break;
 494+ }
 495+ wmsg += '</li>';
 496+ }
 497+ wmsg += '</ul>';
 498+ if ( apiRes.upload.sessionkey )
 499+ _this.warnings_sessionkey = apiRes.upload.sessionkey;
 500+
 501+ // Create the "ignore warning" button
 502+ var buttons = {};
 503+ buttons[ gM( 'mwe-ignorewarning' ) ] = function() {
 504+ //check if we have a stashed key:
 505+ if ( _this.warnings_sessionkey ) {
 506+ //set to "loading"
 507+ $j( '#upProgressDialog' ).html( mw.loading_spinner() );
 508+ //setup request:
 509+ var request = {
 510+ 'action': 'upload',
 511+ 'sessionkey': _this.warnings_sessionkey,
 512+ 'ignorewarnings': 1,
 513+ 'filename': $j( '#wpDestFile' ).val(),
 514+ 'token' : _this.editToken,
 515+ 'comment' : $j( '#wpUploadDescription' ).val()
 516+ };
 517+ //run the upload from stash request
 518+ mw.getJSON(_this.api_url, request, function( data ) {
 519+ _this.processApiResult( data );
 520+ } );
 521+ } else {
 522+ mw.log( 'No session key re-sending upload' )
 523+ //do a stashed upload
 524+ $j( '#wpIgnoreWarning' ).attr( 'checked', true );
 525+ $j( _this.editForm ).submit();
 526+ }
 527+ };
 528+ // Create the "return to form" button
 529+ buttons[ gM( 'mwe-return-to-form' ) ] = function() {
 530+ $j( this ).dialog( 'close' );
 531+ _this.form_post_override = false;
 532+ }
 533+ // Show warning
 534+ _this.interface.setPrompt(
 535+ gM( 'mwe-uploadwarning' ),
 536+ $j('<div />')
 537+ .append(
 538+ $j( '<h3 />' )
 539+ .text( gM( 'mwe-uploadwarning' ) ),
 540+
 541+ $j('<span />')
 542+ .html( wmsg )
 543+ ),
 544+ buttons );
 545+ return false;
 546+ }
 547+ // No error!
 548+ return true;
 549+ },
 550+
 551+
 552+ /**
 553+ * Returns true if the current form has copy upload selected, false otherwise.
 554+ */
 555+ isCopyUpload: function() {
 556+ if ( $j( '#wpSourceTypeFile' ).length == 0
 557+ || $j( '#wpSourceTypeFile' ).get( 0 ).checked )
 558+ {
 559+ this.http_copy_upload = false;
 560+ } else if ( $j('#wpSourceTypeURL').get( 0 ).checked ) {
 561+ this.http_copy_upload = true;
 562+ }
 563+ return this.http_copy_upload;
 564+ },
 565+
 566+ /**
 567+ * Do an upload by submitting the form
 568+ */
 569+ doPostUpload: function() {
 570+ var _this = this;
 571+ var $form = $j( _this.form );
 572+ mw.log( 'mvBaseUploadHandler.doPostUpload' );
 573+ // Issue a normal post request
 574+ // Get the token from the page
 575+ _this.editToken = $j( "#wpEditToken" ).val();
 576+
 577+ // TODO check for sendAsBinary to support Firefox/HTML5 progress on upload
 578+
 579+ this.interface.setLoading();
 580+
 581+ // Add the iframe
 582+ _this.iframeId = 'f_' + ( $j( 'iframe' ).length + 1 );
 583+ //IE only works if you "create element with the name" (not jquery style
 584+ var iframe;
 585+ try {
 586+ iframe = document.createElement( '<iframe name="' + _this.iframeId + '">' );
 587+ } catch (ex) {
 588+ iframe = document.createElement('iframe');
 589+ }
 590+
 591+ $j( "body" ).append(
 592+ $j( iframe )
 593+ .attr({
 594+ 'src':'javascript:false;',
 595+ 'id':_this.iframeId,
 596+ 'name': _this.iframeId
 597+ })
 598+ .css('display', 'none')
 599+ );
 600+
 601+
 602+ // Set the form target to the iframe
 603+ $form.attr( 'target', _this.iframeId );
 604+
 605+ // Set up the completion callback
 606+ $j( '#' + _this.iframeId ).load( function() {
 607+ _this.processIframeResult( $j( this ).get( 0 ) );
 608+ });
 609+
 610+ // Do post override
 611+ _this.form_post_override = true;
 612+
 613+ $form.submit();
 614+ },
 615+
 616+ /**
 617+ * Do an upload by submitting an API request
 618+ */
 619+ doApiCopyUpload: function() {
 620+ mw.log( 'mvBaseUploadHandler.doApiCopyUpload' );
 621+ mw.log( 'doHttpUpload (no form submit) ' );
 622+
 623+ var httpUpConf = {
 624+ 'url' : $j( '#wpUploadFileURL' ).val(),
 625+ 'filename' : $j( '#wpDestFile' ).val(),
 626+ 'comment' : this.getUploadDescription(),
 627+ 'watch' : ( $j( '#wpWatchthis' ).is( ':checked' ) ) ? 'true' : 'false',
 628+ 'ignorewarnings': ($j('#wpIgnoreWarning' ).is( ':checked' ) ) ? 'true' : 'false'
 629+ }
 630+ //check for editToken
 631+ this.editToken = $j( "#wpEditToken" ).val();
 632+ this.doHttpUpload( httpUpConf );
 633+ },
 634+
 635+ /**
 636+ * Get the upload description, append the licence if avaliable
 637+ *
 638+ * NOTE: wpUploadDescription should be a configuration option.
 639+ *
 640+ * @return {String}
 641+ * value of wpUploadDescription
 642+ */
 643+ getUploadDescription: function(){
 644+ //Special case of upload.js commons hack:
 645+ var comment_value = $j( '#wpUploadDescription' ).val();
 646+ if( comment_value == '' ){
 647+ comment_value = $j( "[name='wpUploadDescription']").val();
 648+ }
 649+ //check for licence tag:
 650+ },
 651+
 652+ /**
 653+ * Process the result of the form submission, returned to an iframe.
 654+ * This is the iframe's onload event.
 655+ */
 656+ processIframeResult: function( iframe ) {
 657+ var _this = this;
 658+ var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document;
 659+ // Fix for Opera 9.26
 660+ if ( doc.readyState && doc.readyState != 'complete' ) {
 661+ return;
 662+ }
 663+ // Fix for Opera 9.64
 664+ if ( doc.body && doc.body.innerHTML == "false" ) {
 665+ return;
 666+ }
 667+ var response;
 668+ if ( doc.XMLDocument ) {
 669+ // The response is a document property in IE
 670+ response = doc.XMLDocument;
 671+ } else if ( doc.body ) {
 672+ // Get the json string
 673+ json = $j( doc.body ).find( 'pre' ).text();
 674+ //mw.log( 'iframe:json::' + json_str + "\nbody:" + $j( doc.body ).html() );
 675+ if ( json ) {
 676+ response = window["eval"]( "(" + json + ")" );
 677+ } else {
 678+ response = {};
 679+ }
 680+ } else {
 681+ // response is a xml document
 682+ response = doc;
 683+ }
 684+ // Process the API result
 685+ _this.processApiResult( response );
 686+ },
 687+
 688+ /**
 689+ * Do a generic action=upload API request and monitor its progress
 690+ */
 691+ doHttpUpload: function( params ) {
 692+ var _this = this;
 693+ // Get a clean setup of the interface dispatch
 694+ this.interface.setup( {'title': gM('mwe-upload-in-progress') } );
 695+
 696+ //_this.displayProgressOverlay();
 697+
 698+ // Set the interface dispatch to loading ( in case we don't get an update for some time )
 699+ this.interface.setLoading();
 700+
 701+ // Set up the request
 702+ var request = {
 703+ 'action' : 'upload',
 704+ 'asyncdownload' : true // Do async download
 705+ };
 706+
 707+ // Add any parameters specified by the caller
 708+ for ( key in params ) {
 709+ if ( !request[key] ) {
 710+ request[key] = params[key];
 711+ }
 712+ }
 713+
 714+ // Add the edit token (if available)
 715+ if( !_this.editToken && _this.api_url ) {
 716+ mw.log( 'Error:doHttpUpload: missing token' );
 717+ } else {
 718+ request['token'] =_this.editToken;
 719+ }
 720+
 721+ // Reset the done with action flag
 722+ _this.action_done = false;
 723+
 724+ // Do the api request:
 725+ mw.getJSON(_this.api_url, request, function( data ) {
 726+ _this.processApiResult( data );
 727+ });
 728+ },
 729+
 730+ /**
 731+ * Start periodic checks of the upload status using XHR
 732+ */
 733+ doAjaxUploadStatus: function() {
 734+ var _this = this;
 735+
 736+ // Set up intterface dispatch to display for status updates:
 737+ this.interface.setup( {'title': gM('mwe-upload-in-progress') } );
 738+ //this.displayProgressOverlay();
 739+
 740+ this.upload_status_request = {
 741+ 'action' : 'upload',
 742+ 'httpstatus' : 'true',
 743+ 'sessionkey' : _this.upload_session_key
 744+ };
 745+ // Add token if present
 746+ if ( this.editToken )
 747+ this.upload_status_request['token'] = this.editToken;
 748+
 749+ // Trigger an initial request (subsequent ones will be done by a timer)
 750+ this.onAjaxUploadStatusTimer();
 751+ },
 752+
 753+ /**
 754+ * This is called when the timer which separates XHR requests elapses.
 755+ * It starts a new request.
 756+ */
 757+ onAjaxUploadStatusTimer: function() {
 758+ var _this = this;
 759+ //do the api request:
 760+ mw.getJSON( this.api_url, this.upload_status_request, function ( data ) {
 761+ _this.onAjaxUploadStatusResponse( data );
 762+ } );
 763+ },
 764+
 765+ /**
 766+ * Called when a response to an upload status query is available.
 767+ * Starts the timer for the next upload status check.
 768+ */
 769+ onAjaxUploadStatusResponse: function( data ) {
 770+ var _this = this;
 771+ // Check if we are done
 772+ if ( data.upload['apiUploadResult'] ) {
 773+ //update status to 100%
 774+ _this.updateProgress( 1 );
 775+ //see if we need JSON
 776+ mw.load( [
 777+ 'JSON'
 778+ ], function() {
 779+ var apiResult = {};
 780+ try {
 781+ apiResult = JSON.parse( data.upload['apiUploadResult'] ) ;
 782+ } catch ( e ) {
 783+ //could not parse api result
 784+ mw.log( 'errro: could not parse apiUploadResult' )
 785+ }
 786+ _this.processApiResult( apiResult );
 787+ });
 788+ return ;
 789+ }
 790+
 791+ // else update status:
 792+ if ( data.upload['content_length'] && data.upload['loaded'] ) {
 793+ //we have content length we can show percentage done:
 794+ var fraction = data.upload['loaded'] / data.upload['content_length'];
 795+ //update the status:
 796+ _this.updateProgress( fraction );
 797+ //special case update the file progress where we have data size:
 798+ $j( '#up-status-container' ).html(
 799+ gM( 'mwe-upload-stats-fileprogress',
 800+ [
 801+ mw.lang.formatSize( data.upload['loaded'] ),
 802+ mw.lang.formatSize( data.upload['content_length'] )
 803+ ]
 804+ )
 805+ );
 806+ } else if( data.upload['loaded'] ) {
 807+ _this.updateProgress( 1 );
 808+ mw.log( 'just have loaded (no cotent length: ' + data.upload['loaded'] );
 809+ //for lack of content-length requests:
 810+ $j( '#up-status-container' ).html(
 811+ gM( 'mwe-upload-stats-fileprogress',
 812+ [
 813+ mw.lang.formatSize( data.upload['loaded'] ),
 814+ gM( 'mwe-upload-unknown-size' )
 815+ ]
 816+ )
 817+ );
 818+ }
 819+ if ( _this.api_url == 'proxy' ) {
 820+ // Do the updates a bit less often: every 4.2 seconds
 821+ var timeout = 4200;
 822+ } else {
 823+ // We got a result: set timeout to 100ms + your server update
 824+ // interval (in our case 2s)
 825+ var timeout = 2100;
 826+ }
 827+ setTimeout(
 828+ function() {
 829+ _this.onAjaxUploadStatusTimer();
 830+ },
 831+ timeout );
 832+ },
 833+
 834+ /**
 835+ * Returns true if an action=upload API result was successful, false otherwise
 836+ */
 837+ isApiSuccess: function( apiRes ) {
 838+ if ( apiRes.error || ( apiRes.upload && apiRes.upload.result == "Failure" ) ) {
 839+ return false;
 840+ }
 841+ if ( apiRes.upload && apiRes.upload.error ) {
 842+ return false;
 843+ }
 844+ if ( apiRes.upload && apiRes.upload.warnings ) {
 845+ return false;
 846+ }
 847+ return true;
 848+ },
 849+
 850+
 851+ /**
 852+ * Process the result of an action=upload API request. Display the result
 853+ * to the user.
 854+ *
 855+ * @param {Object} apiRes Api result object
 856+ * @return {Boolean}
 857+ * false if api error
 858+ * true if success & interface has been updated
 859+ */
 860+ processApiResult: function( apiRes ) {
 861+ var _this = this;
 862+ mw.log( 'processApiResult::' );
 863+
 864+ if ( !_this.isApiSuccess( apiRes ) ) {
 865+ // Error detected, show it to the user
 866+ _this.interface.showApiError( apiRes );
 867+ return false;
 868+ }
 869+ if ( apiRes.upload && apiRes.upload.upload_session_key ) {
 870+ // Async upload, do AJAX status polling
 871+ _this.upload_session_key = apiRes.upload.upload_session_key;
 872+ _this.doAjaxUploadStatus();
 873+ mw.log( "set upload_session_key: " + _this.upload_session_key );
 874+ return;
 875+ }
 876+
 877+ if ( apiRes.upload && apiRes.upload.imageinfo && apiRes.upload.imageinfo.descriptionurl ) {
 878+ var url = apiRes.upload.imageinfo.descriptionurl;
 879+
 880+ // Upload complete.
 881+ // Call the completion callback if available.
 882+ if ( _this.done_upload_cb && typeof _this.done_upload_cb == 'function' ) {
 883+ mw.log( "call done_upload_cb" );
 884+
 885+ // This overrides our normal completion handling so we close the
 886+ // dialog immediately.
 887+ _this.interface.close();
 888+ _this.done_upload_cb( apiRes.upload );
 889+ return false;
 890+ }
 891+
 892+ var buttons = {};
 893+ // "Return" button
 894+ buttons[ gM( 'mwe-return-to-form' ) ] = function() {
 895+ $j( this ).dialog( 'destroy' ).remove();
 896+ _this.form_post_override = false;
 897+ }
 898+ // "Go to resource" button
 899+ buttons[ gM('mwe-go-to-resource') ] = function() {
 900+ window.location = url;
 901+ };
 902+ _this.action_done = true;
 903+ _this.interface.setPrompt(
 904+ gM( 'mwe-successfulupload' ),
 905+ gM( 'mwe-upload_done', url),
 906+ buttons );
 907+ mw.log( 'apiRes.upload.imageinfo::' + url );
 908+ return true;
 909+ }
 910+ },
 911+
 912+ /**
 913+ * Get the default title of the progress window
 914+ */
 915+ getProgressTitle: function() {
 916+ return gM( 'mwe-upload-in-progress' );
 917+ },
 918+
 919+ /**
 920+ * Get the DOMNode of the form element we are rewriting.
 921+ * Returns false if it can't be found.
 922+ */
 923+ getForm: function() {
 924+
 925+ if ( this.form_selector && $j( this.form_selector ).length != 0 ) {
 926+ return $j( this.form_selector ).get( 0 );
 927+ } else {
 928+ mw.log( "mvBaseUploadHandler.getForm(): no form_selector" );
 929+ return false;
 930+ }
 931+ }
 932+
 933+};
 934+
 935+// jQuery plugins
 936+
 937+( function( $ ) {
 938+ /**
 939+ * Check the upload destination filename for conflicts and show a conflict
 940+ * error message if there is one
 941+ */
 942+ $.fn.doDestCheck = function( opt ) {
 943+ var _this = this;
 944+ mw.log( 'doDestCheck::' + _this.selector );
 945+
 946+ // Set up option defaults
 947+ if ( !opt.warn_target )
 948+ opt.warn_target = '#wpDestFile-warning';
 949+
 950+ // Add the wpDestFile-warning row
 951+ if ( $j( '#wpDestFile-warning' ).length == 0 ) {
 952+ $j( '#mw-htmlform-options tr:last' )
 953+ .after(
 954+ $j('<tr />' )
 955+ .append( '<td />' )
 956+ .append( '<td />' )
 957+ .attr('id', 'wpDestFile-warning')
 958+ );
 959+ }
 960+ mw.log( 'past dest');
 961+ // Remove any existing warning
 962+ $j( opt.warn_target ).empty();
 963+ mw.log( 'past remove warn:: ' + _this.selector);
 964+ // Show the AJAX spinner
 965+ $j( _this.selector ).after(
 966+ $j('<img />')
 967+ .attr({
 968+ 'id' : "mw-spinner-wpDestFile",
 969+ 'src' : stylepath + '/common/images/spinner.gif'
 970+ })
 971+ );
 972+ mw.log("added spiner");
 973+ var request = {
 974+ 'titles': 'File:' + $j( _this.selector ).val(),
 975+ 'prop': 'imageinfo',
 976+ 'iiprop': 'url|mime|size',
 977+ 'iiurlwidth': 150
 978+ };
 979+
 980+ // Do the destination check ( on the local wiki )
 981+ mw.getJSON( request, function( data ) {
 982+ // Remove spinner
 983+ $j( '#mw-spinner-wpDestFile' ).remove();
 984+
 985+ if ( !data || !data.query || !data.query.pages ) {
 986+ // Ignore a null result
 987+ return;
 988+ }
 989+
 990+ if ( data.query.pages[-1] ) {
 991+ // No conflict found
 992+ return;
 993+ }
 994+ for ( var page_id in data.query.pages ) {
 995+ if ( !data.query.pages[ page_id ].imageinfo ) {
 996+ continue;
 997+ }
 998+
 999+ // Conflict found, show warning
 1000+ if ( data.query.normalized ) {
 1001+ var ntitle = data.query.normalized[0].to;
 1002+ } else {
 1003+ var ntitle = data.query.pages[ page_id ].title
 1004+ }
 1005+ var img = data.query.pages[ page_id ].imageinfo[0];
 1006+ $j( '#wpDestFile-warning' ).html(
 1007+ gM( 'mwe-fileexists', ntitle ) +
 1008+ '<div class="thumb tright">' +
 1009+ '<div ' +
 1010+ 'style="width: ' + ( parseInt( img.thumbwidth ) + 2 ) + 'px;" ' +
 1011+ 'class="thumbinner">' +
 1012+ '<a ' +
 1013+ 'title="' + ntitle + '" ' +
 1014+ 'class="image" ' +
 1015+ 'href="' + img.descriptionurl + '">' +
 1016+ '<img ' +
 1017+ 'width="' + img.thumbwidth + '" ' +
 1018+ 'height="' + img.thumbheight + '" ' +
 1019+ 'border="0" ' +
 1020+ 'class="thumbimage" ' +
 1021+ 'src="' + img.thumburl + '" ' +
 1022+ 'alt="' + ntitle + '"/>' +
 1023+ '</a>' +
 1024+ '<div class="thumbcaption">' +
 1025+ '<div class="magnify">' +
 1026+ '<a title="' + gM('thumbnail-more') + '" class="internal" ' +
 1027+ 'href="' + img.descriptionurl +'">' +
 1028+ '<img width="15" height="11" alt="" ' +
 1029+ 'src="' + stylepath + "/common/images/magnify-clip.png\" />" +
 1030+ '</a>' +
 1031+ '</div>' +
 1032+ gM( 'mwe-fileexists-thumb' ) +
 1033+ '</div>' +
 1034+ '</div>' +
 1035+ '</div>'
 1036+ );
 1037+ }
 1038+ }
 1039+ );
 1040+ }
 1041+})( jQuery );
Property changes on: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadHandler.js
___________________________________________________________________
Name: svn:mergeinfo
11042 + /branches/REL1_15/phase3/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js:51646
/branches/sqlite/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js:58211-58321
Name: svn:eol-style
21043 + native
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/loader.js
@@ -14,12 +14,12 @@
1515 "$j.fn.dragDropFile" : "modules/AddMedia/jquery.dragDropFile.js",
1616 "$j.fn.simpleUploadForm": "modules/AddMedia/jquery.simpleUploadForm.js",
1717
18 - "mw.BaseUploadHandler": "modules/AddMedia/mw.BaseUploadHandler.js",
 18+ "mw.UploadHandler" : "modules/AddMedia/mw.UploadHandler.js",
 19+ "mw.UploadInterface" : "modules/AddMedia/mw.UploadInterface.js",
1920 "mw.Firefogg" : "modules/AddMedia/mw.Firefogg.js",
2021 "mw.FirefoggGUI" : "modules/AddMedia/mw.FirefoggGUI.js",
2122 "mw.FirefoggRender" : "modules/libSequencer/mw.FirefoggRender.js",
22 - "mw.RemoteSearchDriver" : "modules/AddMedia/mw.RemoteSearchDriver.js",
23 - "mw.InterfaceDispatch" : "modules/AddMedia/mw.InterfaceDispatch.js",
 23+ "mw.RemoteSearchDriver" : "modules/AddMedia/mw.RemoteSearchDriver.js",
2424
2525 "baseRemoteSearch" : "modules/AddMedia/searchLibs/baseRemoteSearch.js",
2626 "mediaWikiSearch" : "modules/AddMedia/searchLibs/mediaWikiSearch.js",
@@ -60,8 +60,8 @@
6161 //Set a variable for the base upload interface for easy inclution
6262 var baseUploadlibs = [
6363 [
64 - 'mw.BaseUploadHandler',
65 - 'mw.InterfaceDispatch',
 64+ 'mw.UploadHandler',
 65+ 'mw.UploadInterface',
6666 '$j.ui'
6767 ],
6868 [
@@ -118,7 +118,8 @@
119119
120120 mw.addModuleLoader( 'AddMedia.firefoggRender', function( callback ){
121121 mw.load( [
122 - 'mw.BaseUploadHandler',
 122+ 'mw.UploadHandler',
 123+ 'mw.UploadInterface',
123124 'mw.Firefogg',
124125 'mw.FirefoggRender'
125126 ], function() {
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadInterface.js
@@ -0,0 +1,223 @@
 2+/**
 3+* This handles upload interfaces
 4+*
 5+* There are several interface types:
 6+*
 7+* Inline interface
 8+* Dispatches updates to an inline html target
 9+*
 10+* Dialog interface
 11+* There is only one upload and it results in dialogs taking up the full screen
 12+*
 13+* Iframe interface
 14+* Dispatches updates to an iframe target for upload proxy
 15+*
 16+*/
 17+
 18+/**
 19+ * Base UploadInterfaceDispatch object (extened by
 20+ */
 21+mw.UploadInterface = {
 22+ factory : function( interfaceType ){
 23+ switch( interfaceType ){
 24+ case 'dialog':
 25+ default:
 26+ return new mw.DialogInterface( );
 27+ break;
 28+ }
 29+ }
 30+};
 31+
 32+/**
 33+ * Dialog Interface
 34+ */
 35+mw.DialogInterface = function( ) {
 36+ return this;
 37+}
 38+mw.DialogInterface.prototype = {
 39+
 40+ // The following are really state of the upload, not the interface.
 41+ // we are currently only managing one, so this is okay... for now.
 42+ uploadBeginTime: null,
 43+
 44+ setup: function( options ){
 45+ var _this = this;
 46+
 47+ // Start the "upload" time
 48+ this.uploadBeginTime = (new Date()).getTime();
 49+
 50+ // Remove the old instance if present
 51+ if( $j( '#upProgressDialog' ).length != 0 ) {
 52+ $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
 53+ }
 54+
 55+ // Add a new one
 56+ $j( 'body' ).append(
 57+ $j( '<div />')
 58+ .attr( 'id', "upProgressDialog" )
 59+ );
 60+ if( typeof options == 'undefined' || !options.title ){
 61+ options.title = gM('mwe-upload-in-progress');
 62+ }
 63+ $j( '#upProgressDialog' ).dialog( {
 64+ title : options.title,
 65+ bgiframe: true,
 66+ modal: true,
 67+ draggable: true,
 68+ width: 400,
 69+ heigh: 200,
 70+ beforeclose: function( event, ui ) {
 71+ // If the upload is not complete, ask the user if they want to cancel
 72+ if ( event.button == 0 && _this.action_done === false ) {
 73+ _this.onCancel( this );
 74+ return false;
 75+ } else {
 76+ // Complete already, allow close
 77+ return true;
 78+ }
 79+ },
 80+ buttons: _this.getCancelButton()
 81+ } );
 82+ mw.log( 'upProgressDialog::dialog done' );
 83+
 84+ var $progressContainer = $j('<div />')
 85+ .attr('id', 'up-pbar-container')
 86+ .css({
 87+ 'height' : '15px'
 88+ });
 89+ // add the progress bar
 90+ $progressContainer.append(
 91+ $j('<div />')
 92+ .attr('id', 'up-progressbar')
 93+ .css({
 94+ 'height' : '15px'
 95+ })
 96+ );
 97+ // Add the status container
 98+ $progressContainer.append( $j('<span />' )
 99+ .attr( 'id', 'up-status-container')
 100+ .css( 'float', 'left' )
 101+ .append(
 102+ $j( '<span />' )
 103+ .attr( 'id' , 'up-pstatus')
 104+ .text( '0% -' ),
 105+
 106+ $j( '<span />' )
 107+ .attr( 'id', 'up-status-state' )
 108+ .text( gM( 'mwe-uploaded-status' ) )
 109+ )
 110+ );
 111+ // Add the estimated time remaining
 112+ $progressContainer.append(
 113+ $j('<span />')
 114+ .attr( 'id', 'up-etr' )
 115+ .css( 'float', 'right' )
 116+ .text( gM( 'mwe-uploaded-time-remaining', '' ) )
 117+ )
 118+ // Add the status container to dialog div
 119+ $j( '#upProgressDialog' ).empty().append( $progressContainer );
 120+
 121+ // Open the empty progress window
 122+ $j( '#upProgressDialog' ).dialog( 'open' );
 123+
 124+ // Create progress bar
 125+ $j( '#up-progressbar' ).progressbar({
 126+ value: 0
 127+ });
 128+ },
 129+
 130+ /**
 131+ * Update the progress bar to a given completion fraction (between 0 and 1)
 132+ * NOTE: This progress bar is used for encoding AND for upload with no clear Distinction (might want to fix)
 133+ * @param {Float} progress Progress float
 134+ */
 135+ updateProgress: function( fraction, start_time ) {
 136+ var _this = this;
 137+
 138+ $j( '#up-progressbar' ).progressbar( 'value', parseInt( fraction * 100 ) );
 139+ $j( '#up-pstatus' ).html( parseInt( fraction * 100 ) + '% - ' );
 140+
 141+ if ( _this.uploadBeginTime) {
 142+ var elapsedMilliseconds = ( new Date() ).getTime() - _this.uploadBeginTime;
 143+ if (fraction > 0.0 && elapsedMilliseconds > 0) { // or some other minimums for good data
 144+ var fractionPerMillisecond = fraction / elapsedMilliseconds;
 145+ var remainingSeconds = parseInt( ( ( 1.0 - fraction ) / fractionPerMillisecond ) / 1000 );
 146+ $j( '#up-etr' ).html( gM( 'mwe-uploaded-time-remaining', mw.seconds2npt(remainingSeconds) ) );
 147+ }
 148+ }
 149+
 150+ },
 151+
 152+ /**
 153+ * UI cancel button handler.
 154+ * Show a dialog box asking the user whether they want to cancel an upload.
 155+ * @param Element dialogElement Dialog element to be canceled
 156+ */
 157+ onCancel: function( dialogElement ) {
 158+ //confirm:
 159+ if ( confirm( gM( 'mwe-cancel-confim' ) ) ) {
 160+ // NOTE: (cancel the encode / upload)
 161+ $j( dialogElement ).dialog( 'close' );
 162+ }
 163+ },
 164+
 165+ /**
 166+ * Set the dialog to loading
 167+ * @param optional loadingText text to set dialog to.
 168+ */
 169+ setLoading: function( loadingText ){
 170+ this.action_done = false;
 171+ //Update the progress dialog (no bar without XHR request)
 172+ $j( '#upProgressDialog' ).loadingSpinner();
 173+ },
 174+
 175+ /**
 176+ * Set the interface with a "title", "msg text" and buttons prompts
 177+ * list of buttons below it.
 178+ *
 179+ * @param title_txt Plain text
 180+ * @param msg HTML
 181+ * @param buttons See http://docs.jquery.com/UI/Dialog#option-buttons
 182+ */
 183+ setPrompt: function( title_txt, msg, buttons ) {
 184+ var _this = this;
 185+
 186+ if ( !title_txt )
 187+ title_txt = _this.getProgressTitle();
 188+
 189+ if ( !msg )
 190+ msg = mw.loading_spinner( 'left:40%;top:40px;' );
 191+
 192+ if ( !buttons ) {
 193+ // If no buttons are specified, add a close button
 194+ buttons = {};
 195+ buttons[ gM( 'mwe-ok' ) ] = function() {
 196+ $j( this ).dialog( 'close' );
 197+ };
 198+ }
 199+ $j( '#upProgressDialog' ).dialog( 'option', 'title', title_txt );
 200+ $j( '#upProgressDialog' ).html( msg );
 201+ $j( '#upProgressDialog' ).dialog( 'option', 'buttons', buttons );
 202+ },
 203+
 204+ /**
 205+ * Set the dialog to "done"
 206+ */
 207+ close: function(){
 208+ this.action_done = true;
 209+ $j( '#upProgressDialog' ).dialog( 'destroy' ).remove();
 210+ },
 211+ /**
 212+ * Get a standard cancel button in the jQuery.ui dialog format
 213+ */
 214+ getCancelButton: function() {
 215+ var _this = this;
 216+ mw.log( 'f: getCancelButton()' );
 217+ var cancelBtn = [];
 218+ cancelBtn[ gM( 'mwe-cancel' ) ] = function() {
 219+ $j( dlElm ).dialog( 'close' );
 220+ };
 221+ return cancelBtn;
 222+ }
 223+}
 224+
Property changes on: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.UploadInterface.js
___________________________________________________________________
Name: svn:mergeinfo
1225 + /branches/REL1_15/phase3/js2/mwEmbed/libAddMedia/mw.InterfaceDispatch.js:51646
/branches/sqlite/js2/mwEmbed/libAddMedia/mw.InterfaceDispatch.js:58211-58321
Name: svn:executable
2226 + *
Index: branches/js2-work/phase3/js/mwEmbed/modules/AddMedia/mw.Firefogg.js
@@ -3,7 +3,8 @@
44 */
55
66 mw.addMessages({
7 - "fogg-select_file" : "Select file",
 7+ "mwe-upload-transcode-in-progress" : "Transcode and upload in progress (do not close this window)",
 8+ "fogg-select_file" : "Select file",
89 "fogg-select_new_file" : "Select new file",
910 "fogg-select_url" : "Select URL",
1011 "fogg-save_local_file" : "Save Ogg",
@@ -154,12 +155,12 @@
155156
156157 // Inherit from mw.BaseUploadHandler (unless we're in only_firefogg mode)
157158 if ( !this.only_firefogg ) {
158 - var myBUI = new mw.BaseUploadHandler( options );
 159+ var myBUI = new mw.UploadHandler( options );
159160
160 - // Prefix conflicting members with pe_
 161+ // Prefix conflicting members with parent_
161162 for ( var i in myBUI ) {
162163 if ( this[i] ) {
163 - this['pe_'+ i] = myBUI[i];
 164+ this['parent_'+ i] = myBUI[i];
164165 } else {
165166 this[i] = myBUI[i];
166167 }
@@ -365,7 +366,7 @@
366367 var _this = this;
367368 // Set up the parent if we are in upload mode
368369 if ( this.form_type == 'upload' ) {
369 - this.pe_setupForm();
 370+ this.parent_setupForm();
370371 }
371372
372373 // If Firefogg is not available, just show a "please install" message
@@ -413,20 +414,6 @@
414415 },
415416
416417 /**
417 - * Display an upload progress overlay. Overrides the function in mw.BaseUploadHandler.
418 - */
419 - displayProgressOverlay: function() {
420 - this.pe_displayProgressOverlay();
421 - // If we are uploading video (not in passthrough mode), show preview button
422 - if( this.getFirefogg()
423 - && !this.isCopyUpload()
424 - && !this.getEncoderSettings()['passthrough'] )
425 - {
426 - this.createPreviewControls();
427 - }
428 - },
429 -
430 - /**
431418 * Create controls for showing a transcode/crop/resize preview
432419 */
433420 createPreviewControls: function() {
@@ -565,7 +552,7 @@
566553 */
567554 getForm: function() {
568555 if ( this.form_selector ) {
569 - return this.pe_getForm();
 556+ return this.parent_getForm();
570557 } else {
571558 // No configured form selector
572559 // Use the first form descendant of the current container
@@ -687,7 +674,7 @@
688675 mw.log( 'doLocalEncodeAndSave: no Firefogg object!' );
689676 return false;
690677 }
691 -
 678+
692679 // Set up the target location
693680 // Firefogg shows the "save as" dialog box, and sets the path chosen as
694681 // the destination for a later encode() call.
@@ -699,7 +686,7 @@
700687 // We have a source file, now do the encode
701688 this.doEncode(
702689 function /* onProgress */ ( progress ) {
703 - _this.updateProgress( progress );
 690+ _this.interface.updateProgress( progress );
704691 },
705692 function /* onDone */ () {
706693 mw.log( "done with encoding (no upload) " );
@@ -713,7 +700,7 @@
714701 */
715702 onLocalEncodeDone: function() {
716703 var _this = this;
717 - _this.updateProgressWin( gM( 'fogg-encoding-done' ),
 704+ _this.interface.setPrompt( gM( 'fogg-encoding-done' ),
718705 gM( 'fogg-encoding-done' ) + '<br>' +
719706 //show the video at full resolution upto 720px wide
720707 '<video controls="true" style="margin:auto" id="fogg_final_vid" src="' +
@@ -816,7 +803,7 @@
817804 ' mode:' + this.form_type );
818805 // Return the parent's title if we don't have Firefogg turned on
819806 if ( !this.getFirefogg() || !this.firefogg_form_action ) {
820 - return this.pe_getProgressTitle();
 807+ return this.parent_getProgressTitle();
821808 } else if ( this.form_type == 'local' ) {
822809 return gM( 'fogg-transcoding' );
823810 } else {
@@ -837,9 +824,18 @@
838825 _this.uploadBeginTime = (new Date()).getTime();
839826 // If Firefogg is disabled or doing an copyByUrl upload, just invoke the parent method
840827 if( !this.getFirefogg() || this.isCopyUpload() ) {
841 - _this.pe_doUpload();
 828+ _this.parent_doUpload();
842829 return ;
843830 }
 831+
 832+ // Setup the firefogg dialog (if not passthrough )
 833+ _this.interface.setup( { 'title' : gM( 'mwe-upload-transcode-in-progress' ) } );
 834+ // add the preview controls if transcoding:
 835+ if ( !_this.getEncoderSettings()['passthrough'] ) {
 836+ _this.createPreviewControls();
 837+ }
 838+
 839+
844840 // Get the input form data into an array
845841 mw.log( 'get this.formData ::' );
846842 var data = $j( this.form ).serializeArray();
@@ -869,7 +865,7 @@
870866 // No edit token. Fetch it asynchronously and then do the upload.
871867 mw.getToken( _this.api_url, 'File:'+ _this.formData['filename'], function( editToken ) {
872868 if( !editToken || editToken == '+\\' ) {
873 - _this.updateProgressWin( gM( 'fogg-badtoken' ), gM( 'fogg-badtoken' ) );
 869+ _this.interface.setPrompt( gM( 'fogg-badtoken' ), gM( 'fogg-badtoken' ) );
874870 return false;
875871 }
876872 _this.editToken = editToken;
@@ -1004,9 +1000,7 @@
10051001 _this.fogg.encode( JSON.stringify( { 'passthrough' : true } ) );
10061002 doneCallback();
10071003 return ;
1008 - }
1009 - // Display progress
1010 - _this.displayProgressOverlay();
 1004+ }
10111005
10121006 mw.log( 'doEncode: with: ' + JSON.stringify( encoderSettings ) );
10131007 _this.fogg.encode( JSON.stringify( encoderSettings ) );
@@ -1101,9 +1095,9 @@
11021096 _this.renderPreview();
11031097 }
11041098 }
1105 - //mw.log("update progress: " + _this.fogg.progress() + ' state: ' + _this.fogg.state );
1106 - // Update the progress bar
1107 - _this.updateProgress( _this.fogg.progress() );
 1099+
 1100+ // If not an error, Update the progress bar
 1101+ _this.interface.updateProgress( _this.fogg.progress() );
11081102
11091103 // If we're still uploading or encoding, continue to poll the status
11101104 if ( _this.fogg.state == 'encoding' || _this.fogg.state == 'uploading' ) {
@@ -1130,7 +1124,7 @@
11311125 showMessage = _this.done_upload_cb( _this.formData );
11321126 }
11331127 if ( showMessage ) {
1134 - _this.updateProgressWin( gM( 'mwe-successfulupload' ),
 1128+ _this.interface.setPrompt( gM( 'mwe-successfulupload' ),
11351129 gM( 'mwe-upload_done', apiResult.resultUrl ), buttons );
11361130 } else {
11371131 this.action_done = true;
@@ -1151,7 +1145,7 @@
11521146 */
11531147 onCancel: function( dialogElement ) {
11541148 if ( !this.have_firefogg ) {
1155 - return this.pe_cancel_action();
 1149+ return this.parent_cancel_action();
11561150 }
11571151 mw.log( 'firefogg:cancel' )
11581152 if ( confirm( gM( 'mwe-cancel-confim' ) ) ) {

Status & tagging log