r63669 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r63668‎ | r63669 | r63670 >
Date:01:38, 13 March 2010
Author:neilk
Status:deferred
Tags:
Comment:
conform better to MediaWiki style guide -- massive change without any functionality change, but we might as well get it over with
Modified paths:
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.ApiUploadHandler.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.IframeTransport.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.Language.js (modified) (history)
  • /branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.UploadWizard.js (modified) (history)

Diff [purge]

Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.Language.js
@@ -2,8 +2,10 @@
33 'mwe-code-unknown': 'Unknown language'
44 });
55
6 -
7 -// TODO: make this a more common library, used by this and TimedText
 6+/**
 7+ * Utility class which knows about languages, and how to construct HTML to select them
 8+ * TODO: make this a more common library, used by this and TimedText
 9+ */
810 mw.Language = {
911
1012 defaultCode: 'en', // when we absolutely have no idea what language to preselect
@@ -379,68 +381,84 @@
380382 { code: "got", text: "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a" },
381383 ],
382384
383 - // cache some useful objects
384 - // 1) mostly ready-to-go language HTML menu. When/if we upgrade, make it a jQuery combobox
385 - // 2) dict of language code to name -- useful for testing for existence, maybe other things.
 385+ /**
 386+ * cache some useful objects
 387+ * 1) mostly ready-to-go language HTML menu. When/if we upgrade, make it a jQuery combobox
 388+ * 2) dict of language code to name -- useful for testing for existence, maybe other things.
 389+ */
