r74260 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r74259‎ | r74260 | r74261 >
Date:17:00, 4 October 2010
Author:neilk
Status:deferred
Tags:
Comment:
splitting out some functionality into own files; revised thumbnail generation to use new obtain-thumbnail-on-the-fly SessionStash feature
Modified paths:
  • /branches/uploadwizard/extensions/UploadWizard/resources/mw.GroupProgressBar.js (added) (history)
  • /branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizard.js (modified) (history)
  • /branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardDeed.js (added) (history)
  • /branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardLicenseInput.js (added) (history)
  • /branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardUtil.js (added) (history)

Diff [purge]

Index: branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardDeed.js
@@ -0,0 +1,460 @@
 2+/**
 3+ * Sort of an abstract class for deeds
 4+ */
 5+mw.UploadWizardDeed = function() {
 6+ var _this = this;
 7+ // prevent from instantiating directly?
 8+ return false;
 9+};
 10+
 11+mw.UploadWizardDeed.prototype = {
 12+ valid: function() {
 13+ return false;
 14+ },
 15+
 16+ setFormFields: function() { },
 17+
 18+ getSourceWikiText: function() {
 19+ return $j( this.sourceInput ).val();
 20+ },
 21+
 22+ getAuthorWikiText: function() {
 23+ return $j( this.authorInput ).val();
 24+ },
 25+
 26+ /**
 27+ * Get wikitext representing the licenses selected in the license object
 28+ * @return wikitext of all applicable license templates.
 29+ */
 30+ getLicenseWikiText: function() {
 31+ var _this = this;
 32+ var wikiText = '';
 33+ $j.each ( _this.licenseInput.getTemplates(), function( i, template ) {
 34+ wikiText += "{{" + template + "}}\n";
 35+ } );
 36+
 37+ return wikiText;
 38+ }
 39+
 40+};
 41+
 42+
 43+mw.UploadWizardNullDeed = $j.extend( new mw.UploadWizardDeed(), {
 44+ valid: function() {
 45+ return false;
 46+ }
 47+} );
 48+
 49+
 50+/**
 51+ * Set up the form and deed object for the deed option that says these uploads are all the user's own work.
 52+ * XXX these deeds are starting to turn into jquery fns
 53+ */
 54+mw.UploadWizardDeedOwnWork = function( uploadCount ) {
 55+ uploadCount = uploadCount ? uploadCount : 1;
 56+
 57+ var _this = new mw.UploadWizardDeed();
 58+
 59+ _this.authorInput = $j( '<input />')
 60+ .attr( { name: "author", type: "text" } )
 61+ .addClass( 'mwe-upwiz-sign' );
 62+
 63+ var licenseInputDiv = $j( '<div class="mwe-upwiz-deed-license"></div>' );
 64+ _this.licenseInput = new mw.UploadWizardLicenseInput( licenseInputDiv );
 65+ _this.licenseInput.setDefaultValues();
 66+
 67+ return $j.extend( _this, {
 68+
 69+ name: 'ownwork',
 70+
 71+ /**
 72+ * Is this correctly set, with side effects of causing errors to show in interface.
 73+ * @return boolean true if valid, false if not
 74+ */
 75+ valid: function() {
 76+ // n.b. valid() has side effects and both should be called every time the function is called.
 77+ // do not short-circuit.
 78+ var formValid = _this.$form.valid();
 79+ var licenseInputValid = _this.licenseInput.valid();
 80+ return formValid && licenseInputValid;
 81+ },
 82+
 83+ getSourceWikiText: function() {
 84+ return '{{own}}';
 85+ },
 86+
 87+ // XXX do we need to escape authorInput, or is wikitext a feature here?
 88+ // what about scripts?
 89+ getAuthorWikiText: function() {
 90+ return "[[User:" + mw.UploadWizard.config[ 'userName' ] + '|' + $j( _this.authorInput ).val() + ']]';
 91+ },
 92+
 93+
 94+ getLicenseWikiText: function() {
 95+ var wikiText = '{{self';
 96+ $j.each( _this.licenseInput.getTemplates(), function( i, template ) {
 97+ wikiText += '|' + template;
 98+ } );
 99+ wikiText += '}}';
 100+ return wikiText;
 101+ },
 102+
 103+ setFormFields: function( $selector ) {
 104+ _this.$selector = $selector;
 105+
 106+ _this.$form = $j( '<form/>' );
 107+
 108+ var $standardDiv = $j( '<div />' ).append(
 109+ $j( '<label for="author2" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
 110+ $j( '<p>' )
 111+ .html( gM( 'mwe-upwiz-source-ownwork-assert',
 112+ uploadCount,
 113+ '<span class="mwe-standard-author-input"></span>' )
 114+ ),
 115+ $j( '<p class="mwe-small-print" />' ).append( gM( 'mwe-upwiz-source-ownwork-assert-note' ) )
 116+ );
 117+ $standardDiv.find( '.mwe-standard-author-input' ).append( $j( '<input name="author2" type="text" class="mwe-upwiz-sign" />' ) );
 118+
 119+ var $customDiv = $j('<div/>').append(
 120+ $j( '<label for="author" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
 121+ $j( '<p>' )
 122+ .html( gM( 'mwe-upwiz-source-ownwork-assert-custom',
 123+ uploadCount,
 124+ '<span class="mwe-custom-author-input"></span>' ) ),
 125+ licenseInputDiv
 126+ );
 127+ // have to add the author input this way -- gM() will flatten it to a string and we'll lose it as a dom object
 128+ $customDiv.find( '.mwe-custom-author-input' ).append( _this.authorInput );
 129+
 130+
 131+ var $crossfader = $j( '<div>' ).append( $standardDiv, $customDiv );
 132+ var $toggler = $j( '<p class="mwe-more-options" style="text-align: right" />' )
 133+ .append( $j( '<a />' )
 134+ .append( gM( 'mwe-upwiz-license-show-all' ) )
 135+ .click( function() {
 136+ _this.formValidator.resetForm();
 137+ if ( $crossfader.data( 'crossfadeDisplay' ) === $customDiv ) {
 138+ _this.licenseInput.setDefaultValues();
 139+ $crossfader.morphCrossfade( $standardDiv );
 140+ $j( this ).html( gM( 'mwe-upwiz-license-show-all' ) );
 141+ } else {
 142+ $crossfader.morphCrossfade( $customDiv );
 143+ $j( this ).html( gM( 'mwe-upwiz-license-show-recommended' ) );
 144+ }
 145+ } ) );
 146+
 147+ var $formFields = $j( '<div class="mwe-upwiz-deed-form-internal" />' )
 148+ .append( $crossfader, $toggler );
 149+
 150+
 151+ // synchronize both username signatures
 152+ // set initial value to configured username
 153+ // if one changes all the others change (keyup event)
 154+ //
 155+ // also set tooltips ( the title, tipsy() )
 156+ $formFields.find( '.mwe-upwiz-sign' )
 157+ .attr( {
 158+ title: gM( 'mwe-upwiz-tooltip-sign' ),
 159+ value: mw.UploadWizard.config[ 'userName' ]
 160+ } )
 161+ .tipsyPlus()
 162+ .keyup( function() {
 163+ var thisInput = this;
 164+ var thisVal = $j( thisInput ).val();
 165+ $j.each( $formFields.find( '.mwe-upwiz-sign' ), function( i, input ) {
 166+ if (thisInput !== input) {
 167+ $j( input ).val( thisVal );
 168+ }
 169+ } );
 170+ } );
 171+
 172+ _this.$form.append( $formFields );
 173+ $selector.append( _this.$form );
 174+
 175+ // done after added to the DOM, so there are true heights
 176+ $crossfader.morphCrossfader();
 177+
 178+
 179+ // and finally, make it validatable
 180+ _this.formValidator = _this.$form.validate( {
 181+ rules: {
 182+ author2: {
 183+ required: function( element ) {
 184+ return $crossfader.data( 'crossfadeDisplay' ).get(0) === $standardDiv.get(0);
 185+ },
 186+ minlength: mw.UploadWizard.config[ 'minAuthorLength' ],
 187+ maxlength: mw.UploadWizard.config[ 'maxAuthorLength' ]
 188+ },
 189+ author: {
 190+ required: function( element ) {
 191+ return $crossfader.data( 'crossfadeDisplay' ).get(0) === $customDiv.get(0);
 192+ },
 193+ minlength: mw.UploadWizard.config[ 'minAuthorLength' ],
 194+ maxlength: mw.UploadWizard.config[ 'maxAuthorLength' ]
 195+ }
 196+ },
 197+ messages: {
 198+ author2: {
 199+ required: gM( 'mwe-upwiz-error-signature-blank' ),
 200+ minlength: gM( 'mwe-upwiz-error-signature-too-short', mw.UploadWizard.config[ 'minAuthorLength' ] ),
 201+ maxlength: gM( 'mwe-upwiz-error-signature-too-long', mw.UploadWizard.config[ 'maxAuthorLength' ] )
 202+ },
 203+ author: {
 204+ required: gM( 'mwe-upwiz-error-signature-blank' ),
 205+ minlength: gM( 'mwe-upwiz-error-signature-too-short', mw.UploadWizard.config[ 'minAuthorLength' ] ),
 206+ maxlength: gM( 'mwe-upwiz-error-signature-too-long', mw.UploadWizard.config[ 'maxAuthorLength' ] )
 207+ }
 208+ }
 209+ } );
 210+ }
 211+
 212+
 213+ } );
 214+
 215+};
 216+
 217+// XXX these deeds are starting to turn into jquery fns
 218+mw.UploadWizardDeedThirdParty = function( uploadCount ) {
 219+ var _this = new mw.UploadWizardDeed();
 220+
 221+ _this.uploadCount = uploadCount ? uploadCount : 1;
 222+ _this.sourceInput = $j('<textarea class="mwe-source mwe-long-textarea" name="source" rows="1" cols="40"></textarea>' )
 223+ .growTextArea()
 224+ .attr( 'title', gM( 'mwe-upwiz-tooltip-source' ) )
 225+ .tipsyPlus();
 226+ _this.authorInput = $j('<textarea class="mwe-author mwe-long-textarea" name="author" rows="1" cols="40"></textarea>' )
 227+ .growTextArea()
 228+ .attr( 'title', gM( 'mwe-upwiz-tooltip-author' ) )
 229+ .tipsyPlus();
 230+ licenseInputDiv = $j( '<div class="mwe-upwiz-deed-license"></div>' );
 231+ _this.licenseInput = new mw.UploadWizardLicenseInput( licenseInputDiv );
 232+
 233+
 234+ return $j.extend( _this, mw.UploadWizardDeed.prototype, {
 235+ name: 'thirdparty',
 236+
 237+ setFormFields: function( $selector ) {
 238+ var _this = this;
 239+ _this.$form = $j( '<form/>' );
 240+
 241+ var $formFields = $j( '<div class="mwe-upwiz-deed-form-internal"/>' );
 242+
 243+ if ( uploadCount > 1 ) {
 244+ $formFields.append( $j( '<div />' ).append( gM( 'mwe-upwiz-source-thirdparty-custom-multiple-intro' ) ) );
 245+ }
 246+
 247+ $formFields.append (
 248+ $j( '<div class="mwe-upwiz-source-thirdparty-custom-multiple-intro" />' ),
 249+ $j( '<label for="source" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
 250+ $j( '<div class="mwe-upwiz-thirdparty-fields" />' )
 251+ .append( $j( '<label for="source"/>' ).text( gM( 'mwe-upwiz-source' ) ),
 252+ _this.sourceInput ),
 253+ $j( '<label for="author" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
 254+ $j( '<div class="mwe-upwiz-thirdparty-fields" />' )
 255+ .append( $j( '<label for="author"/>' ).text( gM( 'mwe-upwiz-author' ) ),
 256+ _this.authorInput ),
 257+ $j( '<div class="mwe-upwiz-thirdparty-license" />' )
 258+ .append( gM( 'mwe-upwiz-source-thirdparty-license', uploadCount ) ),
 259+ licenseInputDiv
 260+ );
 261+
 262+ _this.$form.validate( {
 263+ rules: {
 264+ source: { required: true,
 265+ minlength: mw.UploadWizard.config[ 'minSourceLength' ],
 266+ maxlength: mw.UploadWizard.config[ 'maxSourceLength' ] },
 267+ author: { required: true,
 268+ minlength: mw.UploadWizard.config[ 'minAuthorLength' ],
 269+ maxlength: mw.UploadWizard.config[ 'maxAuthorLength' ] }
 270+ },
 271+ messages: {
 272+ source: {
 273+ required: gM( 'mwe-upwiz-error-blank' ),
 274+ minlength: gM( 'mwe-upwiz-error-too-short', mw.UploadWizard.config[ 'minSourceLength' ] ),
 275+ maxlength: gM( 'mwe-upwiz-error-too-long', mw.UploadWizard.config[ 'maxSourceLength' ] )
 276+ },
 277+ author: {
 278+ required: gM( 'mwe-upwiz-error-blank' ),
 279+ minlength: gM( 'mwe-upwiz-error-too-short', mw.UploadWizard.config[ 'minAuthorLength' ] ),
 280+ maxlength: gM( 'mwe-upwiz-error-too-long', mw.UploadWizard.config[ 'maxAuthorLength' ] )
 281+ }
 282+ }
 283+ } );
 284+
 285+ _this.$form.append( $formFields );
 286+
 287+ $selector.append( _this.$form );
 288+ },
 289+
 290+ /**
 291+ * Is this correctly set, with side effects of causing errors to show in interface.
 292+ * this is exactly the same as the ownwork valid() function... hopefully we can reduce these to nothing if we make
 293+ * all validators work the same.
 294+ * @return boolean true if valid, false if not
 295+ */
 296+ valid: function() {
 297+ // n.b. valid() has side effects and both should be called every time the function is called.
 298+ // do not short-circuit.
 299+ var formValid = _this.$form.valid();
 300+ var licenseInputValid = _this.licenseInput.valid();
 301+ return formValid && licenseInputValid;
 302+ }
 303+ } );
 304+};
 305+
 306+
 307+
 308+
 309+/**
 310+ * @param selector where to put this deed chooser
 311+ * @param isPlural whether this chooser applies to multiple files (changes messaging mostly)
 312+ */
 313+mw.UploadWizardDeedChooser = function( selector, deeds, uploadCount ) {
 314+ var _this = this;
 315+ _this.$selector = $j( selector );
 316+ _this.uploadCount = uploadCount ? uploadCount : 1;
 317+
 318+
 319+ _this.$errorEl = $j( '<div class="mwe-error"></div>' );
 320+ _this.$selector.append( _this.$errorEl );
 321+
 322+ // name for radio button set
 323+ mw.UploadWizardDeedChooser.prototype.widgetCount++;
 324+ _this.name = 'deedChooser' + mw.UploadWizardDeedChooser.prototype.widgetCount.toString();
 325+
 326+ $j.each( deeds, function (i, deed) {
 327+ var id = _this.name + '-' + deed.name;
 328+
 329+ var $deedInterface = $j(
 330+ '<div class="mwe-upwiz-deed mwe-upwiz-deed-' + deed.name + '">'
 331+ + '<div class="mwe-upwiz-deed-option-title">'
 332+ + '<span class="mwe-upwiz-deed-header">'
 333+ + '<input id="' + id +'" name="' + _this.name + '" type="radio" value="' + deed.name + '">'
 334+ + '<label for="' + id + '" class="mwe-upwiz-deed-name">'
 335+ + gM( 'mwe-upwiz-source-' + deed.name, _this.uploadCount )
 336+ + '</label>'
 337+ + '</input>'
 338+ + '</span>'
 339+ + '</div>'
 340+ + '<div class="mwe-upwiz-deed-form">'
 341+ + '</div>'
 342+ );
 343+
 344+ var $deedSelector = _this.$selector.append( $deedInterface );
 345+
 346+ deed.setFormFields( $deedInterface.find( '.mwe-upwiz-deed-form' ) );
 347+
 348+ $deedInterface.find( 'span.mwe-upwiz-deed-header input' ).click( function() {
 349+ if ( $j( this ).is(':checked' ) ) {
 350+ _this.choose( deed );
 351+ _this.showDeed( $deedInterface );
 352+ }
 353+ } );
 354+
 355+ } );
 356+
 357+ _this.choose( mw.UploadWizardNullDeed );
 358+ _this.showDeedChoice();
 359+
 360+
 361+};
 362+
 363+
 364+mw.UploadWizardDeedChooser.prototype = {
 365+
 366+ /**
 367+ * How many deed choosers there are (important for creating unique ids, element names)
 368+ */
 369+ widgetCount: 0,
 370+
 371+ /**
 372+ * Check if this form is filled out correctly, with side effects of showing error messages if invalid
 373+ * @return boolean; true if valid, false if not
 374+ */
 375+ valid: function() {
 376+ var _this = this;
 377+ // we assume there is always a deed available, even if it's just the null deed.
 378+ var valid = _this.deed.valid();
 379+ // the only time we need to set an error message is if the null deed is selected.
 380+ // otherwise, we can assume that the widgets have already added error messages.
 381+ if (valid) {
 382+ _this.hideError();
 383+ } else {
 384+ if ( _this.deed === mw.UploadWizardNullDeed ) {
 385+ _this.showError( gM( 'mwe-upwiz-deeds-need-deed', _this.uploadCount ) );
 386+ $j( _this ).bind( 'chooseDeed', function() {
 387+ _this.hideError();
 388+ } );
 389+ }
 390+ }
 391+ return valid;
 392+ },
 393+
 394+ showError: function( error ) {
 395+ this.$errorEl.html( error );
 396+ this.$errorEl.fadeIn();
 397+ },
 398+
 399+ hideError: function() {
 400+ this.$errorEl.fadeOut();
 401+ this.$errorEl.empty();
 402+ },
 403+
 404+ /**
 405+ * How many uploads this deed controls
 406+ */
 407+ uploadCount: 0,
 408+
 409+
 410+ // XXX it's impossible to choose the null deed if we stick with radio buttons, so that may be useless later
 411+ choose: function( deed ) {
 412+ var _this = this;
 413+ _this.deed = deed;
 414+ if ( deed === mw.UploadWizardNullDeed ) {
 415+ $j( _this ).trigger( 'chooseNullDeed' );
 416+ //_this.trigger( 'isNotReady' );
 417+ _this.$selector
 418+ .find( 'input.mwe-accept-deed' )
 419+ .attr( 'checked', false );
 420+ } else {
 421+ $j( _this ).trigger( 'chooseDeed' );
 422+ }
 423+ },
 424+
 425+ /**
 426+ * Go back to original source choice.
 427+ */
 428+ showDeedChoice: function() {
 429+ var $allDeeds = this.$selector.find( '.mwe-upwiz-deed' );
 430+ this.deselectDeed( $allDeeds );
 431+ // $allDeeds.fadeTo( 'fast', 1.0 ); //maskSafeShow();
 432+ },
 433+
 434+ /**
 435+ * From the deed choices, make a choice fade to the background a bit, hide the extended form
 436+ */
 437+ deselectDeed: function( $deedSelector ) {
 438+ $deedSelector.removeClass( 'selected' );
 439+ // $deedSelector.find( 'a.mwe-upwiz-macro-deeds-return' ).hide();
 440+ $deedSelector.find( '.mwe-upwiz-deed-form' ).slideUp( 500 ); //.maskSafeHide();
 441+ },
 442+
 443+ /**
 444+ * From the deed choice page, show a particular deed
 445+ */
 446+ showDeed: function( $deedSelector ) {
 447+ var $otherDeeds = $deedSelector.siblings().filter( '.mwe-upwiz-deed' );
 448+ this.deselectDeed( $otherDeeds );
 449+ // $siblings.fadeTo( 'fast', 0.5 ) // maskSafeHide();
 450+
 451+ $deedSelector
 452+ .addClass('selected')
 453+ .fadeTo( 'fast', 1.0 )
 454+ .find( '.mwe-upwiz-deed-form' ).slideDown( 500 ); // maskSafeShow();
 455+ // $deedSelector.find( 'a.mwe-upwiz-macro-deeds-return' ).show();
 456+ }
 457+
 458+};
 459+
 460+
 461+
Property changes on: branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardDeed.js
___________________________________________________________________
Added: svn:eol-style
1462 + native
Index: branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardLicenseInput.js
@@ -0,0 +1,124 @@
 2+/**
 3+ * Create a group of checkboxes for licenses. N.b. the licenses are named after the templates they invoke.
 4+ * @param div
 5+ * @param values (optional) array of license key names to activate by default
 6+ */
 7+mw.UploadWizardLicenseInput = function( selector, values ) {
 8+ var _this = this;
 9+
 10+ var widgetCount = mw.UploadWizardLicenseInput.prototype.count++;
 11+
 12+ _this.inputs = [];
 13+
 14+ // TODO incompatibility check of this license versus others
 15+
 16+ _this.$selector = $j( selector );
 17+ _this.$selector.append( $j( '<div class="mwe-error"></div>' ) );
 18+
 19+ $j.each( mw.UploadWizard.config[ 'licenses' ], function( i, licenseConfig ) {
 20+ var template = licenseConfig.template;
 21+ var messageKey = licenseConfig.messageKey;
 22+
 23+ var name = 'license_' + template;
 24+ var id = 'licenseInput' + widgetCount + '_' + name;
 25+ var $input = $j( '<input />' )
 26+ .attr( { id: id, name: name, type: 'checkbox', value: template } )
 27+ // we use the selector because events can't be unbound unless they're in the DOM.
 28+ .click( function() { _this.$selector.trigger( 'changeLicenses' ); } );
 29+ _this.inputs.push( $input );
 30+ _this.$selector.append(
 31+ $input,
 32+ $j( '<label />' ).attr( { 'for': id } ).html( gM( messageKey ) ),
 33+ $j( '<br/>' )
 34+ );
 35+ } );
 36+
 37+ if ( values ) {
 38+ _this.setValues( values );
 39+ }
 40+
 41+ return _this;
 42+};
 43+
 44+mw.UploadWizardLicenseInput.prototype = {
 45+ count: 0,
 46+
 47+ /**
 48+ * Sets the value(s) of a license input.
 49+ * @param object of license-key to boolean values, e.g. { cc_by_sa_30: true, gfdl: true }
 50+ */
 51+ setValues: function( licenseValues ) {
 52+ var _this = this;
 53+ $j.each( _this.inputs, function( i, $input ) {
 54+ var template = $input.val();
 55+ $input.attr( 'checked', ~~!!licenseValues[template] );
 56+ } );
 57+ // we use the selector because events can't be unbound unless they're in the DOM.
 58+ _this.$selector.trigger( 'changeLicenses' );
 59+ },
 60+
 61+ /**
 62+ * Set the default configured licenses
 63+ */
 64+ setDefaultValues: function() {
 65+ var _this = this;
 66+ var values = {};
 67+ $j.each( mw.UploadWizard.config[ 'licenses' ], function( i, licenseConfig ) {
 68+ values[ licenseConfig.template ] = licenseConfig['default'];
 69+ } );
 70+ _this.setValues( values );
 71+ },
 72+
 73+ /**
 74+ * Gets the templates associated with checked inputs
 75+ * @return array of template names
 76+ */
 77+ getTemplates: function() {
 78+ return $j( this.inputs )
 79+ .filter( function() { return this.is( ':checked' ); } )
 80+ .map( function() { return this.val(); } );
 81+ },
 82+
 83+ /**
 84+ * Check if a valid value is set, also look for incompatible choices.
 85+ * Side effect: if no valid value, add notes to the interface. Add listeners to interface, to revalidate and remove notes.
 86+ * @return boolean; true if a value set, false otherwise
 87+ */
 88+ valid: function() {
 89+ var _this = this;
 90+ var isValid = true;
 91+
 92+ if ( ! _this.isSet() ) {
 93+ isValid = false;
 94+ errorHtml = gM( 'mwe-upwiz-deeds-need-license' );
 95+ }
 96+
 97+ // XXX something goes here for licenses incompatible with each other
 98+
 99+ var $errorEl = this.$selector.find( '.mwe-error' );
 100+ if (isValid) {
 101+ $errorEl.fadeOut();
 102+ } else {
 103+ // we bind to $selector because unbind() doesn't work on non-DOM objects
 104+ _this.$selector.bind( 'changeLicenses.valid', function() {
 105+ _this.$selector.unbind( 'changeLicenses.valid' );
 106+ _this.valid();
 107+ } );
 108+ $errorEl.html( errorHtml ).show();
 109+ }
 110+
 111+ return isValid;
 112+ },
 113+
 114+
 115+ /**
 116+ * Returns true if any license is set
 117+ * @return boolean
 118+ */
 119+ isSet: function() {
 120+ return this.getTemplates().length > 0;
 121+ }
 122+
 123+};
 124+
 125+
Property changes on: branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardLicenseInput.js
___________________________________________________________________
Added: svn:eol-style
1126 + native
Index: branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardUtil.js
@@ -0,0 +1,126 @@
 2+/**
 3+ * Miscellaneous utilities
 4+ */
 5+mw.UploadWizardUtil = {
 6+
 7+ /**
 8+ * Simple 'more options' toggle that opens more of a form.
 9+ *
 10+ * @param toggleDiv the div which has the control to open and shut custom options
 11+ * @param moreDiv the div containing the custom options
 12+ */
 13+ makeToggler: function ( toggleDiv, moreDiv ) {
 14+ var $toggleLink = $j( '<a>' )
 15+ .addClass( 'mwe-upwiz-toggler mwe-upwiz-more-options' )
 16+ .append( gM( 'mwe-upwiz-more-options' ) );
 17+ $j( toggleDiv ).append( $toggleLink );
 18+
 19+
 20+ var toggle = function( open ) {
 21+ if ( typeof open === 'undefined' ) {
 22+ open = ! ( $j( this ).data( 'open' ) ) ;
 23+ }
 24+ $j( this ).data( 'open', open );
 25+ if ( open ) {
 26+ moreDiv.maskSafeShow();
 27+ /* when open, show control to close */
 28+ $toggleLink.html( gM( 'mwe-upwiz-fewer-options' ) );
 29+ $toggleLink.addClass( "mwe-upwiz-toggler-open" );
 30+ } else {
 31+ moreDiv.maskSafeHide();
 32+ /* when closed, show control to open */
 33+ $toggleLink.html( gM( 'mwe-upwiz-more-options' ) );
 34+ $toggleLink.removeClass( "mwe-upwiz-toggler-open" );
 35+ }
 36+ };
 37+
 38+ toggle(false);
 39+
 40+ $toggleLink.click( function( e ) { e.stopPropagation(); toggle(); } );
 41+
 42+ $j( moreDiv ).addClass( 'mwe-upwiz-toggled' );
 43+ },
 44+
 45+ /**
 46+ * remove an item from an array. Tests for === identity to remove the item
 47+ * XXX the entire rationale for this file may be wrong.
 48+ * XXX The jQuery way would be to query the DOM for objects, not to keep a separate array hanging around
 49+ * @param items the array where we want to remove an item
 50+ * @param item the item to remove
 51+ */
 52+ removeItem: function( items, item ) {
 53+ for ( var i = 0; i < items.length; i++ ) {
 54+ if ( items[i] === item ) {
 55+ items.splice( i, 1 );
 56+ break;
 57+ }
 58+ }
 59+ },
 60+
 61+ /**
 62+ * Capitalise first letter and replace spaces by underscores
 63+ * @param filename (basename, without directories)
 64+ * @return typical title as would appear on MediaWiki
 65+ */
 66+ pathToTitle: function ( filename ) {
 67+ return mw.ucfirst( $j.trim( filename ).replace(/ /g, '_' ) );
 68+ },
 69+
 70+ /**
 71+ * Capitalise first letter and replace underscores by spaces
 72+ * @param title typical title as would appear on MediaWiki
 73+ * @return plausible local filename
 74+ */
 75+ titleToPath: function ( title ) {
 76+ return mw.ucfirst( $j.trim( title ).replace(/_/g, ' ' ) );
 77+ },
 78+
 79+
 80+ /**
 81+ * Transform "File:title_with_spaces.jpg" into "title with spaces"
 82+ * @param typical title that would appear on mediawiki, with File: and extension, may include underscores
 83+ * @return human readable title
 84+ */
 85+ fileTitleToHumanTitle: function( title ) {
 86+ var extension = mw.UploadWizardUtil.getExtension( title );
 87+ if ( typeof extension !== 'undefined' ) {
 88+ // the -1 is to get the '.'
 89+ title = title.substr( 0, title.length - extension.length - 1 );
 90+ }
 91+ // usually File:
 92+ var namespace = wgFormattedNamespaces[wgNamespaceIds['file']];
 93+ if ( title.indexOf( namespace + ':' ) === 0 ) {
 94+ title = title.substr( namespace.length + 1 );
 95+ }
 96+ return mw.UploadWizardUtil.titleToPath( title );
 97+ },
 98+
 99+
 100+ /**
 101+ * Slice extension off a path
 102+ * We assume that extensions are 1-4 characters in length
 103+ * @param path to file, like "foo/bar/baz.jpg"
 104+ * @return extension, like ".jpg" or undefined if it doesn't look lke an extension.
 105+ */
 106+ getExtension: function( path ) {
 107+ var extension = undefined;
 108+ var idx = path.lastIndexOf( '.' );
 109+ if (idx > 0 && ( idx > ( path.length - 5 ) ) && ( idx < ( path.length - 1 ) ) ) {
 110+ extension = path.substr( idx + 1 ).toLowerCase();
 111+ }
 112+ return extension;
 113+ },
 114+
 115+ /**
 116+ * Last resort to guess a proper extension
 117+ */
 118+ mimetypeToExtension: {
 119+ 'image/jpeg': 'jpg',
 120+ 'image/gif': 'gif'
 121+ // fill as needed
 122+ }
 123+
 124+
 125+};
 126+
 127+
Property changes on: branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizardUtil.js
___________________________________________________________________
Added: svn:eol-style
1128 + native
Index: branches/uploadwizard/extensions/UploadWizard/resources/mw.UploadWizard.js
@@ -1,355 +1,8 @@
2 -
3 -/**
4 - * Sort of an abstract class for deeds
5 - */
6 -mw.UploadWizardDeed = function() {
7 - var _this = this;
8 - // prevent from instantiating directly?
9 - return false;
10 -};
11 -
12 -mw.UploadWizardDeed.prototype = {
13 - valid: function() {
14 - return false;
15 - },
16 -
17 - setFormFields: function() { },
18 -
19 - getSourceWikiText: function() {
20 - return $j( this.sourceInput ).val();
21 - },
22 -
23 - getAuthorWikiText: function() {
24 - return $j( this.authorInput ).val();
25 - },
26 -
27 - /**
28 - * Get wikitext representing the licenses selected in the license object
29 - * @return wikitext of all applicable license templates.
30 - */
31 - getLicenseWikiText: function() {
32 - var _this = this;
33 - var wikiText = '';
34 - $j.each ( _this.licenseInput.getTemplates(), function( i, template ) {
35 - wikiText += "{{" + template + "}}\n";
36 - } );
37 -
38 - return wikiText;
39 - }
40 -
41 -};
42 -
43 -
44 -/**
45 - * this is a progress bar for monitoring multiple objects, giving summary view
46 - */
47 -mw.GroupProgressBar = function( selector, text, uploads, endState, progressProperty, weightProperty ) {
48 - var _this = this;
49 -
50 - // XXX need to figure out a way to put text inside bar
51 - _this.$selector = $j( selector );
52 - _this.$selector.html(
53 - '<div class="mwe-upwiz-progress">'
54 - + '<div class="mwe-upwiz-progress-bar-etr-container">'
55 - + '<div class="mwe-upwiz-progress-bar-etr" style="display: none">'
56 - + '<div class="mwe-upwiz-progress-bar"></div>'
57 - + '<div class="mwe-upwiz-etr"></div>'
58 - + '</div>'
59 - + '</div>'
60 - + '<div class="mwe-upwiz-count"></div>'
61 - + '</div>'
62 - );
63 -
64 - _this.$selector.find( '.mwe-upwiz-progress-bar' ).progressbar( { value : 0 } );
65 -
66 - _this.uploads = uploads;
67 - _this.endState = endState;
68 - _this.progressProperty = progressProperty;
69 - _this.weightProperty = weightProperty;
70 - _this.beginTime = undefined;
71 -
72 -};
73 -
74 -mw.GroupProgressBar.prototype = {
75 -
76 - /**
77 - * Show the progress bar with a slideout motion
78 - */
79 - showBar: function() {
80 - this.$selector.find( '.mwe-upwiz-progress-bar-etr' ).fadeIn( 200 );
81 - },
82 -
83 - /**
84 - * loop around the uploads, summing certain properties for a weighted total fraction
85 - */
86 - start: function() {
87 - var _this = this;
88 -
89 - var totalWeight = 0.0;
90 - $j.each( _this.uploads, function( i, upload ) {
91 - totalWeight += upload[_this.weightProperty];
92 - } );
93 -
94 - _this.setBeginTime();
95 - var shown = false;
96 -
97 - var displayer = function() {
98 - var fraction = 0.0;
99 - var endStateCount = 0;
100 - var hasData = false;
101 - $j.each( _this.uploads, function( i, upload ) {
102 - if ( upload.state == _this.endState ) {
103 - endStateCount++;
104 - }
105 - if (upload[_this.progressProperty] !== undefined) {
106 - fraction += upload[_this.progressProperty] * ( upload[_this.weightProperty] / totalWeight );
107 - if (upload[_this.progressProperty] > 0 ) {
108 - hasData = true;
109 - }
110 - }
111 - } );
112 - //mw.log( 'hasdata:' + hasData + ' endstatecount:' + endStateCount );
113 - // sometimes, the first data we have just tells us that it's over. So only show the bar
114 - // if we have good data AND the fraction is less than 1.
115 - if ( hasData && fraction < 1.0 ) {
116 - if ( ! shown ) {
117 - _this.showBar();
118 - shown = true;
119 - }
120 - _this.showProgress( fraction );
121 - }
122 - _this.showCount( endStateCount );
123 -
124 - if ( endStateCount < _this.uploads.length ) {
125 - setTimeout( displayer, 200 );
126 - } else {
127 - _this.showProgress( 1.0 );
128 - // not necessary to hide bar since we're going to the next step.
129 - /* setTimeout( function() { _this.hideBar(); }, 500 ); */
130 - }
131 - };
132 - displayer();
133 - },
134 -
135 -
136 - /**
137 - * Hide the progress bar with a slideup motion
138 - */
139 - hideBar: function() {
140 - this.$selector.find( '.mwe-upwiz-progress-bar-etr' ).fadeOut( 200 );
141 - },
142 -
143 - /**
144 - * sets the beginning time (useful for figuring out estimated time remaining)
145 - * if time parameter omitted, will set beginning time to now
146 - *
147 - * @param time optional; the time this bar is presumed to have started (epoch milliseconds)
148 - */
149 - setBeginTime: function( time ) {
150 - this.beginTime = time ? time : ( new Date() ).getTime();
151 - },
152 -
153 -
154 - /**
155 - * Show overall progress for the entire UploadWizard
156 - * The current design doesn't have individual progress bars, just one giant one.
157 - * We did some tricky calculations in startUploads to try to weight each individual file's progress against
158 - * the overall progress.
159 - * @param fraction the amount of whatever it is that's done whatever it's done
160 - */
161 - showProgress: function( fraction ) {
162 - var _this = this;
163 -
164 - _this.$selector.find( '.mwe-upwiz-progress-bar' ).progressbar( 'value', parseInt( fraction * 100, 10 ) );
165 -
166 - var remainingTime = _this.getRemainingTime( fraction );
 2+// XXX
 3+// this is sure starting to look like we should compose of UI, handler.
1674
168 - if ( remainingTime !== null ) {
169 - var t = mw.seconds2Measurements( parseInt( remainingTime / 1000, 10 ) );
170 - var timeString;
171 - if (t.hours === 0) {
172 - if (t.minutes === 0) {
173 - if (t.seconds === 0) {
174 - timeString = gM( 'mwe-upwiz-finished' );
175 - } else {
176 - timeString = gM( 'mwe-upwiz-secs-remaining', t.seconds );
177 - }
178 - } else {
179 - timeString = gM( 'mwe-upwiz-mins-secs-remaining', t.minutes, t.seconds );
180 - }
181 - } else {
182 - timeString = gM( 'mwe-upwiz-hrs-mins-secs-remaining', t.hours, t.minutes, t.seconds );
183 - }
184 - _this.$selector.find( '.mwe-upwiz-etr' ).html( timeString );
185 - }
186 - },
1875
188 - /**
189 - * Calculate remaining time for all uploads to complete.
190 - *
191 - * @param fraction fraction of progress to show
192 - * @return estimated time remaining (in milliseconds)
193 - */
194 - getRemainingTime: function ( fraction ) {
195 - var _this = this;
196 - if ( _this.beginTime ) {
197 - var elapsedTime = ( new Date() ).getTime() - _this.beginTime;
198 - if ( fraction > 0.0 && elapsedTime > 0 ) { // or some other minimums for good data
199 - var rate = fraction / elapsedTime;
200 - return parseInt( ( 1.0 - fraction ) / rate, 10 );
201 - }
202 - }
203 - return null;
204 - },
205 -
206 -
207 - /**
208 - * Show the overall count as we upload
209 - * @param count -- the number of items that have done whatever has been done e.g. in "uploaded 2 of 5", this is the 2
210 - */
211 - showCount: function( count ) {
212 - var _this = this;
213 - _this.$selector
214 - .find( '.mwe-upwiz-count' )
215 - .html( gM( 'mwe-upwiz-upload-count', [ count, _this.uploads.length ] ) );
216 - }
217 -
218 -
219 -};
220 -
221 -
222 -
223 -//mw.setConfig('uploadHandlerClass', mw.MockUploadHandler); // ApiUploadHandler?
224 -
225 -// available licenses should be a configuration of the MediaWiki instance,
226 -// not hardcoded here.
227 -// but, MediaWiki has no real concept of a License as a first class object -- there are templates and then specially - parsed
228 -// texts to create menus -- hack on top of hacks -- a bit too much to deal with ATM
2296 /**
230 - * Create a group of checkboxes for licenses. N.b. the licenses are named after the templates they invoke.
231 - * @param div
232 - * @param values (optional) array of license key names to activate by default
233 - */
234 -mw.UploadWizardLicenseInput = function( selector, values ) {
235 - var _this = this;
236 -
237 - var widgetCount = mw.UploadWizardLicenseInput.prototype.count++;
238 -
239 - _this.inputs = [];
240 -
241 - // TODO incompatibility check of this license versus others
242 -
243 - _this.$selector = $j( selector );
244 - _this.$selector.append( $j( '<div class="mwe-error"></div>' ) );
245 -
246 - $j.each( mw.UploadWizard.config[ 'licenses' ], function( i, licenseConfig ) {
247 - var template = licenseConfig.template;
248 - var messageKey = licenseConfig.messageKey;
249 -
250 - var name = 'license_' + template;
251 - var id = 'licenseInput' + widgetCount + '_' + name;
252 - var $input = $j( '<input />' )
253 - .attr( { id: id, name: name, type: 'checkbox', value: template } )
254 - // we use the selector because events can't be unbound unless they're in the DOM.
255 - .click( function() { _this.$selector.trigger( 'changeLicenses' ); } );
256 - _this.inputs.push( $input );
257 - _this.$selector.append(
258 - $input,
259 - $j( '<label />' ).attr( { 'for': id } ).html( gM( messageKey ) ),
260 - $j( '<br/>' )
261 - );
262 - } );
263 -
264 - if ( values ) {
265 - _this.setValues( values );
266 - }
267 -
268 - return _this;
269 -};
270 -
271 -mw.UploadWizardLicenseInput.prototype = {
272 - count: 0,
273 -
274 - /**
275 - * Sets the value(s) of a license input.
276 - * @param object of license-key to boolean values, e.g. { cc_by_sa_30: true, gfdl: true }
277 - */
278 - setValues: function( licenseValues ) {
279 - var _this = this;
280 - $j.each( _this.inputs, function( i, $input ) {
281 - var template = $input.val();
282 - $input.attr( 'checked', ~~!!licenseValues[template] );
283 - } );
284 - // we use the selector because events can't be unbound unless they're in the DOM.
285 - _this.$selector.trigger( 'changeLicenses' );
286 - },
287 -
288 - /**
289 - * Set the default configured licenses
290 - */
291 - setDefaultValues: function() {
292 - var _this = this;
293 - var values = {};
294 - $j.each( mw.UploadWizard.config[ 'licenses' ], function( i, licenseConfig ) {
295 - values[ licenseConfig.template ] = licenseConfig['default'];
296 - } );
297 - _this.setValues( values );
298 - },
299 -
300 - /**
301 - * Gets the templates associated with checked inputs
302 - * @return array of template names
303 - */
304 - getTemplates: function() {
305 - return $j( this.inputs )
306 - .filter( function() { return this.is( ':checked' ); } )
307 - .map( function() { return this.val(); } );
308 - },
309 -
310 - /**
311 - * Check if a valid value is set, also look for incompatible choices.
312 - * Side effect: if no valid value, add notes to the interface. Add listeners to interface, to revalidate and remove notes.
313 - * @return boolean; true if a value set, false otherwise
314 - */
315 - valid: function() {
316 - var _this = this;
317 - var isValid = true;
318 -
319 - if ( ! _this.isSet() ) {
320 - isValid = false;
321 - errorHtml = gM( 'mwe-upwiz-deeds-need-license' );
322 - }
323 -
324 - // XXX something goes here for licenses incompatible with each other
325 -
326 - var $errorEl = this.$selector.find( '.mwe-error' );
327 - if (isValid) {
328 - $errorEl.fadeOut();
329 - } else {
330 - // we bind to $selector because unbind() doesn't work on non-DOM objects
331 - _this.$selector.bind( 'changeLicenses.valid', function() {
332 - _this.$selector.unbind( 'changeLicenses.valid' );
333 - _this.valid();
334 - } );
335 - $errorEl.html( errorHtml ).show();
336 - }
337 -
338 - return isValid;
339 - },
340 -
341 -
342 - /**
343 - * Returns true if any license is set
344 - * @return boolean
345 - */
346 - isSet: function() {
347 - return this.getTemplates().length > 0;
348 - }
349 -
350 -};
351 -
352 -
353 -/**
3547 * Represents the upload -- in its local and remote state. (Possibly those could be separate objects too...)
3558 * This is our 'model' object if we are thinking MVC. Needs to be better factored, lots of feature envy with the UploadWizard
3569 * states:
@@ -370,9 +23,7 @@
37124 _this.mimetype = undefined;
37225 _this.extension = undefined;
37326
374 - // XXX
375 - // this is sure starting to look like we should compose of UI, handler.
376 -
 27+
37728 // details
37829 _this.ui = new mw.UploadWizardUploadInterface( _this, filesDiv );
37930
@@ -544,58 +195,32 @@
545196 },
546197
547198 /**
548 - * Supply information to create a thumbnail for this Upload. Runs async, with a callback.
 199+ * Fetch a thumbnail for this upload of the desired width.
549200 * It is assumed you don't call this until it's been transported.
550201 *
551 - * XXX should check if we really need this second API call or if we can get MediaWiki to make us a thumbnail URL upon upload
552 - *
 202+ * We create the thumbnail by passing a special URL which creates the thumbnail on the fly and returns the image contents.
 203+ * If the original image URL is http://foo.com/bar/baz/xyz.jpg, and the desired width is 120 pixels,
 204+ * the thumbnail URL is http://foo.com/bar/baz/120px-xyz.jpg
 205+ *
553206 * @param width - desired width of thumbnail (height will scale to match)
554 - * @param callback - callback to execute once thumbnail has been obtained -- must accept object with properties of width, height, and url.
 207+ * @param callback - callback to execute once thumbnail has been obtained -- must accept Image object
555208 */
556209 getThumbnail: function( width, callback ) {
557210 var _this = this;
558 - if ( _this._thumbnails[ "width" + width ] !== undefined ) {
559 - callback( _this._thumbnails[ "width" + width ] );
560 - return;
561 - }
562 -
563 - var params = {
564 - 'titles': _this.title,
565 - 'prop': 'imageinfo',
566 - 'iiurlwidth': width,
567 - 'iiprop': 'url'
568 - };
569 -
570 - debugger;
571 - this.api.get( params, function( data ) {
572 - if ( !data || !data.query || !data.query.pages ) {
573 - mw.log(" No data? ");
574 - // XXX do something about the thumbnail spinner, maybe call the callback with a broken image.
575 - return;
 211+ key = "width" + width;
 212+ if ( mw.isDefined( _this._thumbnails[key] ) && typeof _this._thumbnails[key] === 'Image' ) {
 213+ callback( _this._thumbnails[key] );
 214+ } else {
 215+ var thumbUrl = _this.imageinfo.url.replace( /(.*)/([^\/]+)$/, "$1/" + width + "px-" + $2 );
 216+ _this._thumbnails[ "width" + width ] = new Image( thumbUrl );
 217+ var image = new Image();
 218+ image.onload = function(){
 219+ _this._thumbnails[key] = image;
 220+ callback( image );
576221 }
577 -
578 - if ( data.query.pages[-1] ) {
579 - // XXX do something about the thumbnail spinner, maybe call the callback with a broken image.
580 - return;
581 - }
582 - for ( var page_id in data.query.pages ) {
583 - var page = data.query.pages[ page_id ];
584 - if ( ! page.imageinfo ) {
585 - alert("imageinfo missing");
586 - // not found? error
587 - } else {
588 - var imageInfo = page.imageinfo[0];
589 - var thumbnail = {
590 - width: imageInfo.thumbwidth,
591 - height: imageInfo.thumbheight,
592 - url: imageInfo.thumburl
593 - };
594 - _this._thumbnails[ "width" + width ] = thumbnail;
595 - callback( thumbnail );
596 - }
597 - }
598 - } );
599 -
 222+ image.src = thumbUrl;
 223+ }
 224+
600225 },
601226
602227
@@ -624,7 +249,7 @@
625250 $j( '<img/>' )
626251 .attr( 'width', thumbnail.width )
627252 .attr( 'height', thumbnail.height )
628 - .attr( 'src', thumbnail.url ) ) );
 253+ .attr( 'src', thumbnail.src ) ) );
629254 };
630255
631256 $j( selector ).loadingSpinner();
@@ -2640,558 +2265,6 @@
26412266 }
26422267 };
26432268
2644 -mw.UploadWizardNullDeed = $j.extend( new mw.UploadWizardDeed(), {
2645 - valid: function() {
2646 - return false;
2647 - }
2648 -} );
2649 -
2650 -
2651 -/**
2652 - * Set up the form and deed object for the deed option that says these uploads are all the user's own work.
2653 - * XXX these deeds are starting to turn into jquery fns
2654 - */
2655 -mw.UploadWizardDeedOwnWork = function( uploadCount ) {
2656 - uploadCount = uploadCount ? uploadCount : 1;
2657 -
2658 - var _this = new mw.UploadWizardDeed();
2659 -
2660 - _this.authorInput = $j( '<input />')
2661 - .attr( { name: "author", type: "text" } )
2662 - .addClass( 'mwe-upwiz-sign' );
2663 -
2664 - var licenseInputDiv = $j( '<div class="mwe-upwiz-deed-license"></div>' );
2665 - _this.licenseInput = new mw.UploadWizardLicenseInput( licenseInputDiv );
2666 - _this.licenseInput.setDefaultValues();
2667 -
2668 - return $j.extend( _this, {
2669 -
2670 - name: 'ownwork',
2671 -
2672 - /**
2673 - * Is this correctly set, with side effects of causing errors to show in interface.
2674 - * @return boolean true if valid, false if not
2675 - */
2676 - valid: function() {
2677 - // n.b. valid() has side effects and both should be called every time the function is called.
2678 - // do not short-circuit.
2679 - var formValid = _this.$form.valid();
2680 - var licenseInputValid = _this.licenseInput.valid();
2681 - return formValid && licenseInputValid;
2682 - },
2683 -
2684 - getSourceWikiText: function() {
2685 - return '{{own}}';
2686 - },
2687 -
2688 - // XXX do we need to escape authorInput, or is wikitext a feature here?
2689 - // what about scripts?
2690 - getAuthorWikiText: function() {
2691 - return "[[User:" + mw.UploadWizard.config[ 'userName' ] + '|' + $j( _this.authorInput ).val() + ']]';
2692 - },
2693 -
2694 -
2695 - getLicenseWikiText: function() {
2696 - var wikiText = '{{self';
2697 - $j.each( _this.licenseInput.getTemplates(), function( i, template ) {
2698 - wikiText += '|' + template;
2699 - } );
2700 - wikiText += '}}';
2701 - return wikiText;
2702 - },
2703 -
2704 - setFormFields: function( $selector ) {
2705 - _this.$selector = $selector;
2706 -
2707 - _this.$form = $j( '<form/>' );
2708 -
2709 - var $standardDiv = $j( '<div />' ).append(
2710 - $j( '<label for="author2" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
2711 - $j( '<p>' )
2712 - .html( gM( 'mwe-upwiz-source-ownwork-assert',
2713 - uploadCount,
2714 - '<span class="mwe-standard-author-input"></span>' )
2715 - ),
2716 - $j( '<p class="mwe-small-print" />' ).append( gM( 'mwe-upwiz-source-ownwork-assert-note' ) )
2717 - );
2718 - $standardDiv.find( '.mwe-standard-author-input' ).append( $j( '<input name="author2" type="text" class="mwe-upwiz-sign" />' ) );
2719 -
2720 - var $customDiv = $j('<div/>').append(
2721 - $j( '<label for="author" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
2722 - $j( '<p>' )
2723 - .html( gM( 'mwe-upwiz-source-ownwork-assert-custom',
2724 - uploadCount,
2725 - '<span class="mwe-custom-author-input"></span>' ) ),
2726 - licenseInputDiv
2727 - );
2728 - // have to add the author input this way -- gM() will flatten it to a string and we'll lose it as a dom object
2729 - $customDiv.find( '.mwe-custom-author-input' ).append( _this.authorInput );
2730 -
2731 -
2732 - var $crossfader = $j( '<div>' ).append( $standardDiv, $customDiv );
2733 - var $toggler = $j( '<p class="mwe-more-options" style="text-align: right" />' )
2734 - .append( $j( '<a />' )
2735 - .append( gM( 'mwe-upwiz-license-show-all' ) )
2736 - .click( function() {
2737 - _this.formValidator.resetForm();
2738 - if ( $crossfader.data( 'crossfadeDisplay' ) === $customDiv ) {
2739 - _this.licenseInput.setDefaultValues();
2740 - $crossfader.morphCrossfade( $standardDiv );
2741 - $j( this ).html( gM( 'mwe-upwiz-license-show-all' ) );
2742 - } else {
2743 - $crossfader.morphCrossfade( $customDiv );
2744 - $j( this ).html( gM( 'mwe-upwiz-license-show-recommended' ) );
2745 - }
2746 - } ) );
2747 -
2748 - var $formFields = $j( '<div class="mwe-upwiz-deed-form-internal" />' )
2749 - .append( $crossfader, $toggler );
2750 -
2751 -
2752 - // synchronize both username signatures
2753 - // set initial value to configured username
2754 - // if one changes all the others change (keyup event)
2755 - //
2756 - // also set tooltips ( the title, tipsy() )
2757 - $formFields.find( '.mwe-upwiz-sign' )
2758 - .attr( {
2759 - title: gM( 'mwe-upwiz-tooltip-sign' ),
2760 - value: mw.UploadWizard.config[ 'userName' ]
2761 - } )
2762 - .tipsyPlus()
2763 - .keyup( function() {
2764 - var thisInput = this;
2765 - var thisVal = $j( thisInput ).val();
2766 - $j.each( $formFields.find( '.mwe-upwiz-sign' ), function( i, input ) {
2767 - if (thisInput !== input) {
2768 - $j( input ).val( thisVal );
2769 - }
2770 - } );
2771 - } );
2772 -
2773 - _this.$form.append( $formFields );
2774 - $selector.append( _this.$form );
2775 -
2776 - // done after added to the DOM, so there are true heights
2777 - $crossfader.morphCrossfader();
2778 -
2779 -
2780 - // and finally, make it validatable
2781 - _this.formValidator = _this.$form.validate( {
2782 - rules: {
2783 - author2: {
2784 - required: function( element ) {
2785 - return $crossfader.data( 'crossfadeDisplay' ).get(0) === $standardDiv.get(0);
2786 - },
2787 - minlength: mw.UploadWizard.config[ 'minAuthorLength' ],
2788 - maxlength: mw.UploadWizard.config[ 'maxAuthorLength' ]
2789 - },
2790 - author: {
2791 - required: function( element ) {
2792 - return $crossfader.data( 'crossfadeDisplay' ).get(0) === $customDiv.get(0);
2793 - },
2794 - minlength: mw.UploadWizard.config[ 'minAuthorLength' ],
2795 - maxlength: mw.UploadWizard.config[ 'maxAuthorLength' ]
2796 - }
2797 - },
2798 - messages: {
2799 - author2: {
2800 - required: gM( 'mwe-upwiz-error-signature-blank' ),
2801 - minlength: gM( 'mwe-upwiz-error-signature-too-short', mw.UploadWizard.config[ 'minAuthorLength' ] ),
2802 - maxlength: gM( 'mwe-upwiz-error-signature-too-long', mw.UploadWizard.config[ 'maxAuthorLength' ] )
2803 - },
2804 - author: {
2805 - required: gM( 'mwe-upwiz-error-signature-blank' ),
2806 - minlength: gM( 'mwe-upwiz-error-signature-too-short', mw.UploadWizard.config[ 'minAuthorLength' ] ),
2807 - maxlength: gM( 'mwe-upwiz-error-signature-too-long', mw.UploadWizard.config[ 'maxAuthorLength' ] )
2808 - }
2809 - }
2810 - } );
2811 - }
2812 -
2813 -
2814 - } );
2815 -
2816 -};
2817 -
2818 -// XXX these deeds are starting to turn into jquery fns
2819 -mw.UploadWizardDeedThirdParty = function( uploadCount ) {
2820 - var _this = new mw.UploadWizardDeed();
2821 -
2822 - _this.uploadCount = uploadCount ? uploadCount : 1;
2823 - _this.sourceInput = $j('<textarea class="mwe-source mwe-long-textarea" name="source" rows="1" cols="40"></textarea>' )
2824 - .growTextArea()
2825 - .attr( 'title', gM( 'mwe-upwiz-tooltip-source' ) )
2826 - .tipsyPlus();
2827 - _this.authorInput = $j('<textarea class="mwe-author mwe-long-textarea" name="author" rows="1" cols="40"></textarea>' )
2828 - .growTextArea()
2829 - .attr( 'title', gM( 'mwe-upwiz-tooltip-author' ) )
2830 - .tipsyPlus();
2831 - licenseInputDiv = $j( '<div class="mwe-upwiz-deed-license"></div>' );
2832 - _this.licenseInput = new mw.UploadWizardLicenseInput( licenseInputDiv );
2833 -
2834 -
2835 - return $j.extend( _this, mw.UploadWizardDeed.prototype, {
2836 - name: 'thirdparty',
2837 -
2838 - setFormFields: function( $selector ) {
2839 - var _this = this;
2840 - _this.$form = $j( '<form/>' );
2841 -
2842 - var $formFields = $j( '<div class="mwe-upwiz-deed-form-internal"/>' );
2843 -
2844 - if ( uploadCount > 1 ) {
2845 - $formFields.append( $j( '<div />' ).append( gM( 'mwe-upwiz-source-thirdparty-custom-multiple-intro' ) ) );
2846 - }
2847 -
2848 - $formFields.append (
2849 - $j( '<div class="mwe-upwiz-source-thirdparty-custom-multiple-intro" />' ),
2850 - $j( '<label for="source" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
2851 - $j( '<div class="mwe-upwiz-thirdparty-fields" />' )
2852 - .append( $j( '<label for="source"/>' ).text( gM( 'mwe-upwiz-source' ) ),
2853 - _this.sourceInput ),
2854 - $j( '<label for="author" generated="true" class="mwe-validator-error" style="display:block;"/>' ),
2855 - $j( '<div class="mwe-upwiz-thirdparty-fields" />' )
2856 - .append( $j( '<label for="author"/>' ).text( gM( 'mwe-upwiz-author' ) ),
2857 - _this.authorInput ),
2858 - $j( '<div class="mwe-upwiz-thirdparty-license" />' )
2859 - .append( gM( 'mwe-upwiz-source-thirdparty-license', uploadCount ) ),
2860 - licenseInputDiv
2861 - );
2862 -
2863 - _this.$form.validate( {
2864 - rules: {
2865 - source: { required: true,
2866 - minlength: mw.UploadWizard.config[ 'minSourceLength' ],
2867 - maxlength: mw.UploadWizard.config[ 'maxSourceLength' ] },
2868 - author: { required: true,
2869 - minlength: mw.UploadWizard.config[ 'minAuthorLength' ],
2870 - maxlength: mw.UploadWizard.config[ 'maxAuthorLength' ] }
2871 - },
2872 - messages: {
2873 - source: {
2874 - required: gM( 'mwe-upwiz-error-blank' ),
2875 - minlength: gM( 'mwe-upwiz-error-too-short', mw.UploadWizard.config[ 'minSourceLength' ] ),
2876 - maxlength: gM( 'mwe-upwiz-error-too-long', mw.UploadWizard.config[ 'maxSourceLength' ] )
2877 - },
2878 - author: {
2879 - required: gM( 'mwe-upwiz-error-blank' ),
2880 - minlength: gM( 'mwe-upwiz-error-too-short', mw.UploadWizard.config[ 'minAuthorLength' ] ),
2881 - maxlength: gM( 'mwe-upwiz-error-too-long', mw.UploadWizard.config[ 'maxAuthorLength' ] )
2882 - }
2883 - }
2884 - } );
2885 -
2886 - _this.$form.append( $formFields );
2887 -
2888 - $selector.append( _this.$form );
2889 - },
2890 -
2891 - /**
2892 - * Is this correctly set, with side effects of causing errors to show in interface.
2893 - * this is exactly the same as the ownwork valid() function... hopefully we can reduce these to nothing if we make
2894 - * all validators work the same.
2895 - * @return boolean true if valid, false if not
2896 - */
2897 - valid: function() {
2898 - // n.b. valid() has side effects and both should be called every time the function is called.
2899 - // do not short-circuit.
2900 - var formValid = _this.$form.valid();
2901 - var licenseInputValid = _this.licenseInput.valid();
2902 - return formValid && licenseInputValid;
2903 - }
2904 - } );
2905 -};
2906 -
2907 -
2908 -
2909 -
2910 -/**
2911 - * @param selector where to put this deed chooser
2912 - * @param isPlural whether this chooser applies to multiple files (changes messaging mostly)
2913 - */
2914 -mw.UploadWizardDeedChooser = function( selector, deeds, uploadCount ) {
2915 - var _this = this;
2916 - _this.$selector = $j( selector );
2917 - _this.uploadCount = uploadCount ? uploadCount : 1;
2918 -
2919 -
2920 - _this.$errorEl = $j( '<div class="mwe-error"></div>' );
2921 - _this.$selector.append( _this.$errorEl );
2922 -
2923 - // name for radio button set
2924 - mw.UploadWizardDeedChooser.prototype.widgetCount++;
2925 - _this.name = 'deedChooser' + mw.UploadWizardDeedChooser.prototype.widgetCount.toString();
2926 -
2927 - $j.each( deeds, function (i, deed) {
2928 - var id = _this.name + '-' + deed.name;
2929 -
2930 - var $deedInterface = $j(
2931 - '<div class="mwe-upwiz-deed mwe-upwiz-deed-' + deed.name + '">'
2932 - + '<div class="mwe-upwiz-deed-option-title">'
2933 - + '<span class="mwe-upwiz-deed-header">'
2934 - + '<input id="' + id +'" name="' + _this.name + '" type="radio" value="' + deed.name + '">'
2935 - + '<label for="' + id + '" class="mwe-upwiz-deed-name">'
2936 - + gM( 'mwe-upwiz-source-' + deed.name, _this.uploadCount )
2937 - + '</label>'
2938 - + '</input>'
2939 - + '</span>'
2940 - // + ' <a class="mwe-upwiz-macro-deeds-return">' + gM( 'mwe-upwiz-change' ) + '</a>'
2941 - + '</div>'
2942 - + '<div class="mwe-upwiz-deed-form">'
2943 - + '</div>'
2944 - );
2945 -
2946 - var $deedSelector = _this.$selector.append( $deedInterface );
2947 -
2948 - deed.setFormFields( $deedInterface.find( '.mwe-upwiz-deed-form' ) );
2949 -
2950 - $deedInterface.find( 'span.mwe-upwiz-deed-header input' ).click( function() {
2951 - if ( $j( this ).is(':checked' ) ) {
2952 - _this.choose( deed );
2953 - _this.showDeed( $deedInterface );
2954 - }
2955 - } );
2956 -
2957 - } );
2958 -
2959 - /*
2960 - $j( '.mwe-upwiz-macro-deeds-return' ).click( function() {
2961 - _this.choose( mw.UploadWizardNullDeed );
2962 - _this.showDeedChoice();
2963 - } );
2964 - */
2965 -
2966 - _this.choose( mw.UploadWizardNullDeed );
2967 - _this.showDeedChoice();
2968 -
2969 -
2970 -};
2971 -
2972 -
2973 -mw.UploadWizardDeedChooser.prototype = {
2974 -
2975 - /**
2976 - * How many deed choosers there are (important for creating unique ids, element names)
2977 - */
2978 - widgetCount: 0,
2979 -
2980 - /**
2981 - * Check if this form is filled out correctly, with side effects of showing error messages if invalid
2982 - * @return boolean; true if valid, false if not
2983 - */
2984 - valid: function() {
2985 - var _this = this;
2986 - // we assume there is always a deed available, even if it's just the null deed.
2987 - var valid = _this.deed.valid();
2988 - // the only time we need to set an error message is if the null deed is selected.
2989 - // otherwise, we can assume that the widgets have already added error messages.
2990 - if (valid) {
2991 - _this.hideError();
2992 - } else {
2993 - if ( _this.deed === mw.UploadWizardNullDeed ) {
2994 - _this.showError( gM( 'mwe-upwiz-deeds-need-deed', _this.uploadCount ) );
2995 - $j( _this ).bind( 'chooseDeed', function() {
2996 - _this.hideError();
2997 - } );
2998 - }
2999 - }
3000 - return valid;
3001 - },
3002 -
3003 - showError: function( error ) {
3004 - this.$errorEl.html( error );
3005 - this.$errorEl.fadeIn();
3006 - },
3007 -
3008 - hideError: function() {
3009 - this.$errorEl.fadeOut();
3010 - this.$errorEl.empty();
3011 - },
3012 -
3013 - /**
3014 - * How many uploads this deed controls
3015 - */
3016 - uploadCount: 0,
3017 -
3018 -
3019 - // XXX it's impossible to choose the null deed if we stick with radio buttons, so that may be useless later
3020 - choose: function( deed ) {
3021 - var _this = this;
3022 - _this.deed = deed;
3023 - if ( deed === mw.UploadWizardNullDeed ) {
3024 - $j( _this ).trigger( 'chooseNullDeed' );
3025 - //_this.trigger( 'isNotReady' );
3026 - _this.$selector
3027 - .find( 'input.mwe-accept-deed' )
3028 - .attr( 'checked', false );
3029 - } else {
3030 - $j( _this ).trigger( 'chooseDeed' );
3031 - }
3032 - },
3033 -
3034 - /**
3035 - * Go back to original source choice.
3036 - */
3037 - showDeedChoice: function() {
3038 - var $allDeeds = this.$selector.find( '.mwe-upwiz-deed' );
3039 - this.deselectDeed( $allDeeds );
3040 - // $allDeeds.fadeTo( 'fast', 1.0 ); //maskSafeShow();
3041 - },
3042 -
3043 - /**
3044 - * From the deed choices, make a choice fade to the background a bit, hide the extended form
3045 - */
3046 - deselectDeed: function( $deedSelector ) {
3047 - $deedSelector.removeClass( 'selected' );
3048 - // $deedSelector.find( 'a.mwe-upwiz-macro-deeds-return' ).hide();
3049 - $deedSelector.find( '.mwe-upwiz-deed-form' ).slideUp( 500 ); //.maskSafeHide();
3050 - },
3051 -
3052 - /**
3053 - * From the deed choice page, show a particular deed
3054 - */
3055 - showDeed: function( $deedSelector ) {
3056 - var $otherDeeds = $deedSelector.siblings().filter( '.mwe-upwiz-deed' );
3057 - this.deselectDeed( $otherDeeds );
3058 - // $siblings.fadeTo( 'fast', 0.5 ) // maskSafeHide();
3059 -
3060 - $deedSelector
3061 - .addClass('selected')
3062 - .fadeTo( 'fast', 1.0 )
3063 - .find( '.mwe-upwiz-deed-form' ).slideDown( 500 ); // maskSafeShow();
3064 - // $deedSelector.find( 'a.mwe-upwiz-macro-deeds-return' ).show();
3065 - }
3066 -
3067 -};
3068 -
3069 -
3070 -
3071 -/**
3072 - * Miscellaneous utilities
3073 - */
3074 -mw.UploadWizardUtil = {
3075 -
3076 - /**
3077 - * Simple 'more options' toggle that opens more of a form.
3078 - *
3079 - * @param toggleDiv the div which has the control to open and shut custom options
3080 - * @param moreDiv the div containing the custom options
3081 - */
3082 - makeToggler: function ( toggleDiv, moreDiv ) {
3083 - var $toggleLink = $j( '<a>' )
3084 - .addClass( 'mwe-upwiz-toggler mwe-upwiz-more-options' )
3085 - .append( gM( 'mwe-upwiz-more-options' ) );
3086 - $j( toggleDiv ).append( $toggleLink );
3087 -
3088 -
3089 - var toggle = function( open ) {
3090 - if ( typeof open === 'undefined' ) {
3091 - open = ! ( $j( this ).data( 'open' ) ) ;
3092 - }
3093 - $j( this ).data( 'open', open );
3094 - if ( open ) {
3095 - moreDiv.maskSafeShow();
3096 - /* when open, show control to close */
3097 - $toggleLink.html( gM( 'mwe-upwiz-fewer-options' ) );
3098 - $toggleLink.addClass( "mwe-upwiz-toggler-open" );
3099 - } else {
3100 - moreDiv.maskSafeHide();
3101 - /* when closed, show control to open */
3102 - $toggleLink.html( gM( 'mwe-upwiz-more-options' ) );
3103 - $toggleLink.removeClass( "mwe-upwiz-toggler-open" );
3104 - }
3105 - };
3106 -
3107 - toggle(false);
3108 -
3109 - $toggleLink.click( function( e ) { e.stopPropagation(); toggle(); } );
3110 -
3111 - $j( moreDiv ).addClass( 'mwe-upwiz-toggled' );
3112 - },
3113 -
3114 - /**
3115 - * remove an item from an array. Tests for === identity to remove the item
3116 - * XXX the entire rationale for this file may be wrong.
3117 - * XXX The jQuery way would be to query the DOM for objects, not to keep a separate array hanging around
3118 - * @param items the array where we want to remove an item
3119 - * @param item the item to remove
3120 - */
3121 - removeItem: function( items, item ) {
3122 - for ( var i = 0; i < items.length; i++ ) {
3123 - if ( items[i] === item ) {
3124 - items.splice( i, 1 );
3125 - break;
3126 - }
3127 - }
3128 - },
3129 -
3130 - /**
3131 - * Capitalise first letter and replace spaces by underscores
3132 - * @param filename (basename, without directories)
3133 - * @return typical title as would appear on MediaWiki
3134 - */
3135 - pathToTitle: function ( filename ) {
3136 - return mw.ucfirst( $j.trim( filename ).replace(/ /g, '_' ) );
3137 - },
3138 -
3139 - /**
3140 - * Capitalise first letter and replace underscores by spaces
3141 - * @param title typical title as would appear on MediaWiki
3142 - * @return plausible local filename
3143 - */
3144 - titleToPath: function ( title ) {
3145 - return mw.ucfirst( $j.trim( title ).replace(/_/g, ' ' ) );
3146 - },
3147 -
3148 -
3149 - /**
3150 - * Transform "File:title_with_spaces.jpg" into "title with spaces"
3151 - * @param typical title that would appear on mediawiki, with File: and extension, may include underscores
3152 - * @return human readable title
3153 - */
3154 - fileTitleToHumanTitle: function( title ) {
3155 - var extension = mw.UploadWizardUtil.getExtension( title );
3156 - if ( typeof extension !== 'undefined' ) {
3157 - // the -1 is to get the '.'
3158 - title = title.substr( 0, title.length - extension.length - 1 );
3159 - }
3160 - // usually File:
3161 - var namespace = wgFormattedNamespaces[wgNamespaceIds['file']];
3162 - if ( title.indexOf( namespace + ':' ) === 0 ) {
3163 - title = title.substr( namespace.length + 1 );
3164 - }
3165 - return mw.UploadWizardUtil.titleToPath( title );
3166 - },
3167 -
3168 -
3169 - /**
3170 - * Slice extension off a path
3171 - * We assume that extensions are 1-4 characters in length
3172 - * @param path to file, like "foo/bar/baz.jpg"
3173 - * @return extension, like ".jpg" or undefined if it doesn't look lke an extension.
3174 - */
3175 - getExtension: function( path ) {
3176 - var extension = undefined;
3177 - var idx = path.lastIndexOf( '.' );
3178 - if (idx > 0 && ( idx > ( path.length - 5 ) ) && ( idx < ( path.length - 1 ) ) ) {
3179 - extension = path.substr( idx + 1 ).toLowerCase();
3180 - }
3181 - return extension;
3182 - },
3183 -
3184 - /**
3185 - * Last resort to guess a proper extension
3186 - */
3187 - mimetypeToExtension: {
3188 - 'image/jpeg': 'jpg',
3189 - 'image/gif': 'gif'
3190 - // fill as needed
3191 - }
3192 -
3193 -
3194 -};
3195 -
31962269 ( function( $j ) {
31972270
31982271 /**
@@ -3345,9 +2418,7 @@
33462419 */
33472420
33482421 }
3349 -
3350 - // XXX bind to a custom event in case the div size changes : ?
3351 -
 2422+ // XXX bind to a custom event in case the div size changes
33522423 } );
33532424
33542425 return this;
Index: branches/uploadwizard/extensions/UploadWizard/resources/mw.GroupProgressBar.js
@@ -0,0 +1,178 @@
 2+/**
 3+ * this is a progress bar for monitoring multiple objects, giving summary view
 4+ */
 5+mw.GroupProgressBar = function( selector, text, uploads, endState, progressProperty, weightProperty ) {
 6+ var _this = this;
 7+
 8+ // XXX need to figure out a way to put text inside bar
 9+ _this.$selector = $j( selector );
 10+ _this.$selector.html(
 11+ '<div class="mwe-upwiz-progress">'
 12+ + '<div class="mwe-upwiz-progress-bar-etr-container">'
 13+ + '<div class="mwe-upwiz-progress-bar-etr" style="display: none">'
 14+ + '<div class="mwe-upwiz-progress-bar"></div>'
 15+ + '<div class="mwe-upwiz-etr"></div>'
 16+ + '</div>'
 17+ + '</div>'
 18+ + '<div class="mwe-upwiz-count"></div>'
 19+ + '</div>'
 20+ );
 21+
 22+ _this.$selector.find( '.mwe-upwiz-progress-bar' ).progressbar( { value : 0 } );
 23+
 24+ _this.uploads = uploads;
 25+ _this.endState = endState;
 26+ _this.progressProperty = progressProperty;
 27+ _this.weightProperty = weightProperty;
 28+ _this.beginTime = undefined;
 29+
 30+};
 31+
 32+mw.GroupProgressBar.prototype = {
 33+
 34+ /**
 35+ * Show the progress bar with a slideout motion
 36+ */
 37+ showBar: function() {
 38+ this.$selector.find( '.mwe-upwiz-progress-bar-etr' ).fadeIn( 200 );
 39+ },
 40+
 41+ /**
 42+ * loop around the uploads, summing certain properties for a weighted total fraction
 43+ */
 44+ start: function() {
 45+ var _this = this;
 46+
 47+ var totalWeight = 0.0;
 48+ $j.each( _this.uploads, function( i, upload ) {
 49+ totalWeight += upload[_this.weightProperty];
 50+ } );
 51+
 52+ _this.setBeginTime();
 53+ var shown = false;
 54+
 55+ var displayer = function() {
 56+ var fraction = 0.0;
 57+ var endStateCount = 0;
 58+ var hasData = false;
 59+ $j.each( _this.uploads, function( i, upload ) {
 60+ if ( upload.state == _this.endState ) {
 61+ endStateCount++;
 62+ }
 63+ if (upload[_this.progressProperty] !== undefined) {
 64+ fraction += upload[_this.progressProperty] * ( upload[_this.weightProperty] / totalWeight );
 65+ if (upload[_this.progressProperty] > 0 ) {
 66+ hasData = true;
 67+ }
 68+ }
 69+ } );
 70+ //mw.log( 'hasdata:' + hasData + ' endstatecount:' + endStateCount );
 71+ // sometimes, the first data we have just tells us that it's over. So only show the bar
 72+ // if we have good data AND the fraction is less than 1.
 73+ if ( hasData && fraction < 1.0 ) {
 74+ if ( ! shown ) {
 75+ _this.showBar();
 76+ shown = true;
 77+ }
 78+ _this.showProgress( fraction );
 79+ }
 80+ _this.showCount( endStateCount );
 81+
 82+ if ( endStateCount < _this.uploads.length ) {
 83+ setTimeout( displayer, 200 );
 84+ } else {
 85+ _this.showProgress( 1.0 );
 86+ // not necessary to hide bar since we're going to the next step.
 87+ /* setTimeout( function() { _this.hideBar(); }, 500 ); */
 88+ }
 89+ };
 90+ displayer();
 91+ },
 92+
 93+
 94+ /**
 95+ * Hide the progress bar with a slideup motion
 96+ */
 97+ hideBar: function() {
 98+ this.$selector.find( '.mwe-upwiz-progress-bar-etr' ).fadeOut( 200 );
 99+ },
 100+
 101+ /**
 102+ * sets the beginning time (useful for figuring out estimated time remaining)
 103+ * if time parameter omitted, will set beginning time to now
 104+ *
 105+ * @param time optional; the time this bar is presumed to have started (epoch milliseconds)
 106+ */
 107+ setBeginTime: function( time ) {
 108+ this.beginTime = time ? time : ( new Date() ).getTime();
 109+ },
 110+
 111+
 112+ /**
 113+ * Show overall progress for the entire UploadWizard
 114+ * The current design doesn't have individual progress bars, just one giant one.
 115+ * We did some tricky calculations in startUploads to try to weight each individual file's progress against
 116+ * the overall progress.
 117+ * @param fraction the amount of whatever it is that's done whatever it's done
 118+ */
 119+ showProgress: function( fraction ) {
 120+ var _this = this;
 121+
 122+ _this.$selector.find( '.mwe-upwiz-progress-bar' ).progressbar( 'value', parseInt( fraction * 100, 10 ) );
 123+
 124+ var remainingTime = _this.getRemainingTime( fraction );
 125+
 126+ if ( remainingTime !== null ) {
 127+ var t = mw.seconds2Measurements( parseInt( remainingTime / 1000, 10 ) );
 128+ var timeString;
 129+ if (t.hours === 0) {
 130+ if (t.minutes === 0) {
 131+ if (t.seconds === 0) {
 132+ timeString = gM( 'mwe-upwiz-finished' );
 133+ } else {
 134+ timeString = gM( 'mwe-upwiz-secs-remaining', t.seconds );
 135+ }
 136+ } else {
 137+ timeString = gM( 'mwe-upwiz-mins-secs-remaining', t.minutes, t.seconds );
 138+ }
 139+ } else {
 140+ timeString = gM( 'mwe-upwiz-hrs-mins-secs-remaining', t.hours, t.minutes, t.seconds );
 141+ }
 142+ _this.$selector.find( '.mwe-upwiz-etr' ).html( timeString );
 143+ }
 144+ },
 145+
 146+ /**
 147+ * Calculate remaining time for all uploads to complete.
 148+ *
 149+ * @param fraction fraction of progress to show
 150+ * @return estimated time remaining (in milliseconds)
 151+ */
 152+ getRemainingTime: function ( fraction ) {
 153+ var _this = this;
 154+ if ( _this.beginTime ) {
 155+ var elapsedTime = ( new Date() ).getTime() - _this.beginTime;
 156+ if ( fraction > 0.0 && elapsedTime > 0 ) { // or some other minimums for good data
 157+ var rate = fraction / elapsedTime;
 158+ return parseInt( ( 1.0 - fraction ) / rate, 10 );
 159+ }
 160+ }
 161+ return null;
 162+ },
 163+
 164+
 165+ /**
 166+ * Show the overall count as we upload
 167+ * @param count -- the number of items that have done whatever has been done e.g. in "uploaded 2 of 5", this is the 2
 168+ */
 169+ showCount: function( count ) {
 170+ var _this = this;
 171+ _this.$selector
 172+ .find( '.mwe-upwiz-count' )
 173+ .html( gM( 'mwe-upwiz-upload-count', [ count, _this.uploads.length ] ) );
 174+ }
 175+
 176+
 177+};
 178+
 179+
Property changes on: branches/uploadwizard/extensions/UploadWizard/resources/mw.GroupProgressBar.js
___________________________________________________________________
Added: svn:eol-style
1180 + native

Status & tagging log