386390 initialize: function() {
387 - if (mw.Language.initialized) {
 391+ if ( mw.Language.initialized ) {
388392 return;
389393 }
390394 mw.Language._codes = {};
391 - var select = $j('<select/>');
392 - $j.each(mw.Language.languages, function(i, language) {
 395+ var select = $j( '<select/>' );
 396+ $j.each( mw.Language.languages, function( i, language ) {
393397 select.append(
394 - $j('<option>')
395 - .attr('value', language.code)
396 - .append(language.text)
 398+ $j( '<option>' )
 399+ .attr( 'value', language.code )
 400+ .append( language.text )
397401 );
398402 mw.Language._codes[language.code] = language.text;
399 - });
 403+ } );
400404 mw.Language.$_select = select;
401405 mw.Language.initialized = true;
402406 },
403407
404 - getMenu: function(name, code) {
 408+ /**
 409+ * Get an HTML select menu of all our languages.
 410+ * @param name desired name of select element
 411+ * @param code desired default language code
 412+ * @return HTML select element configured as desired
 413+ */
 414+ getMenu: function( name, code ) {
405415 mw.Language.initialize();
406416 var $select = mw.Language.$_select.clone();
407 - $select.attr('name', name);
408 - if (code === mw.Language.UNKNOWN) {
 417+ $select.attr( 'name', name );
 418+ if ( code === mw.Language.UNKNOWN ) {
409419 // n.b. MediaWiki LanguageHandler has ability to add custom label for 'Unknown'; possibly as pseudo-label
410 - $select.prepend($j('<option>').attr('value', mw.Language.UNKNOWN).append(gM('mwe-code-unknown')));
411 - $select.val(mw.Language.UNKNOWN);
412 - } else if (code !== undefined) {
413 - $select.val(mw.Language.getClosest(code));
 420+ $select.prepend( $j( '<option>' ).attr( 'value', mw.Language.UNKNOWN ).append( gM( 'mwe-code-unknown' )) );
 421+ $select.val( mw.Language.UNKNOWN );
 422+ } else if ( code !== undefined ) {
 423+ $select.val( mw.Language.getClosest( code ));
414424 }
415 - return $select.get(0);
 425+ return $select.get( 0 );
416426 },
417427
418 - /* logic from MediaWiki:LanguageHandler.js */
419 - // handle null cases, special cases for some Chinese variants
420 - // Otherwise, if handed "foo-bar-baz" language, try to match most specific language,
421 - // "foo-bar-baz", then "foo-bar", then "foo"
422 - getClosest: function(code) {
 428+ /**
 429+ * Figure out the closest language we have to a supplied language code.
 430+ * It seems that people on Mediawiki set their language code as freetext, and it could be anything, even
 431+ * variants we don't have a record for, or ones that are not in any ISO standard.
 432+ *
 433+ * Logic copied from MediaWiki:LanguageHandler.js
 434+ * handle null cases, special cases for some Chinese variants
 435+ * Otherwise, if handed "foo-bar-baz" language, try to match most specific language,
 436+ * "foo-bar-baz", then "foo-bar", then "foo"
 437+ *
 438+ * @param code A string representing a language code, which we may or may not have.
 439+ * Expected to be separated with dashes as codes from ISO 639, e.g. "zh-tw" for Chinese ( Traditional )
 440+ * @return a language code which is close to the supplied parameter, or fall back to mw.Language.defaultCode
 441+ */
 442+ getClosest: function( code ) {
423443 mw.Language.initialize();
424 - if (typeof (code) != 'string' || code === null || code.length === 0) {
 444+ if ( typeof ( code ) != 'string' || code === null || code.length === 0 ) {
425445 return mw.Language.defaultCode;
426446 }
427 - if (code == 'nan' || code == 'minnan') {
 447+ if ( code == 'nan' || code == 'minnan' ) {
428448 return 'zh-min-nan';
429 - } else if (mw.Language._codes[code] !== undefined) {
 449+ } else if ( mw.Language._codes[code] !== undefined ) {
430450 return code;
431451 }
432 - return mw.Language.getClosest(code.substring(0, code.indexOf('-')));
 452+ return mw.Language.getClosest( code.substring( 0, code.indexOf( '-' )) );
433453 },
434454
435 - // XXX n.b. there are a lot of "closest matching language" features in older MediaWiki:LanguageHandler; we will have to emulate
436455
437 -
438456 // enhance a simple text input to be an autocompleting language menu
439457 // this will work when/if we move to jQuery 1.4. As of now the autocomplete is too underpowered for our needs without
440458 // serious hackery
441459 /*
442 - $j.fn.languageMenu = function(options) {
 460+ $j.fn.languageMenu = function( options ) {
443461 var _this = this;
444 - _this.autocomplete(null, {
 462+ _this.autocomplete( null, {
445463 minChars: 0,
446464 width: 310,
447465 selectFirst: true,
@@ -450,16 +468,16 @@
451469 highlightItem: true,
452470 scroll: true,
453471 scrollHeight: 220,
454 - formatItem: function(row, i, max, term) {
 472+ formatItem: function( row, i, max, term ) {
455473 return row.code + " " + row.code;
456474 },
457 - formatMatch: function(row, i, max, term) {
 475+ formatMatch: function( row, i, max, term ) {
458476 return row.code + " " + row.code;
459477 },
460 - formatResult: function(row) {
 478+ formatResult: function( row ) {
461479 return row.code;
462480 }
463 - }, mw.languages);
 481+ }, mw.languages );
464482
465483 // and add a dropdown so we can see the thingy, too
466484 return _this;
@@ -467,7 +485,7 @@
468486 */
469487
470488 // XXX the concept of "internal language" exists in UploadForm.js -- seems to be how they handled i18n, with
471 - // language codes that has underscores rather than dashes, ("en_gb" rather than the correct "en-gb").
 489+ // language codes that has underscores rather than dashes, ( "en_gb" rather than the correct "en-gb" ).
472490 // although other info such as Information boxes was recorded correctly.
473491 // This is presumed not to apply to the shiny new world of JS2, where i18n is handled in other ways.
474492
Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.UploadWizard.js
@@ -1,4 +1,4 @@
2 -mw.addMessages({
 2+mw.addMessages( {
33 'mwe-upwiz-tab-file': 'Step 1',
44 'mwe-upwiz-tab-metadata': 'Step 2',
55 'mwe-upwiz-tab-thanks': 'Step 3',
@@ -54,22 +54,22 @@
5555
5656 // available licenses should be a configuration of the MediaWiki instance,
5757 // not hardcoded here.
58 - // but, MediaWiki has no real concept of a License as a first class object -- there are templates and then specially-parsed
 58+ // but, MediaWiki has no real concept of a License as a first class object -- there are templates and then specially - parsed
5959 // texts to create menus -- hack on top of hacks -- a bit too much to deal with ATM
6060 'mwe-lic-pd': 'Public domain',
6161 'mwe-lic-cc-0': 'Creative Commons Zero waiver',
6262 'mwe-lic-cc-by-3.0': 'Creative Commons Attribution 3.0',
6363 'mwe-lic-cc-by-sa-3.0': 'Creative Commons Attribution ShareAlike 3.0',
6464 'mwe-lic-gfdl': 'GFDL'
65 -});
 65+} );
6666
6767
6868
69 -// this interface only works for the wizard... should say so in class name
70 -// XXX there is a CSS/scripting trick to get X-browser consistent file input, plus one-click file input
71 -// It will not work in Netscape 4, Explorer 4, or Netscape 3.
72 -// We probably don't care, but... http://www.quirksmode.org/dom/inputfile.html in case we do
73 -mw.UploadWizardUploadInterface = function(filenameAcceptedCb) {
 69+/**
 70+ * Create an interface fragment corresponding to a file input, suitable for Upload Wizard.
 71+ * @param filenameAcceptedCb Execute if good filename entered into this interface; useful for knowing if we're ready to upload
 72+ */
 73+mw.UploadWizardUploadInterface = function( filenameAcceptedCb ) {
7474 var _this = this;
7575
7676 _this.filenameAcceptedCb = filenameAcceptedCb;
@@ -89,133 +89,160 @@
9090
9191 _this.form = $j('<form class="mwe-upwiz-form"></form>')
9292 .append($j('<div class="mwe-upwiz-file-ctrl-container">')
93 - .append(_this.fileInputCtrl)
94 - .append(_this.visibleFilename)
95 - ).append(_this.filenameCtrl).get(0);
 93+ .append( _this.fileInputCtrl )
 94+ .append( _this.visibleFilename )
 95+ ).append( _this.filenameCtrl ).get( 0 );
9696
9797 _this.progressMessage = $j('<span class="mwe-upwiz-status-message" style="display: none"></span>').get(0);
9898
99 - $j(_this.fileInputCtrl).change( function() { _this.fileChanged() } );
 99+ $j( _this.fileInputCtrl ).change( function() { _this.fileChanged() } );
100100
101101 _this.errorDiv = $j('<div class="mwe-upwiz-upload-error" style="display: none;"></div>').get(0);
102102
103103
104 - $j(_this.div).append(_this.form)
105 - .append(_this.progressMessage)
106 - .append(_this.errorDiv);
 104+ $j( _this.div ).append( _this.form )
 105+ .append( _this.progressMessage )
 106+ .append( _this.errorDiv );
107107
108 - // _this.progressBar = (no progress bar for individual uploads yet)
 108+ // _this.progressBar = ( no progress bar for individual uploads yet )
109109 // add a metadata thing to metadata
110110 };
111111
112112 mw.UploadWizardUploadInterface.prototype = {
113 - /* start! */
 113+ /**
 114+ * Things to do to this interface once we start uploading
 115+ */
114116 start: function() {
115117 var _this = this;
116 - $j(_this.removeCtrl).hide();
 118+ $j( _this.removeCtrl ).hide();
117119 },
118120
119 - /* generically busy, but not a fraction. Encoding, or transports that don't know progress */
 121+ /**
 122+ * Make this interface look "busy" (i.e. spinner) without indicating a particular percentage of file uploaded.
 123+ * Will be useful for encoding phase of Firefogg, for example.
 124+ */
120125 busy: function() {
121126 var _this = this;
122127 // for now we implement this as looking like "100% progress"
123128 // e.g. an animated bar that takes up all the space
124 - _this.progress(1.0);
 129+ _this.progress( 1.0 );
125130 },
126131
127 - /* show progress with a certain fraction */
128 - progress: function(fraction) {
 132+ /**
 133+ * Show progress by a fraction
 134+ * @param fraction The fraction of progress. Float between 0 and 1
 135+ */
 136+ progress: function( fraction ) {
129137 var _this = this;
130 - $j(_this.progressMessage).addClass('mwe-upwiz-status-progress')
131 - .html(gM( 'mwe-upwiz-uploading' ))
132 - .show();
 138+ $j( _this.progressMessage ).addClass('mwe-upwiz-status-progress')
 139+ .html(gM( 'mwe-upwiz-uploading' ))
 140+ .show();
133141 // update individual progress bar with fraction?
134142 },
135143
136 - // this is just completed in the sense that it's all uploaded. There may be other errors?
137 - // really need to rethink the UI / metadata separation
138 - completed: function(result) {
 144+ /**
 145+ * Execute when this upload is completed; cleans up interface.
 146+ * @param result AJAx result object
 147+ */
 148+ completed: function( result ) {
139149 var _this = this;
140 - $j(_this.progressMessage).removeClass('mwe-upwiz-status-progress')
141 - .addClass('mwe-upwiz-status-completed')
142 - .html(gM( 'mwe-upwiz-completed' ));
 150+ $j( _this.progressMessage ).removeClass( 'mwe-upwiz-status-progress' )
 151+ .addClass( 'mwe-upwiz-status-completed' )
 152+ .html( gM( 'mwe-upwiz-completed' ) );
143153 },
144154
 155+ /**
 156+ * Run this when the value of the file input has changed. Check the file for various forms of goodness.
 157+ */
145158 fileChanged: function() {
146159 var _this = this;
147160 _this.clearErrors();
148161 var ext = _this.getExtension();
149 - if (_this.isGoodExtension(ext)) {
 162+ if ( _this.isGoodExtension( ext ) ) {
150163 _this.updateFilename();
151164 } else {
152 - _this.error('bad-filename-extension', ext);
 165+ _this.error( 'bad-filename-extension', ext );
153166 }
154167 },
155168
156 - // this does two things:
157 - // 1) since the file input has been hidden with some clever CSS (to avoid x-browser styling issues),
158 - // update the visible filename
159 - //
160 - // 2) update the filename desired when added to MediaWiki. This should be RELATED to the filename on the filesystem,
161 - // but it should be silently fixed so that it does not trigger uniqueness conflicts. i.e. if server has cat.jpg we change ours to cat_2.jpg.
162 - // This is hard to do in a scalable fashion on the client; we don't want to do 12 api calls to get cat_12.jpg.
163 - // Ideally we should ask the SERVER for a decently unique filename related to our own.
164 - // So, at the moment, this is hacked with a guaranteed-unique filename instead.
 169+ /**
 170+ * this does two things:
 171+ * 1 ) since the file input has been hidden with some clever CSS ( to avoid x-browser styling issues ),
 172+ * update the visible filename
 173+ *
 174+ * 2 ) update the filename desired when added to MediaWiki. This should be RELATED to the filename on the filesystem,
 175+ * but it should be silently fixed so that it does not trigger uniqueness conflicts. i.e. if server has cat.jpg we change ours to cat_2.jpg.
 176+ * This is hard to do in a scalable fashion on the client; we don't want to do 12 api calls to get cat_12.jpg.
 177+ * Ideally we should ask the SERVER for a decently unique filename related to our own.
 178+ * So, at the moment, this is hacked with a guaranteed - unique filename instead.
 179+ */
165180 updateFilename: function() {
166181 var _this = this;
167182 var path = $j(_this.fileInputCtrl).attr('value');
168183
169184 // visible filename
170 - $j(_this.visibleFilename).removeClass('helper').html(path);
 185+ $j( _this.visibleFilename ).removeClass( 'helper' ).html( path );
171186
172187 // desired filename
173 - var filename = _this.convertPathToFilename(path);
 188+ var filename = _this.convertPathToFilename( path );
174189 // this is a hack to get a filename guaranteed unique.
175 - uniqueFilename = mw.getConfig('userName') + "_" + (new Date()).getTime() + "_" + filename;
176 - $j(_this.filenameCtrl).attr('value', uniqueFilename);
 190+ uniqueFilename = mw.getConfig( 'userName' ) + "_" + ( new Date() ).getTime() + "_" + filename;
 191+ $j(_this.filenameCtrl).attr( 'value', uniqueFilename );
177192 _this.filenameAcceptedCb();
178193 },
179194
 195+ /**
 196+ * Remove any complaints we had about errors and such
 197+ * XXX this should be changed to something Theme compatible
 198+ */
180199 clearErrors: function() {
181200 var _this = this;
182 - // XXX this should be changed to something Theme compatible
183 - $j(_this.div).removeClass('mwe-upwiz-upload-error');
184 - $j(_this.errorDiv).hide().empty();
 201+ $j( _this.div ).removeClass( 'mwe-upwiz-upload-error ');
 202+ $j( _this.errorDiv ).hide().empty();
185203 },
186204
 205+ /**
 206+ * Show an error with the upload
 207+ */
187208 error: function() {
188209 var _this = this;
189 - var args = Array.prototype.slice.call(arguments); // copies arguments into a real array
 210+ var args = Array.prototype.slice.call( arguments ); // copies arguments into a real array
190211 var msg = 'mwe-upwiz-upload-error-' + args[0];
191 - $j(_this.errorDiv).append($j('<p class="mwe-upwiz-upload-error">' + gM(msg, args.slice(1)) + '</p>'));
 212+ $j( _this.errorDiv ).append( $j( '<p class="mwe-upwiz-upload-error">' + gM( msg, args.slice( 1 ) ) + '</p>') );
192213 // apply a error style to entire did
193 - $j(_this.div).addClass('mwe-upwiz-upload-error');
194 - $j(_this.errorDiv).show();
 214+ $j( _this.div ).addClass( 'mwe-upwiz-upload-error' );
 215+ $j( _this.errorDiv ).show();
195216 },
196217
197 - // arguably should be about filename, not path?
198 - // may check for common bad patterns here, like DSC_NNNNN, filenames too short, too long, etc.
199 - // steal that from the commons js
 218+ /**
 219+ * Get the extension of the path in fileInputCtrl
 220+ * @return extension as string
 221+ */
200222 getExtension: function() {
201223 var _this = this;
202224 var path = $j(_this.fileInputCtrl).attr('value');
203225 return path.substr( path.lastIndexOf( '.' ) + 1 ).toLowerCase();
204226 },
205227
206 - // XXX this is common utility code
207 - // used when converting contents of a file input and coming up with a suitable "filename" for mediawiki
208 - // test: what if path is length 0
209 - // what if path is all separators
210 - // what if path ends with a separator character
211 - // what if it ends with multiple separator characters
212 - convertPathToFilename: function(path) {
 228+ /**
 229+ * XXX this is common utility code
 230+ * used when converting contents of a file input and coming up with a suitable "filename" for mediawiki
 231+ * test: what if path is length 0
 232+ * what if path is all separators
 233+ * what if path ends with a separator character
 234+ * what if it ends with multiple separator characters
 235+ *
 236+ * @param path
 237+ * @return filename suitable for mediawiki as string
 238+ */
 239+ convertPathToFilename: function( path ) {
213240 if (path === undefined || path == '') {
214241 return '';
215242 }
216243
217244 var lastFileSeparatorIdx = Math.max(path.lastIndexOf( '/' ), path.lastIndexOf( '\\' ));
218245 // lastFileSeparatorIdx is now -1 if no separator found, or some index in the string.
219 - // so, +1, that is either 0 (beginning of string) or the character after last separator.
 246+ // so, +1, that is either 0 ( beginning of string ) or the character after last separator.
220247 // caution! could go past end of string... need to be more careful
221248 var filename = path.substring( lastFileSeparatorIdx + 1, 10000 );
222249
@@ -225,14 +252,18 @@
226253 return filename;
227254 },
228255
229 - // XXX this is common utility code
230 - // XXX unused, copied because we'll probably need it... stripped from old doDestinationFill
231 - // this is used when checking for "bad" extensions in a filename.
232 - isGoodExtension: function(ext) {
 256+ /**
 257+ * XXX this is common utility code
 258+ * copied because we'll probably need it... stripped from old doDestinationFill
 259+ * this is used when checking for "bad" extensions in a filename.
 260+ * @param ext
 261+ * @return boolean if extension was acceptable
 262+ */
 263+ isGoodExtension: function( ext ) {
233264 var _this = this;
234265 var found = false;
235266 var extensions = mw.getConfig('fileExtensions');
236 - if (extensions) {
 267+ if ( extensions ) {
237268 for ( var i = 0; i < extensions.length; i++ ) {
238269 if ( extensions[i].toLowerCase() == ext ) {
239270 found = true;
@@ -243,25 +274,12 @@
244275 }
245276
246277 };
247 -
248 -
249 -mw.UploadWizard = function() {
250 -
251 - this.uploadHandlerClass = mw.getConfig('uploadHandlerClass') || this.getUploadHandlerClass();
252 - this.isCompleted = false;
253278
254 - this.uploads = [];
255 - // leading underline for privacy. DO NOT TAMPER.
256 - this._uploadsQueued = [];
257 - this._uploadsInProgress = [];
258 - this._uploadsCompleted = [];
259 -
260 - this.uploadsBeginTime = null;
261 -
262 - return this;
263 -};
264 -
265 -mw.UploadWizardDescription = function(languageCode) {
 279+/**
 280+ * Object that represents an indvidual language description, in the metadata portion of Upload Wizard
 281+ * @param languageCode
 282+ */
 283+mw.UploadWizardDescription = function( languageCode ) {
266284 var _this = this;
267285
268286 // Logic copied from MediaWiki:UploadForm.js
@@ -277,56 +295,64 @@
278296 $j(_this.languageMenu).addClass('mwe-upwiz-desc-lang-select');
279297 _this.description = $j('<textarea name="desc" rows="3" cols="50" class="mwe-upwiz-desc-lang-text"></textarea>').get(0);
280298 _this.div = $j('<div class="mwe-upwiz-desc-lang-container"></div>')
281 - .append(_this.languageMenu)
282 - .append(_this.description)
 299+ .append( _this.languageMenu )
 300+ .append( _this.description )
283301
284302 };
285303
286304 mw.UploadWizardDescription.prototype = {
287305
 306+ /**
 307+ * Obtain text of this description, suitable for including into Information template
 308+ * @return wikitext as a string
 309+ */
288310 getWikiText: function() {
289311 var _this = this;
290312 return '{{' + _this.languageMenu.value + '|' + _this.description.value + '}}'
291313 }
292314 };
293315
294 -mw.UploadWizardMetadata = function(containerDiv) {
 316+/**
 317+ * Object that represents the Metadata (step 2) portion of the UploadWizard
 318+ * @param containerDiv The div to put the interface into
 319+ */
 320+mw.UploadWizardMetadata = function( containerDiv ) {
295321
296322 var _this = this;
297323 _this.descriptions = [];
298324
299 - _this.div = $j('<div class="mwe-upwiz-metadata-file"></div>');
 325+ _this.div = $j( '<div class="mwe-upwiz-metadata-file"></div>' );
300326
301 - _this.macroDiv = $j('<div class="mwe-upwiz-macro"></div>')
302 - .append($j('<input type="submit" value="test edit"/>').click(function() { _this.submit() }));
 327+ _this.macroDiv = $j( '<div class="mwe-upwiz-macro"></div>' )
 328+ .append( $j( '<input type="submit" value="test edit"/>' ).click( function( ) { _this.submit( ) } ));
303329
304 - _this.thumbnailDiv = $j('<div class="mwe-upwiz-thumbnail"></div>');
 330+ _this.thumbnailDiv = $j( '<div class="mwe-upwiz-thumbnail"></div>' );
305331
306 - _this.errorDiv = $j('<div class="mwe-upwiz-metadata-error"></div>');
 332+ _this.errorDiv = $j( '<div class="mwe-upwiz-metadata-error"></div>' );
307333
308 - _this.dataDiv = $j('<div class="mwe-upwiz-metadata-data"></div>');
 334+ _this.dataDiv = $j( '<div class="mwe-upwiz-metadata-data"></div>' );
309335
310 - _this.descriptionsDiv = $j('<div class="mwe-upwiz-metadata-descriptions"></div>');
 336+ _this.descriptionsDiv = $j( '<div class="mwe-upwiz-metadata-descriptions"></div>' );
311337
312 - _this.descriptionAdder = $j('<a id="mwe-upwiz-desc-add"/>')
313 - .attr('href', '#')
314 - .html( gM('mwe-upwiz-desc-add-0') )
315 - .click( function() { _this.addDescription() } );
 338+ _this.descriptionAdder = $j( '<a id="mwe-upwiz-desc-add"/>' )
 339+ .attr( 'href', '#' )
 340+ .html( gM( 'mwe-upwiz-desc-add-0' ) )
 341+ .click( function( ) { _this.addDescription( ) } );
316342
317343 _this.descriptionsContainerDiv =
318 - $j('<div class="mwe-upwiz-metadata-descriptions-container"></div>')
319 - .append( $j('<div class="mwe-upwiz-metadata-descriptions-title">' + gM('mwe-upwiz-desc') + '</div>') )
320 - .append(_this.descriptionsDiv)
321 - .append( $j('<div class="mwe-upwiz-metadata-descriptions-add"></div>')
322 - .append(_this.descriptionAdder) );
 344+ $j( '<div class="mwe-upwiz-metadata-descriptions-container"></div>' )
 345+ .append( $j( '<div class="mwe-upwiz-metadata-descriptions-title">' + gM( 'mwe-upwiz-desc' ) + '</div>' ) )
 346+ .append( _this.descriptionsDiv )
 347+ .append( $j( '<div class="mwe-upwiz-metadata-descriptions-add"></div>' )
 348+ .append( _this.descriptionAdder ) );
323349
324350
325 - $j(_this.div)
326 - .append(_this.macroDiv)
327 - .append(_this.thumbnailDiv)
328 - .append(_this.errorDiv)
329 - .append($j(_this.dataDiv)
330 - .append(_this.descriptionsContainerDiv));
 351+ $j( _this.div )
 352+ .append( _this.macroDiv )
 353+ .append( _this.thumbnailDiv )
 354+ .append( _this.errorDiv )
 355+ .append( $j( _this.dataDiv )
 356+ .append( _this.descriptionsContainerDiv ));
331357
332358
333359
@@ -352,120 +378,152 @@
353379 // Other info
354380
355381 _this.addDescription();
356 - $j(containerDiv).append(_this.div);
 382+ $j( containerDiv ).append( _this.div );
357383
358384
359385 };
360386
361387 mw.UploadWizardMetadata.prototype = {
362388
 389+ /**
 390+ * Do anything related to a change in the number of descriptions
 391+ */
363392 recountDescriptions: function() {
364393 var _this = this;
365394 // if there is some maximum number of descriptions, deal with that here
366 - $j(_this.descriptionAdder).html( gM('mwe-upwiz-desc-add-' + (_this.descriptions.length == 0 ? '0' : 'n') ) );
 395+ $j( _this.descriptionAdder ).html( gM( 'mwe-upwiz-desc-add-' + ( _this.descriptions.length == 0 ? '0' : 'n' ) ) );
367396 },
368397
369398
 399+ /**
 400+ * Add a new description
 401+ */
370402 addDescription: function() {
371403 var _this = this;
372 - var languageCode = _this.descriptions.length ? mw.Language.UNKNOWN : mw.getConfig('userLanguage');
373 - var description = new mw.UploadWizardDescription(languageCode);
 404+ var languageCode = _this.descriptions.length ? mw.Language.UNKNOWN : mw.getConfig('userLanguage' );
 405+ var description = new mw.UploadWizardDescription( languageCode );
374406
375 - description.removeCtrl = $j('<a title="' + gM( 'mwe-upwiz-remove-description') + '" href="#">x</a>')
376 - .addClass('mwe-upwiz-remove')
377 - .addClass('mwe-upwiz-remove-desc')
378 - .click( function() { _this.removeDescription(description) } )
379 - .get(0);
380 - $j(description.div).append(description.removeCtrl);
 407+ description.removeCtrl = $j('<a title="' + gM( 'mwe-upwiz-remove-description' ) + '" href="#">x</a>' )
 408+ .addClass('mwe-upwiz-remove' )
 409+ .addClass('mwe-upwiz-remove-desc' )
 410+ .click( function() { _this.removeDescription( description ) } )
 411+ .get( 0 );
 412+ $j( description.div ).append( description.removeCtrl );
381413
382 - $j(_this.descriptionsDiv).append(description.div);
383 - _this.descriptions.push(description);
 414+ $j( _this.descriptionsDiv ).append( description.div );
 415+ _this.descriptions.push( description );
384416 _this.recountDescriptions();
385417 },
386418
387 - removeDescription: function(description) {
 419+ /**
 420+ * Remove a description
 421+ * @param description
 422+ */
 423+ removeDescription: function( description ) {
388424 var _this = this;
389 - $j(description.div).remove();
390 - mw.UploadWizardUtil.removeItem(_this.descriptions, description);
 425+ $j( description.div ).remove();
 426+ mw.UploadWizardUtil.removeItem( _this.descriptions, description );
391427 _this.recountDescriptions();
392428 },
393429
394 - // this is a lot like upload ui's error -- should merge
 430+ /**
 431+ * Display an error with metadata
 432+ * XXX this is a lot like upload ui's error -- should merge
 433+ */
395434 error: function() {
396435 var _this = this;
397 - var args = Array.prototype.slice.call(arguments); // copies arguments into a real array
 436+ var args = Array.prototype.slice.call( arguments ); // copies arguments into a real array
398437 var msg = 'mwe-upwiz-upload-error-' + args[0];
399 - $j(_this.errorDiv).append($j('<p class="mwe-upwiz-upload-error">' + gM(msg, args.slice(1)) + '</p>'));
 438+ $j( _this.errorDiv ).append( $j( '<p class="mwe-upwiz-upload-error">' + gM( msg, args.slice( 1 ) ) + '</p>' ) );
400439 // apply a error style to entire did
401 - $j(_this.div).addClass('mwe-upwiz-upload-error');
402 - $j(_this.dataDiv).hide();
403 - $j(_this.errorDiv).show();
 440+ $j( _this.div ).addClass( 'mwe-upwiz-upload-error' );
 441+ $j( _this.dataDiv ).hide();
 442+ $j( _this.errorDiv ).show();
404443 },
405444
406 - // just like error but with ok/cancel
407 - errorDuplicate: function(sessionKey, duplicates) {
 445+ /**
 446+ * Display an error but check before proceeding -- useful for cases where user can override a failed upload due to
 447+ * hash collision
 448+ * just like error but with ok / cancel
 449+ * @param sessionKey
 450+ * @param duplicates
 451+ */
 452+ errorDuplicate: function( sessionKey, duplicates ) {
408453 var _this = this;
409454 /*
410455 TODO - do something clever to get page URLs and image URLs
411456 var duplicatePageTitles = result.upload.warnings.duplicate;
412457 var duplicates = [];
413 - for (var i = 0; i < duplicates.length; i++) {
414 - imageInfo = mw.getJSON(undefined,
 458+ for ( var i = 0; i < duplicates.length; i++ ) {
 459+ imageInfo = mw.getJSON( undefined,
415460 {'titles' : duplicatePageTitles[i], 'prop' : 'imageinfo'})
416 - function() { _this.renderUploads() });
417 - duplicates.push({
 461+ function() { _this.renderUploads() } );
 462+ duplicates.push( {
418463 // ?? async, so we should insert later...
419 - })
 464+ } )
420465 }
421466 */
422 - _this.error('duplicate');
 467+ _this.error( 'duplicate' );
423468 // add placeholder spinners to div, and then fetch the thumbnails and so on async
424469 // meanwhile...
425 - //$j(_this.errorDiv).append(
 470+ //$j( _this.errorDiv ).append(
426471 // $j('<form></form>');
427 - // same as normal error but you get to ok/cancel, which resubmits with ignore warnings
 472+ // same as normal error but you get to ok / cancel, which resubmits with ignore warnings
428473 },
429474
430 - // given the API result pull some info into the form (for instance, extracted from EXIF, desired filename)
431 - populateFromResult: function(result) {
 475+ /**
 476+ * Given the API result pull some info into the form ( for instance, extracted from EXIF, desired filename )
 477+ * @param result Upload API result object
 478+ */
 479+ populateFromResult: function( result ) {
432480 var _this = this;
433481 var upload = result.upload;
434 - mw.log("populating from result");
435 - _this.setThumbnail(upload.filename, mw.getConfig('thumbnailWidth'));
436 - //_this.setSource(upload. result);
 482+ mw.log( "populating from result" );
 483+ _this.setThumbnail( upload.filename, mw.getConfig( 'thumbnailWidth' ));
 484+ //_this.setSource( upload. result );
437485
438 - //_this.setFilename(upload.filename);
 486+ //_this.setFilename( upload.filename );
439487
440488 //_this.setDescription(); // is there anything worthwhile here? image comment?
441 - //_this.setDate(upload.metadata);
442 - //_this.setLocation(upload.metadata); // we could be VERY clever with location sensing...
443 - //_this.setAuthor(_this.config.user, upload.exif.Copyright);
 489+ //_this.setDate( upload.metadata );
 490+ //_this.setLocation( upload.metadata ); // we could be VERY clever with location sensing...
 491+ //_this.setAuthor( _this.config.user, upload.exif.Copyright );
444492 },
445493
446 - // look up thumbnail info and set it
447 - setThumbnail: function(filename, width) {
 494+ /**
 495+ * look up thumbnail info and set it on the form, with loading spinner
 496+ * @param filename
 497+ * @param width
 498+ */
 499+ setThumbnail: function( filename, width ) {
448500 var _this = this;
449501
450 - var callback = function(imageInfo) {
451 - var thumbnail = $j('<img class="mwe-upwiz-thumbnail"/>').get(0);
 502+ var callback = function( imageInfo ) {
 503+ var thumbnail = $j( '<img class="mwe-upwiz-thumbnail"/>' ).get( 0 );
452504 thumbnail.width = imageInfo.thumbwidth;
453505 thumbnail.height = imageInfo.thumbheight;
454506 thumbnail.src = imageInfo.thumburl;
455507 // side effect: will replace thumbnail's loadingSpinner
456 - _this.thumbnailDiv.html(thumbnail);
 508+ _this.thumbnailDiv.html( thumbnail );
457509 };
458510
459511 _this.thumbnailDiv.loadingSpinner();
460 - _this.getThumbnail("File:" + filename, width, callback);
 512+ _this.getThumbnail( "File:" + filename, width, callback );
461513
462514 },
463515
464 - // use iinfo to get thumbnail info
465 - // this API method can be used to get a lot of thumbnails at once, but that may not be so useful for us ATM
466 - // this is mostly ripped off from mw.UploadHandler's doDestCheck, but: stripped of UI, does only one, does not check for name collisions.
467 - getThumbnail: function(title, width, setThumbnailCb, apiUrl) {
 516+ /**
 517+ * use iinfo to get thumbnail info
 518+ * this API method can be used to get a lot of thumbnails at once, but that may not be so useful for us ATM
 519+ * this is mostly ripped off from mw.UploadHandler's doDestCheck, but: stripped of UI, does only one, does not check for name collisions.
 520+ * @param title - name of the file on mediawiki (e.g. File:Foo.jpg)
 521+ * @param width - desired width of thumbnail (height will scale to match)
 522+ * @param setThumbnailCb - callback to execute once info has been obtained (for instance, put it into the interface)
 523+ * @param apiUrl - where to get your API results
 524+ */
 525+ getThumbnail: function( title, width, setThumbnailCb, apiUrl ) {
468526
469 - if (apiUrl === undefined) {
 527+ if ( apiUrl === undefined ) {
470528 apiUrl = mw.getLocalApiUrl();
471529 }
472530
@@ -476,34 +534,38 @@
477535 'iiprop': 'url|mime|size'
478536 };
479537
480 - mw.getJSON(apiUrl, params, function( data ) {
 538+ mw.getJSON( apiUrl, params, function( data ) {
481539 if ( !data || !data.query || !data.query.pages ) {
482540 mw.log(" No data? ")
483541 return;
484542 }
485543
486 - if (data.query.pages[-1]) {
 544+ if ( data.query.pages[-1] ) {
487545 // not found ? error
488546 }
489547 for ( var page_id in data.query.pages ) {
490548 var page = data.query.pages[ page_id ];
491 - if (! page.imageinfo ) {
 549+ if ( ! page.imageinfo ) {
492550 // not found? error
493551 } else {
494552 var imageInfo = page.imageinfo[0];
495 - setThumbnailCb(imageInfo);
 553+ setThumbnailCb( imageInfo );
496554 }
497555 }
498 - });
 556+ } );
499557 },
500558
501559
 560+ /**
 561+ * Convert entire metadata for this file into wikiText, which will then be posted to the file
 562+ * @return wikitext representing all metadata
 563+ */
502564 getWikiText: function() {
503565 var _this = this;
504566 wikiText = '';
505567
506568
507 - // http://commons.wikimedia.org/wiki/Template:Information
 569+ // http://commons.wikimedia.org / wiki / Template:Information
508570
509571 // can we be more slick and do this with maps, applys, joins?
510572 var information = {
@@ -518,16 +580,16 @@
519581
520582 // sanity check the descriptions -- do not have two in the same lang
521583 // all should be a known lang
522 - if (_this.descriptions.length === 0) {
 584+ if ( _this.descriptions.length === 0 ) {
523585 // ruh roh
524 - // we should not even allow them to press the button (?) but then what about the queue...
 586+ // we should not even allow them to press the button ( ? ) but then what about the queue...
525587 }
526 - $j.each(_this.descriptions, function(i, description) {
527 - information.description += descriptions.getWikiText();
528 - })
 588+ $j.each( _this.descriptions, function( i, desc ) {
 589+ information.description += desc.getWikiText();
 590+ } )
529591
530592 var info = '';
531 - for (var key in information) {
 593+ for ( var key in information ) {
532594 info += '|' + key + '=' + information[key] + "\n";
533595 }
534596
@@ -536,33 +598,39 @@
537599 wikiText += '{{Information\n' + info + '}}\n';
538600
539601 // wikiText += "=={int:license}==\n";
540 - // XXX get the real one -- usually dual license GFDL/cc-by-sa
 602+ // XXX get the real one -- usually dual license GFDL / cc - by - sa
541603 //wikiText += "{{cc-by-sa-3.0}}\n";
542 - // http://commons.wikimedia.org/wiki/Template:Information
 604+ // http://commons.wikimedia.org / wiki / Template:Information
543605
544606 return wikiText;
545607 },
546608
 609+ /**
 610+ * Check if we are ready to post wikitext
 611+ */
547612 isReady: function() {
548613 // somehow, all the various issues discovered with this upload should be present in a single place
549614 // where we can then check on
550615 // perhaps as simple as _this.issues or _this.agenda
551616 },
552617
 618+ /**
 619+ * Post wikitext as edited here, to the file
 620+ */
553621 submit: function() {
554622 var _this = this;
555623 // are we okay to submit?
556624 // check descriptions
557625
558 - // are we changing the name (moving the file?) if so, do that first, and the rest of this submission has to become
 626+ // are we changing the name ( moving the file? ) if so, do that first, and the rest of this submission has to become
559627 // a callback when that is completed?
560628
561 - // XXX check state of metadata for okayness (license selected, at least one desc, sane filename)
 629+ // XXX check state of metadata for okayness ( license selected, at least one desc, sane filename )
562630 var wikiText = _this.getWikiText();
563 - mw.log(wikiText);
 631+ mw.log( wikiText );
564632 // do some api call to edit the info
565633
566 - // api.php  ? action=edit & title=Talk:Main_Page & section=new &  summary=Hello%20World & text=Hello%20everyone! & watch &  basetimestamp=2008-03-20T17:26:39Z &  token=cecded1f35005d22904a35cc7b736e18%2B%5C
 634+ // api.php  ? action = edit & title = Talk:Main_Page & section = new &  summary = Hello%20World & text = Hello%20everyone! & watch &  basetimestamp = 2008 - 03 - 20T17:26:39Z &  token = cecded1f35005d22904a35cc7b736e18%2B%5C
567635 // caution this may result in a captcha response, which user will have to solve
568636 //
569637
@@ -572,8 +640,8 @@
573641 // we are presuming this File page is brand new, so let's not bother with the whole redirection deal. ('noredirect')
574642
575643 /*
576 - Note: In this example, all parameters are passed in a GET request just for the sake of simplicity. However, action=move requires POST requests; GET requests will cause an error. Moving Main Pgae (sic) and its talk page to Main Page, without creating a redirect
577 - api.php  ? action=move & from=Main%20Pgae & to=Main%20Page &  reason=Oops,%20misspelling & movetalk & noredirect &  token=58b54e0bab4a1d3fd3f7653af38e75cb%2B\
 644+ Note: In this example, all parameters are passed in a GET request just for the sake of simplicity. However, action = move requires POST requests; GET requests will cause an error. Moving Main Pgae ( sic ) and its talk page to Main Page, without creating a redirect
 645+ api.php  ? action = move & from = Main%20Pgae & to = Main%20Page &  reason = Oops,%20misspelling & movetalk & noredirect &  token = 58b54e0bab4a1d3fd3f7653af38e75cb%2B\
578646 */
579647
580648
@@ -581,6 +649,25 @@
582650 };
583651
584652
 653+
 654+/**
 655+ * Object that reperesents the entire multi-step Upload Wizard
 656+ */
 657+mw.UploadWizard = function() {
 658+
 659+ this.uploadHandlerClass = mw.getConfig('uploadHandlerClass') || this.getUploadHandlerClass();
 660+ this.isCompleted = false;
 661+
 662+ this.uploads = [];
 663+ // leading underline for privacy. DO NOT TAMPER.
 664+ this._uploadsQueued = [];
 665+ this._uploadsInProgress = [];
 666+ this._uploadsCompleted = [];
 667+
 668+ this.uploadsBeginTime = null;
 669+
 670+};
 671+
585672 mw.UploadWizard.prototype = {
586673 maxUploads: 10, // XXX get this from config
587674 maxSimultaneousUploads: 2, // XXX get this from config
@@ -599,30 +686,33 @@
600687 'NullUploadHandler'
601688 ],
602689
603 - // let's figure out exactly what we can use.
604 - //
 690+ /*
 691+ * We can use various UploadHandlers based on the browser's capabilities. Let's pick one.
 692+ * For example, the ApiUploadHandler should work just about everywhere, but XhrUploadHandler
 693+ * allows for more fine-grained upload progress
 694+ * @return valid JS upload handler class constructor function
 695+ */
605696 getUploadHandlerClass: function() {
 697+ // return mw.MockUploadHandler;
 698+ return mw.ApiUploadHandler;
 699+ /*
606700 var _this = this;
607 - for (var i = 0; i < uploadHandlers.length; i++) {
 701+ for ( var i = 0; i < uploadHandlers.length; i++ ) {
608702 var klass = mw[uploadHandlers[i]];
609 - if (klass != undefined && klass.canRun(this.config)) {
 703+ if ( klass != undefined && klass.canRun( this.config )) {
610704 return klass;
611705 }
612706 }
613707 // this should never happen; NullUploadHandler should always work
614708 return null;
 709+ */
615710 },
616 - */
617 -
618 - // later we will do some testing to see if they can support more advanced UploadHandlers, like
619 - // an XHR based one or Firefogg
620 - getUploadHandlerClass: function() {
621 - // return mw.MockUploadHandler;
622 - return mw.ApiUploadHandler;
623 - },
624 -
625 - // create the basic interface to make an upload in this div
626 - createInterface: function(div) {
 711+
 712+ /**
 713+ * create the basic interface to make an upload in this div
 714+ * @param div The div in the DOM to put all of this into.
 715+ */
 716+ createInterface: function( div ) {
627717 var _this = this;
628718 div.innerHTML =
629719
@@ -672,7 +762,7 @@
673763 // Create global progress bar
674764 $j( '#mwe-upwiz-progress-bar' ).progressbar({
675765 value: 0
676 - });
 766+ } );
677767
678768 // add one to start
679769 _this.addUpload();
@@ -681,29 +771,38 @@
682772 _this.moveToTab('file');
683773 },
684774
685 - moveToTab: function(selectedTabName) {
 775+ /**
 776+ * Advance one "step" in the wizard interface.
 777+ * @param selectedTabName
 778+ */
 779+ moveToTab: function( selectedTabName ) {
686780 var _this = this;
687 - for (var i=0; i < _this.tabs.length; i++) {
 781+ for ( var i = 0; i < _this.tabs.length; i++ ) {
688782 tabName = _this.tabs[i];
689 - var tabDiv = $j('#mwe-upwiz-tabdiv-' + tabName);
690 - var tab = $j('#mwe-upwiz-tab-' + tabName);
691 - if (selectedTabName == tabName) {
 783+ var tabDiv = $j( '#mwe-upwiz-tabdiv-' + tabName );
 784+ var tab = $j( '#mwe-upwiz-tab-' + tabName );
 785+ if ( selectedTabName == tabName ) {
692786 tabDiv.show();
693 - tab.addClass('mwe-upwiz-tab-highlight');
 787+ tab.addClass( 'mwe-upwiz-tab-highlight' );
694788 } else {
695789 tabDiv.hide();
696 - tab.removeClass('mwe-upwiz-tab-highlight');
 790+ tab.removeClass( 'mwe-upwiz-tab-highlight' );
697791 }
698792 }
699793 // XXX possibly select appropriate form field to begin work
700794 },
701795
702 - // add an Upload, with controls.
703 - // XXX study what Mdale is doing to create this file form controls... he has full control over CSS etc and the browsing button.
 796+ /**
 797+ * add an Upload
 798+ * we create the upload interface, a handler to transport it to the server,
 799+ * and UI for the upload itself and the "metadata" at the second step of the wizard.
 800+ * Finally stuff it into an array of uploads.
 801+ * @return boolean success
 802+ */
704803 addUpload: function() {
705804 var _this = this;
706805 var idx = _this.uploads.length; // or?
707 - if (idx == _this.maxUploads) {
 806+ if ( idx == _this.maxUploads ) {
708807 return false;
709808 }
710809
@@ -713,45 +812,45 @@
714813
715814 // API
716815 // XXX hardcoded for now. Maybe passed through config or guessed at here.
717 - // upload.api = new mw.UploadApiProcessor(function(result) { _this.uploadCompleted);
 816+ // upload.api = new mw.UploadApiProcessor( function( result ) { _this.uploadCompleted );
718817
719818
720819 // UI
721 - // originalFilename is the basename of the file on our file system. This is what we really wanted (probably).
 820+ // originalFilename is the basename of the file on our file system. This is what we really wanted ( probably ).
722821 // the system will upload with a temporary filename and we'll get that back from the API return when we upload
723822 var filenameAcceptedCb = function() {
724823 _this.updateFileCounts();
725824 };
726 - var ui = new mw.UploadWizardUploadInterface(filenameAcceptedCb);
727 - ui.removeCtrl = $j('<a title="' + gM( 'mwe-upwiz-remove-upload')
728 - + '" href="#" class="mwe-upwiz-remove">x</a>')
729 - .click( function() { _this.removeUpload(upload) } )
730 - .get(0);
731 - $j(ui.div).append(ui.removeCtrl);
 825+ var ui = new mw.UploadWizardUploadInterface( filenameAcceptedCb );
 826+ ui.removeCtrl = $j( '<a title="' + gM( 'mwe-upwiz-remove-upload' )
 827+ + '" href="#" class="mwe-upwiz-remove">x</a>' )
 828+ .click( function() { _this.removeUpload( upload ) } )
 829+ .get( 0 );
 830+ $j( ui.div ).append( ui.removeCtrl );
732831
733832 upload.ui = ui;
734833 // handler -- usually ApiUploadHandler
735 - upload.handler = new _this.uploadHandlerClass(upload.ui);
 834+ upload.handler = new _this.uploadHandlerClass( upload.ui );
736835
737836 // this is for UI only...
738 - upload.handler.addProgressCb( function(fraction) { _this.uploadProgress(upload, fraction) } );
 837+ upload.handler.addProgressCb( function( fraction ) { _this.uploadProgress( upload, fraction ) } );
739838
740839 // this is only the UI one, so is the result even going to be there?
741 - upload.handler.addCompletedCb( function(result) { _this.uploadCompleted(upload, result) } );
 840+ upload.handler.addCompletedCb( function( result ) { _this.uploadCompleted( upload, result ) } );
742841
743842 // not sure about this...UI only?
744843 // this will tell us that at least one of our uploads has had an error -- may change messaging,
745844 // like, please fix below
746 - upload.handler.addErrorCb( function(error) { _this.uploadError(upload, error) } );
 845+ upload.handler.addErrorCb( function( error ) { _this.uploadError( upload, error ) } );
747846
748847 // metadata
749 - upload.metadata = new mw.UploadWizardMetadata($j('#mwe-upwiz-metadata-files'));
 848+ upload.metadata = new mw.UploadWizardMetadata( $j( '#mwe-upwiz-metadata-files' ));
750849
751850
752851
753 - _this.uploads.push(upload);
 852+ _this.uploads.push( upload );
754853
755 - $j("#mwe-upwiz-files").append(upload.ui.div);
 854+ $j( "#mwe-upwiz-files" ).append( upload.ui.div );
756855
757856
758857
@@ -760,135 +859,165 @@
761860
762861 // update the uploadUi to add files - we may be over limit
763862 _this.updateFileCounts();
764 -
 863+ return true;
765864 },
766865
767 - /* Remove an upload from our array of uploads, and the HTML UI
768 - We can remove the HTML UI directly, as jquery will just get the parent.
769 - We need to grep through the array of uploads, since we don't know the current index. */
770 - removeUpload: function(upload) {
 866+ /**
 867+ * Remove an upload from our array of uploads, and the HTML UI
 868+ * We can remove the HTML UI directly, as jquery will just get the parent.
 869+ * We need to grep through the array of uploads, since we don't know the current index.
 870+ *
 871+ * @param upload
 872+ */
 873+ removeUpload: function( upload ) {
771874 var _this = this;
772 - $j(upload.ui.div).remove();
773 - $j(upload.metadata.div).remove();
774 - mw.UploadWizardUtil.removeItem(_this.uploads, upload);
 875+ $j( upload.ui.div ).remove();
 876+ $j( upload.metadata.div ).remove();
 877+ mw.UploadWizardUtil.removeItem( _this.uploads, upload );
775878 _this.updateFileCounts();
776879 },
777880
778 - // using a second array to iterate, because we will be splicing the main one, _this.uploads
 881+ /**
 882+ * This is useful to clean out unused upload file inputs if the user hits GO.
 883+ * We are using a second array to iterate, because we will be splicing the main one, _this.uploads
 884+ */
779885 removeEmptyUploads: function() {
780886 var _this = this;
781887 var toRemove = [];
782 - for (var i = 0; i < _this.uploads.length; i++) {
783 - if (_this.uploads[i].ui.fileInputCtrl.value == "") {
784 - toRemove.push(_this.uploads[i]);
 888+ for ( var i = 0; i < _this.uploads.length; i++ ) {
 889+ if ( _this.uploads[i].ui.fileInputCtrl.value == "" ) {
 890+ toRemove.push( _this.uploads[i] );
785891 }
786892 };
787 - for (var i = 0; i < toRemove.length; i++) {
788 - _this.removeUpload(toRemove[i]);
 893+ for ( var i = 0; i < toRemove.length; i++ ) {
 894+ _this.removeUpload( toRemove[i] );
789895 }
790896 },
791897
 898+ /**
 899+ * Kick off the upload processes.
 900+ * Does some precalculations, changes the interface to be less mutable, moves the uploads to a queue,
 901+ * and kicks off a thread which will take from the queue.
 902+ */
792903 startUploads: function() {
793904 var _this = this;
794905 _this.removeEmptyUploads();
795906 // remove the upload button, and the add file button
796 - $j('#mwe-upwiz-upload-ctrl').hide();
797 - $j('#mwe-upwiz-add-file').hide();
 907+ $j( '#mwe-upwiz-upload-ctrl' ).hide();
 908+ $j( '#mwe-upwiz-add-file' ).hide();
798909
799910 // remove ability to change files
800911 // ideally also hide the "button"... but then we require styleable file input CSS trickery
801912 // although, we COULD do this just for files already in progress...
802913
803914 // XXX we just want to VISUALLY lock it in -- disabling this seems to remove it from form post
804 - // $j('.mwe-upwiz-file').attr('disabled', 'disabled');
 915+ // $j( '.mwe-upwiz-file' ).attr( 'disabled', 'disabled' );
805916
806917 // add the upload progress bar, with ETA
807918 // add in the upload count
808 - $j('#mwe-upwiz-progress').show();
 919+ $j( '#mwe-upwiz-progress' ).show();
809920
810 - _this.uploadsBeginTime = (new Date()).getTime();
 921+ _this.uploadsBeginTime = ( new Date() ).getTime();
811922
812 - var canGetFileSize = (_this.uploadHandlerClass.prototype.getFileSize !== undefined);
 923+ var canGetFileSize = ( _this.uploadHandlerClass.prototype.getFileSize !== undefined );
813924
814925 // queue the uploads
815926 _this.totalWeight = 0;
816 - for (var i = 0; i < _this.uploads.length; i++) {
 927+ for ( var i = 0; i < _this.uploads.length; i++ ) {
817928 var upload = _this.uploads[i];
818929
819930 // we may want to do something clever here to detect
820931 // whether this is a real or dummy weight
821 - if (canGetFileSize) {
 932+ if ( canGetFileSize ) {
822933 upload.weight = upload.getFileSize();
823934 } else {
824935 upload.weight = 1;
825936 }
826937 _this.totalWeight += upload.weight;
827938
828 - _this._uploadsQueued.push(upload);
 939+ _this._uploadsQueued.push( upload );
829940 }
830941 setTimeout( function () { _this._startUploadsQueued(); }, 0 );
831942 },
832943
833 - // making this another thread of execution, because we want to avoid any race condition
834 - // this way, this is the only "thread" that can start uploads
835 - // it may miss a newly completed upload but it will get it eventually
 944+ /**
 945+ * Uploads must be 'queued' to be considered for uploading
 946+ * making this another thread of execution, because we want to avoid any race condition
 947+ * this way, this is the only "thread" that can start uploads
 948+ * it may miss a newly completed upload but it will get it eventually
 949+ *
 950+ */
836951 _startUploadsQueued: function() {
837952 var _this = this;
838 - var uploadsToStart = Math.min(_this.maxSimultaneousUploads - _this._uploadsInProgress.length, _this._uploadsQueued.length);
839 - mw.log("_startUploadsQueued: should start " + uploadsToStart + " uploads");
840 - while (uploadsToStart--) {
 953+ var uploadsToStart = Math.min( _this.maxSimultaneousUploads - _this._uploadsInProgress.length,
 954+ _this._uploadsQueued.length );
 955+ mw.log( "_startUploadsQueued: should start " + uploadsToStart + " uploads" );
 956+ while ( uploadsToStart-- ) {
841957 var upload = _this._uploadsQueued.shift();
842 - _this._uploadsInProgress.push(upload);
 958+ _this._uploadsInProgress.push( upload );
843959 upload.handler.start();
844960 }
845 - if (_this._uploadsQueued.length) {
 961+ if ( _this._uploadsQueued.length ) {
846962 setTimeout( function () { _this._startUploadsQueued(); }, 1000 );
847963 }
848964 },
849965
850966
851 - // could be a spinning loop by itself, but this is annoying to debug
852 - // and then we'd have to be careful to note the state-transition to completed once and only once. Race conditions.
 967+ /**
 968+ * Show overall progress for the entire UploadWizard
 969+ * The current design doesn't have individual progress bars, just one giant one.
 970+ * We did some tricky calculations in startUploads to try to weight each individual file's progress against
 971+ * the overall progress.
 972+ */
853973 showProgress: function() {
854974 var _this = this;
855 - if (_this.isCompleted) {
 975+ if ( _this.isCompleted ) {
856976 return;
857977 }
858978
859 - //var updateFileCounts = false;
860979 var fraction = 0;
861 - for (var i = 0; i < _this.uploads.length; i++) {
 980+ for ( var i = 0; i < _this.uploads.length; i++ ) {
862981 var upload = _this.uploads[i];
863 - mw.log("progress of " + upload.ui.fileInputCtrl.value + " = " + upload.progress);
864 - fraction += upload.progress * (upload.weight / _this.totalWeight);
 982+ mw.log( "progress of " + upload.ui.fileInputCtrl.value + " = " + upload.progress );
 983+ fraction += upload.progress * ( upload.weight / _this.totalWeight );
865984 }
866 - _this.showProgressBar(fraction);
 985+ _this.showProgressBar( fraction );
867986
868 - var remainingTime = _this.getRemainingTime(_this.uploadsBeginTime, fraction);
869 - if (remainingTime !== null) {
870 - _this.showRemainingTime(remainingTime);
 987+ var remainingTime = _this.getRemainingTime( _this.uploadsBeginTime, fraction );
 988+ if ( remainingTime !== null ) {
 989+ _this.showRemainingTime( remainingTime );
871990 }
872991 },
873992
874 - // show the progress bar
875 - showProgressBar: function(fraction) {
 993+ /**
 994+ * Show the progress bar for the entire Upload Wizard.
 995+ * @param fraction fraction completed (float between 0 and 1)
 996+ */
 997+ showProgressBar: function( fraction ) {
876998 $j( '#mwe-upwiz-progress-bar' ).progressbar( 'value', parseInt( fraction * 100 ) );
877999 },
8781000
879 - // show remaining time for all the uploads
880 - // remainingTime is in milliseconds
881 - // XXX should be localized - x hours, x minutes, x seconds
882 - showRemainingTime: function(remainingTime) {
 1001+ /**
 1002+ * Show remaining time for all the uploads
 1003+ * XXX should be localized - x hours, x minutes, x seconds
 1004+ * @param remainingTime estimated time remaining in milliseconds
 1005+ */
 1006+ showRemainingTime: function( remainingTime ) {
8831007 $j( '#mwe-upwiz-etr' ).html( gM( 'mwe-upwiz-remaining', mw.seconds2npt(parseInt(remainingTime / 1000)) ) );
8841008 },
8851009
8861010
887 - // XXX should be refactored with the very similar code in mw.UploadInterface.js:updateProgress
888 - // returns time in whatever units getTime() returns; presumed milliseconds
889 - getRemainingTime: function (beginTime, fractionCompleted) {
 1011+ /**
 1012+ * Calculate remaining time for all uploads to complete.
 1013+ *
 1014+ * @param beginTime time in whatever unit getTime returns, presume epoch milliseconds
 1015+ * @param fractionCompleted fraction completed
 1016+ * @return time in whatever units getTime() returns; presumed milliseconds
 1017+ */
 1018+ getRemainingTime: function ( beginTime, fractionCompleted ) {
8901019 if ( beginTime ) {
8911020 var elapsedTime = ( new Date() ).getTime() - beginTime;
892 - if (fractionCompleted > 0.0 && elapsedTime > 0) { // or some other minimums for good data
 1021+ if ( fractionCompleted > 0.0 && elapsedTime > 0 ) { // or some other minimums for good data
8931022 var rate = fractionCompleted / elapsedTime;
8941023 return parseInt( ( 1.0 - fractionCompleted ) / rate );
8951024 }
@@ -896,35 +1025,45 @@
8971026 return null;
8981027 },
8991028
900 - // okay we are in a confusing state here -- are we asking for progress to be stored in the uploadhandler for our perusal or
901 - // to be explicitly forwarded to us
902 - uploadProgress: function(upload, progress) {
 1029+ /**
 1030+ * Record the progress of an individual upload
 1031+ * okay we are in a confusing state here -- are we asking for progress to be stored in the uploadhandler for our perusal or
 1032+ * to be explicitly forwarded to us
 1033+ * @param upload an Upload object
 1034+ * @param progress fraction of progress (float between 0 and 1)
 1035+ */
 1036+ uploadProgress: function( upload, progress ) {
9031037 mw.log("upload progress is " + progress);
9041038 var _this = this;
9051039 upload.progress = progress;
9061040 _this.showProgress();
9071041 },
9081042
909 - uploadCompleted: function(upload, result) {
 1043+ /**
 1044+ * To be executed when an individual upload finishes. Processes the result and updates step 2's metadata
 1045+ * @param upload an Upload object
 1046+ * @param result the API result in parsed JSON form
 1047+ */
 1048+ uploadCompleted: function( upload, result ) {
9101049 var _this = this;
911 - _this._uploadsCompleted.push(upload);
912 - mw.UploadWizardUtil.removeItem(_this._uploadsInProgress, upload);
 1050+ _this._uploadsCompleted.push( upload );
 1051+ mw.UploadWizardUtil.removeItem( _this._uploadsInProgress, upload );
9131052
9141053 if ( result.upload && result.upload.imageinfo && result.upload.imageinfo.descriptionurl ) {
9151054 // success
9161055 setTimeout( function() {
917 - upload.metadata.populateFromResult(result); }, 0 );
 1056+ upload.metadata.populateFromResult( result ); }, 0 );
9181057
919 - } else if (result.upload && result.upload.sessionkey) {
920 - // there was a warning-type error which prevented it from adding the result to the db
921 - if (result.upload.warnings.duplicate) {
 1058+ } else if ( result.upload && result.upload.sessionkey ) {
 1059+ // there was a warning - type error which prevented it from adding the result to the db
 1060+ if ( result.upload.warnings.duplicate ) {
9221061 var duplicates = result.upload.warnings.duplicate;
923 - _this.metadata.errorDuplicate(result.upload.sessionkey, duplicates);
 1062+ _this.metadata.errorDuplicate( result.upload.sessionkey, duplicates );
9241063 }
9251064
9261065 // XXX namespace collision
9271066 // and other errors that result in a stash
928 - } else if (0 /* actual failure */) {
 1067+ } else if ( 0 /* actual failure */ ) {
9291068 // we may want to tag or otherwise queue it as an upload to retry
9301069 }
9311070
@@ -932,55 +1071,63 @@
9331072 },
9341073
9351074
936 - // depending on number of file upoads, change link text (and/or disable it)
937 - // change button disabled/enabled
 1075+ /**
 1076+ * Occurs whenever we need to update the interface based on how many files are there or have completed
 1077+ * Also detects if all uploads have completed and kicks off the process that eventually gets us to Step 2.
 1078+ */
9381079 updateFileCounts: function() {
939 - mw.log("update counts");
 1080+ mw.log( "update counts" );
9401081 var _this = this;
941 - $j('#mwe-upwiz-add-file').html(gM('mwe-upwiz-add-file-' + (_this.uploads.length === 0 ? '0' : 'n')));
942 - if (_this.uploads.length < _this.maxUploads) {
943 - $j('#mwe-upwiz-add-file').removeAttr('disabled');
 1082+ $j( '#mwe-upwiz-add-file' ).html( gM( 'mwe-upwiz-add-file-' + ( _this.uploads.length === 0 ? '0' : 'n' )) );
 1083+ if ( _this.uploads.length < _this.maxUploads ) {
 1084+ $j( '#mwe-upwiz-add-file' ).removeAttr( 'disabled' );
9441085 } else {
945 - $j('#mwe-upwiz-add-file').attr('disabled', true);
 1086+ $j( '#mwe-upwiz-add-file' ).attr( 'disabled', true );
9461087 }
9471088
9481089 var hasFile;
949 - for (var i = 0; i < _this.uploads.length; i++) {
 1090+ for ( var i = 0; i < _this.uploads.length; i++ ) {
9501091 var upload = _this.uploads[i];
951 - if (upload.ui.fileInputCtrl.value != "") {
 1092+ if ( upload.ui.fileInputCtrl.value != "" ) {
9521093 hasFile = true;
9531094 }
9541095 }
955 - if (hasFile) {
956 - $j('#mwe-upwiz-upload-ctrl').removeAttr('disabled');
 1096+ if ( hasFile ) {
 1097+ $j( '#mwe-upwiz-upload-ctrl' ).removeAttr( 'disabled' );
9571098 } else {
958 - $j('#mwe-upwiz-upload-ctrl').attr('disabled', 'disabled');
 1099+ $j( '#mwe-upwiz-upload-ctrl' ).attr( 'disabled', 'disabled' );
9591100 }
9601101
9611102
962 - $j('#mwe-upwiz-count').html( gM('mwe-upwiz-upload-count', [ _this._uploadsCompleted.length, _this.uploads.length ]) );
 1103+ $j( '#mwe-upwiz-count' ).html( gM( 'mwe-upwiz-upload-count', [ _this._uploadsCompleted.length, _this.uploads.length ] ) );
9631104
964 - if (_this.uploads.length > 0 && _this._uploadsCompleted.length == _this.uploads.length) {
 1105+ if ( _this.uploads.length > 0 && _this._uploadsCompleted.length == _this.uploads.length ) {
9651106 // is this enough to stop the progress monitor?
9661107 _this.isCompleted = true;
9671108 // set progress to 100%
968 - _this.showProgressBar(1);
969 - _this.showRemainingTime(0);
 1109+ _this.showProgressBar( 1 );
 1110+ _this.showRemainingTime( 0 );
9701111
9711112 // XXX then should make the progress bar not have the animated lines when done. Solid blue, or fade away or something.
9721113 // likewise, the remaining time should disappear, fadeout maybe.
9731114
9741115 // do some sort of "all done" thing for the UI - advance to next tab maybe.
975 - _this.moveToTab('metadata');
 1116+ _this.moveToTab( 'metadata' );
9761117 }
9771118
9781119 },
9791120
9801121
 1122+ /**
 1123+ *
 1124+ */
9811125 pause: function() {
9821126
9831127 },
9841128
 1129+ /**
 1130+ *
 1131+ */
9851132 stop: function() {
9861133
9871134 },
@@ -989,10 +1136,16 @@
9901137 // entire METADATA TAB
9911138 //
9921139
 1140+ /**
 1141+ *
 1142+ */
9931143 createMetadata: function() {
9941144
9951145 },
9961146
 1147+ /**
 1148+ *
 1149+ */
9971150 submitMetadata: function() {
9981151
9991152 },
@@ -1001,13 +1154,22 @@
10021155
10031156 };
10041157
1005 -// XXX refactor? or, reconsider approach -- this is an awful hack in some ways
1006 -// The jQuery way would be to query the DOM for objects, not to keep a separate array hanging around
 1158+/**
 1159+ * Miscellaneous utilities
 1160+ */
10071161 mw.UploadWizardUtil = {
1008 - removeItem: function(items, item) {
1009 - for (var i = 0; i < items.length; i++) {
1010 - if (items[i] === item) {
1011 - items.splice(i, 1);
 1162+ /**
 1163+ * remove an item from an array. Tests for === identity to remove the item
 1164+ * XXX the entire rationale for this file may be wrong.
 1165+ * XXX The jQuery way would be to query the DOM for objects, not to keep a separate array hanging around
 1166+ * @param items the array where we want to remove an item
 1167+ * @param item the item to remove
 1168+ */
 1169+ removeItem: function( items, item ) {
 1170+ for ( var i = 0; i < items.length; i++ ) {
 1171+ if ( items[i] === item ) {
 1172+ items.splice( i, 1 );
 1173+ break;
10121174 }
10131175 }
10141176 }
Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.ApiUploadHandler.js
@@ -6,7 +6,11 @@
77 // n.b. if there are message strings, or any assumption about HTML structure of the form.
88 // then we probably did it wrong
99
10 -mw.ApiUploadHandler = function(ui) {
 10+/**
 11+ * Represents an object which configures a form to upload its files via an iframe talking to the MediaWiki API.
 12+ * @param an UploadInterface object, which contains a .form property which points to a real HTML form in the DOM
 13+ */
 14+mw.ApiUploadHandler = function( ui ) {
1115 var _this = this;
1216
1317 _this.ui = ui;
@@ -23,110 +27,145 @@
2428 // can also use Xhr Binary depending on config
2529 _this.transport = new mw.IframeTransport(
2630 _this.ui.form,
27 - function(fraction){ _this.progress(fraction) },
28 - function(result) { _this.completed(result) }
 31+ function( fraction ){ _this.progress( fraction ) },
 32+ function( result ) { _this.completed( result ) }
2933 );
3034
3135 };
3236
3337 mw.ApiUploadHandler.prototype = {
34 - addProgressCb: function(fn) {
 38+ /**
 39+ * Allow other parties to register interest in how we are progressing
 40+ * @param callback which accepts a float between 0 and 1 as our current progress
 41+ */
 42+ addProgressCb: function( fn ) {
3543 var _this = this;
36 - _this.progressCallbacks.push(function(progress) { fn(progress) });
 44+ _this.progressCallbacks.push( function( progress ) { fn( progress ) } );
3745 },
3846
39 -
40 - addCompletedCb: function(f) {
 47+ /**
 48+ * Allow other parties to register interest in when we finish uploading
 49+ * @param callback
 50+ */
 51+ addCompletedCb: function( f ) {
4152 var _this = this;
42 - _this.completedCallbacks.push(f);
 53+ _this.completedCallbacks.push( f );
4354 },
4455
45 - addErrorCb: function(f) {
 56+ /**
 57+ * Allow other parties to register interest in when we have an error
 58+ * @param callback
 59+ */
 60+ addErrorCb: function( f ) {
4661 var _this = this;
47 - _this.errorCallbacks.push(f);
 62+ _this.errorCallbacks.push( f );
4863 },
4964
 65+ /**
 66+ * Configure an HTML form so that it will submit its files to our transport (an iframe)
 67+ * with proper params for the API
 68+ * @param callback
 69+ */
5070 configureForm: function() {
51 - var apiUrl = mw.getLocalApiUrl(); // XXX or? throw new Error("configuration", "no API url");
52 - if (! (mw.getConfig('token') ) ) {
53 - throw new Error("configuration", "no edit token");
 71+ var apiUrl = mw.getLocalApiUrl(); // XXX or? throw new Error( "configuration", "no API url" );
 72+ if ( ! ( mw.getConfig( 'token' ) ) ) {
 73+ throw new Error( "configuration", "no edit token" );
5474 }
5575
5676 var _this = this;
57 - mw.log("configuring form for Upload API");
 77+ mw.log( "configuring form for Upload API" );
5878
5979 // Set the form action
6080 try {
61 - $j(_this.ui.form)
62 - .attr('action', apiUrl)
63 - .attr('method', 'POST')
64 - .attr('enctype', 'multipart/form-data');
 81+ $j( _this.ui.form )
 82+ .attr( 'action', apiUrl )
 83+ .attr( 'method', 'POST' )
 84+ .attr( 'enctype', 'multipart/form-data' );
6585 } catch ( e ) {
66 - alert("oops, form modification didn't work in ApiUploadHandler");
67 - mw.log("IE for some reason error's out when you change the action");
 86+ alert( "oops, form modification didn't work in ApiUploadHandler" );
 87+ mw.log( "IE for some reason error's out when you change the action" );
6888 // well, if IE fucks this up perhaps we should do something to make sure it writes correctly
6989 // from the outset?
7090 }
7191
72 - _this.addFormInputIfMissing('token', mw.getConfig('token'));
73 - _this.addFormInputIfMissing('action', 'upload');
74 - _this.addFormInputIfMissing('format', 'jsonfm');
 92+ _this.addFormInputIfMissing( 'token', mw.getConfig( 'token' ));
 93+ _this.addFormInputIfMissing( 'action', 'upload' );
 94+ _this.addFormInputIfMissing( 'format', 'jsonfm' );
7595
7696 // XXX only for testing, so it stops complaining about dupes
77 - _this.addFormInputIfMissing('ignorewarnings', '1');
 97+ if ( mw.getConfig( 'debug' )) {
 98+ _this.addFormInputIfMissing( 'ignorewarnings', '1' );
 99+ }
78100 },
79101
80 - addFormInputIfMissing: function(name, value) {
 102+ /**
 103+ * Add a hidden input to a form if it was not already there.
 104+ * @param name the name of the input
 105+ * @param value the value of the input
 106+ */
 107+ addFormInputIfMissing: function( name, value ) {
81108 var _this = this;
82 - var $jForm = $j(_this.ui.form);
 109+ var $jForm = $j( _this.ui.form );
83110 if ( $jForm.find( "[name='" + name + "']" ).length == 0 ) {
84111 $jForm.append(
85 - $j('<input />')
86 - .attr({
 112+ $j( '<input />' )
 113+ .attr( {
87114 'type': "hidden",
88115 'name' : name,
89116 'value' : value
90 - })
 117+ } )
91118 );
92119 }
93120 },
94121
 122+ /**
 123+ * Kick off the upload!
 124+ */
95125 start: function() {
96126 var _this = this;
97 - mw.log("api: upload start!")
98 - _this.beginTime = (new Date()).getTime();
 127+ mw.log( "api: upload start!" );
 128+ _this.beginTime = ( new Date() ).getTime();
99129 _this.ui.start();
100130 _this.ui.busy();
101 - $j(this.ui.form).submit();
 131+ $j( this.ui.form ).submit();
102132 },
103133
104 - progress: function(fraction) {
105 - mw.log("api: upload progress!")
 134+ /**
 135+ * Central dispatch function for every other object interested in our progress
 136+ * @param fraction float between 0 and 1, representing progress
 137+ */
 138+ progress: function( fraction ) {
 139+ mw.log( "api: upload progress!" );
106140 var _this = this;
107 - _this.ui.progress(fraction);
108 - for (var i = 0; i < _this.progressCallbacks.length; i++) {
109 - _this.progressCallbacks[i](fraction);
 141+ _this.ui.progress( fraction );
 142+ for ( var i = 0; i < _this.progressCallbacks.length; i++ ) {
 143+ _this.progressCallbacks[i]( fraction );
110144 }
111145 },
112146
113 - // this is not quite the right place for all this code
114 - // perhaps should be abstract to any uploadHandler, or not
115 - // in this at all
116 - completed: function(result) {
117 - mw.log("api: upload completed!")
 147+ /**
 148+ * Central dispatch function for everyone else interested if we've completed
 149+ * @param result javascript object representing MediaWiki API result.
 150+ */
 151+ completed: function( result ) {
 152+ mw.log( "api: upload completed!" );
118153 var _this = this;
119154 _this.ui.completed();
120 - for (var i = 0; i < _this.completedCallbacks.length; i++) {
121 - _this.completedCallbacks[i](result);
 155+ for ( var i = 0; i < _this.completedCallbacks.length; i++ ) {
 156+ _this.completedCallbacks[i]( result );
122157 }
123158 },
124159
125 - error: function(error) {
126 - mw.log("api: error!");
 160+ /**
 161+ * Central dispatch function for everyone else interested if we've had an error
 162+ * @param error the error
 163+ */
 164+ error: function( error ) {
 165+ mw.log( "api: error!" );
127166 var _this = this;
128 - _this.ui.error(error);
129 - for (var i = 0; i < _this.errorCallbacks.length; i++) {
130 - _this.errorCallbacks[i](error);
 167+ _this.ui.error( error );
 168+ for ( var i = 0; i < _this.errorCallbacks.length; i++ ) {
 169+ _this.errorCallbacks[i]( error );
131170 }
132171 }
133172 };
Index: branches/js2-work/phase3/js/mwEmbed/modules/UploadWizard/mw.IframeTransport.js
@@ -1,4 +1,12 @@
2 -mw.IframeTransport = function(form, progressCb, completedCb) {
 2+/**
 3+ * Represents a "transport" for files to upload; in this case an iframe.
 4+ * The iframe is made to be the target of a form so that the existing page does not reload, even though it's a POST.
 5+ * @param form an HTML form
 6+ * @param progressCb callback to execute when we've started. (does not do float here because iframes can't
 7+ * monitor fractional progress).
 8+ * @param completedCb callback to execute when we've finished the upload
 9+ */
 10+mw.IframeTransport = function( form, progressCb, completedCb ) {
311 var _this = this;
412
513 _this.form = form;
@@ -7,47 +15,51 @@
816
917 _this.iframeId = 'f_' + ( $j( 'iframe' ).length + 1 );
1018
11 - //IE only works if you "create element with the name" (not jquery style)
 19+ //IE only works if you "create element with the name" ( not jquery style )
1220 var iframe;
1321 try {
1422 iframe = document.createElement( '<iframe name="' + _this.iframeId + '">' );
15 - } catch (ex) {
16 - iframe = document.createElement('iframe');
 23+ } catch ( ex ) {
 24+ iframe = document.createElement( 'iframe' );
1725 }
1826
1927 // we configure form on load, because the first time it loads, it's blank
2028 // then we configure it to deal with an API submission
2129 $j( iframe )
22 - .attr({ 'src' : 'javascript:false;',
23 - 'id' : _this.iframeId,
24 - 'name' : _this.iframeId })
25 - .load(function() { _this.configureForm() })
26 - .css('display', 'none');
 30+ .attr( { 'src' : 'javascript:false;',
 31+ 'id' : _this.iframeId,
 32+ 'name' : _this.iframeId } )
 33+ .load( function() { _this.configureForm() } )
 34+ .css( 'display', 'none' );
2735
2836 $j( "body" ).append( iframe );
2937 };
3038
3139 mw.IframeTransport.prototype = {
 40+ /**
 41+ * Configure the form we have so that it submits to the iframe
 42+ * Ensure callback on completion of upload
 43+ */
3244 configureForm: function() {
33 - mw.log("configuring form for iframe transport");
 45+ mw.log( "configuring form for iframe transport" );
3446 var _this = this;
3547 // Set the form target to the iframe
36 - var $jForm = $j(_this.form);
 48+ var $jForm = $j( _this.form );
3749 $jForm.attr( 'target', _this.iframeId );
3850
3951 // attach an additional handler to the form, so, when submitted, it starts showing the progress
4052 // XXX this is lame .. there should be a generic way to indicate busy status...
4153 $jForm.submit( function() {
42 - mw.log("submitting to iframe...");
43 - _this.progressCb(1.0);
 54+ mw.log( "submitting to iframe..." );
 55+ _this.progressCb( 1.0 );
4456 return true;
4557 } );
4658
4759 // Set up the completion callback
4860 $j( '#' + _this.iframeId ).load( function() {
49 - mw.log("received result in iframe");
 61+ mw.log( "received result in iframe" );
5062 _this.processIframeResult( $j( this ).get( 0 ) );
51 - });
 63+ } );
5264 },
5365
5466 /**
@@ -61,13 +73,13 @@
6274 var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document;
6375 // Fix for Opera 9.26
6476 if ( doc.readyState && doc.readyState != 'complete' ) {
65 - mw.log("not complete");
 77+ mw.log( "not complete" );
6678 return;
6779 }
6880
6981 // Fix for Opera 9.64
7082 if ( doc.body && doc.body.innerHTML == "false" ) {
71 - mw.log("no innerhtml");
 83+ mw.log( "no innerhtml" );
7284 return;
7385 }
7486 var response;
@@ -78,9 +90,9 @@
7991 // Get the json string
8092 // XXX wait... why are we grepping it out of an HTML doc? We requested jsonfm, why?
8193 json = $j( doc.body ).find( 'pre' ).text();
82 - mw.log( 'iframe:json::' + json)
 94+ mw.log( 'iframe:json::' + json )
8395 if ( json ) {
84 - response = window["eval"]( "(" + json + ")" );
 96+ response = window["eval"]( "( " + json + " )" );
8597 } else {
8698 response = {};
8799 }

Status & tagging log