r84070 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r84069‎ | r84070 | r84071 >
Date:23:59, 15 March 2011
Author:dale
Status:deferred
Tags:
Comment:
improved firefogg support
improved getting encode settings from timedMediaHandler ( if available )
Modified paths:
  • /branches/uploadwizard-firefogg/UploadWizard.config.php (added) (history)
  • /branches/uploadwizard-firefogg/UploadWizardHooks.php (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.Api.edit.js (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.ApiUploadHandler.js (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.DestinationChecker.js (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.FirefoggHandler.js (added) (history)
  • /branches/uploadwizard-firefogg/resources/mw.FirefoggTransport.js (added) (history)
  • /branches/uploadwizard-firefogg/resources/mw.IframeTransport.js (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.Log.js (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.UploadWizard.js (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.UploadWizardDetails.js (modified) (history)
  • /branches/uploadwizard-firefogg/resources/mw.UploadWizardUploadInterface.js (added) (history)
  • /branches/uploadwizard-firefogg/resources/mw.UtilitiesTime.js (modified) (history)

Diff [purge]

Index: branches/uploadwizard-firefogg/UploadWizard.config.php
@@ -0,0 +1,126 @@
 2+<?php
 3+/**
 4+ * Upload Wizard Configuration
 5+ * Do not modify this file, instead use localsettings.php and set:
 6+ * $wgUploadWizardConfig[ 'name'] = 'value';
 7+ */
 8+global $wgFileExtensions, $wgServer, $wgScriptPath, $wgAPIModules,
 9+$wgTimedMediaHandlerFileExtensions, $wgAutoloadClasses;
 10+return array(
 11+ // Upload wizard has an internal debug flag
 12+ 'debug' => false,
 13+
 14+ // If the uploaded file should be auto categorized
 15+ 'autoCategory' => true,
 16+
 17+ // File extensions acceptable in this wiki
 18+ 'fileExtensions' => $wgFileExtensions,
 19+
 20+ // Check if we want to enable firefogg ( for transcoding )
 21+ 'enableFirefogg' => true,
 22+
 23+ // Check if we have the firefogg upload api module enabled:
 24+ 'enableFirefoggChunkUpload' => isset( $wgAPIModules['firefoggupload'] )? true : false,
 25+
 26+ // Firefogg encode settings ( if timed media handler extension is installed use HD webm, else mid-rage ogg )
 27+ 'firefoggEncodeSettings' => ( class_exists( 'WebVideoTranscode' ) )?
 28+ WebVideoTranscode::$derivativeSettings[ WebVideoTranscode::ENC_WEBM_HQ_VBR ] :
 29+ array(
 30+ 'maxSize' => '480',
 31+ 'videoBitrate' => '512',
 32+ 'audioBitrate' => '96',
 33+ 'noUpscaling' => 'true',
 34+ 'twopass' => 'true',
 35+ 'keyframeInterval' => '128',
 36+ 'bufDelay' => '256',
 37+ 'videoCodec' => 'theora',
 38+ ),
 39+
 40+ // The default api url is for the current wiki ( can override at run time )
 41+ 'apiUrl' => $wgServer . $wgScriptPath . '/api.php',
 42+
 43+ // The progress update interval for uploads
 44+ 'uploadProgressInterval' => 250,
 45+
 46+ // Default thumbnail width
 47+ 'thumbnailWidth' => 120,
 48+
 49+ // Max thumbnail height:
 50+ 'thumbnailMaxHeight' => 200,
 51+
 52+ // Min thumbnail width
 53+ 'smallThumbnailWidth' => 60,
 54+
 55+ // Small thumbnail max height
 56+ 'smallThumbnailMaxHeight' => 100,
 57+
 58+ // Icon thumbnail width:
 59+ 'iconThumbnailWidth' => 32,
 60+
 61+ // Icon thumbnail height:
 62+ 'iconThumbnailMaxHeight' => 32,
 63+
 64+ // Max author string length
 65+ 'maxAuthorLength' => 50,
 66+
 67+ // Min author string length
 68+ 'minAuthorLength' => 2,
 69+
 70+ // Max source string length
 71+ 'maxSourceLength' => 200,
 72+
 73+ // Min source string length
 74+ 'minSourceLength' => 5,
 75+
 76+ // Max file title string length
 77+ 'maxTitleLength' => 200,
 78+
 79+ // Min file title string length
 80+ 'minTitleLength' => 5,
 81+
 82+ // Max file description length
 83+ 'maxDescriptionLength' => 4096,
 84+
 85+ // Min file description length
 86+ 'minDescriptionLength' => 5,
 87+
 88+ // Max length for other file information:
 89+ 'maxOtherInformationLength' => 4096,
 90+
 91+ // Max number of simultaneous upload requests
 92+ 'maxSimultaneousConnections' => 1,
 93+
 94+ // Max number of uploads for a given form
 95+ 'maxUploads' => 10,
 96+
 97+ // not for use with all wikis.
 98+ // The ISO 639 code for the language tagalog is "tl".
 99+ // Normally we name templates for languages by the ISO 639 code.
 100+ // Commons already had a template called 'tl: though.
 101+ // so, this workaround will cause tagalog descriptions to be saved with this template instead.
 102+ 'languageTemplateFixups' => array( 'tl' => 'tgl' ),
 103+
 104+ // names of all license templates, in order. Case sensitive!
 105+ // n.b. in the future, the licenses for a wiki will probably be defined in PHP or even LocalSettings.
 106+ 'licenses' => array(
 107+ array( 'template' => 'Cc-by-sa-3.0','messageKey' => 'mwe-upwiz-license-cc-by-sa-3.0', 'default' => true ),
 108+ array( 'template' => 'Cc-by-3.0', 'messageKey' => 'mwe-upwiz-license-cc-by-3.0', 'default' => false ),
 109+ array( 'template' => 'Cc-zero', 'messageKey' => 'mwe-upwiz-license-cc-zero', 'default' => false ),
 110+ // n.b. the PD-US is only for testing purposes, obviously we need some geographical discrimination here...
 111+ array( 'template' => 'PD-US', 'messageKey' => 'mwe-upwiz-license-pd-us', 'default' => false ),
 112+ array( 'template' => 'GFDL', 'messageKey' => 'mwe-upwiz-license-gfdl', 'default' => false )
 113+ )
 114+
 115+ // XXX this is horribly confusing -- some file restrictions are client side, others are server side
 116+ // the filename prefix blacklist is at least server side -- all this should be replaced with PHP regex config
 117+ // or actually, in an ideal world, we'd have some way to reliably detect gibberish, rather than trying to
 118+ // figure out what is bad via individual regexes, we'd detect badness. Might not be too hard.
 119+ //
 120+ // we can export these to JS if we so want.
 121+ // filenamePrefixBlacklist: wgFilenamePrefixBlacklist,
 122+ //
 123+ // filenameRegexBlacklist: [
 124+ // /^(test|image|img|bild|example?[\s_-]*)$/, // test stuff
 125+ // /^(\d{10}[\s_-][0-9a-f]{10}[\s_-][a-z])$/ // flickr
 126+ // ]
 127+);
Index: branches/uploadwizard-firefogg/UploadWizardHooks.php
@@ -57,6 +57,11 @@
5858 // workhorse libraries
5959 'resources/mw.IframeTransport.js',
6060 'resources/mw.ApiUploadHandler.js',
 61+
 62+ // firefogg support
 63+ 'resources/mw.FirefoggHandler.js',
 64+ 'resources/mw.FirefoggTransport.js',
 65+
6166 'resources/mw.DestinationChecker.js',
6267 'resources/mw.UploadWizardUtil.js',
6368
@@ -64,9 +69,8 @@
6570 'resources/mw.GroupProgressBar.js',
6671
6772 // UploadWizard specific abstractions
68 - 'resources/mw.UploadWizardDeed.js',
6973 'resources/mw.UploadWizardLicenseInput.js',
70 -
 74+
7175 // main library
7276 'resources/mw.UploadWizard.js',
7377
Index: branches/uploadwizard-firefogg/resources/mw.FirefoggHandler.js
@@ -0,0 +1,105 @@
 2+/**
 3+ * An attempt to refactor out the stuff that does API-via-iframe transport
 4+ * In the hopes that this will eventually work for AddMediaWizard too
 5+ */
 6+
 7+/**
 8+ * Represents an object which configures a form to upload its files via an iframe talking to the MediaWiki API.
 9+ * @param an UploadInterface object, which contains a .form property which points to a real HTML form in the DOM
 10+ */
 11+mw.FirefoggHandler = function( upload ) {
 12+ return this.init( upload );
 13+};
 14+
 15+mw.FirefoggHandler.prototype = {
 16+ // The transport object
 17+ transport : null, // lazy init
 18+ /**
 19+ * Constructor
 20+ */
 21+ init: function( upload ){
 22+ this.upload = upload;
 23+ this.api = upload.api;
 24+ // update the mwe-upwiz-file-input target
 25+ this.upload.ui.$fileInputCtrl = this.getInputControl()
 26+ this.upload.ui.fileCtrlContainer.empty().append(
 27+ this.upload.ui.$fileInputCtrl
 28+ )
 29+ },
 30+ // Setup local pointer to firefogg instance
 31+ getFogg: function(){
 32+ if( ! this.fogg ){
 33+ this.fogg = new Firefogg();
 34+ }
 35+ return this.fogg;
 36+ },
 37+ getTransport: function(){
 38+ var _this = this;
 39+ if( !this.transport ){
 40+ this.transport = new mw.FirefoggTransport(
 41+ this.getForm(),
 42+ this.getFogg(),
 43+ function( fraction ) {
 44+ _this.upload.setTransportProgress( fraction );
 45+ // also update preview video:
 46+ },
 47+ function( result ) {
 48+ mw.log("FirefoggTransport::getTransport> Transport done " + JSON.stringify( result ) );
 49+ _this.upload.setTransported( result );
 50+ }
 51+ );
 52+ }
 53+ return this.transport;
 54+ },
 55+ isGoodExtension: function( ext ){
 56+ // First check if its an oky extension for the wiki:
 57+ if( $j.inArray( ext.toLowerCase(), mw.UploadWizard.config[ 'fileExtensions' ] ) !== -1 ){
 58+ return true;
 59+ }
 60+ // Check if its a file that can be transcoded:
 61+ if( this.getTransport().isSourceAudio() || this.getTransport().isSourceVideo() ){
 62+ return true;
 63+ }
 64+ return false;
 65+ },
 66+
 67+ getForm: function(){
 68+ return $j( this.upload.ui.form );
 69+ },
 70+
 71+ /**
 72+ * Get a pointer to the "file" input control
 73+ */
 74+ getInputControl: function(){
 75+ var _this = this;
 76+ return $j('<input />').attr({
 77+ 'size': "1",
 78+ 'name': "file",
 79+ 'type': "text"
 80+ })
 81+ .addClass( "mwe-upwiz-file-input" )
 82+ .click( function() {
 83+ if( _this.getFogg().selectVideo() ) {
 84+ // Update the value of the input file:
 85+ $j( this )
 86+ .val( _this.getFogg().sourceFilename )
 87+ //.trigger('change');
 88+ // note the change trigger does not work because we replace the target:
 89+ _this.upload.ui.fileChanged();
 90+ }
 91+ } );
 92+ },
 93+
 94+ /**
 95+ * If chunks are disabled transcode then upload else
 96+ * upload and transcode at the same time
 97+ */
 98+ start: function() {
 99+ var _this = this;
 100+ mw.log( "mw.FirefoggHandler::start> upload start!" );
 101+ _this.beginTime = ( new Date() ).getTime();
 102+ _this.upload.ui.setStatus( 'mwe-upwiz-transport-started' );
 103+ _this.upload.ui.showTransportProgress();
 104+ _this.getTransport().doUpload();
 105+ }
 106+};
Property changes on: branches/uploadwizard-firefogg/resources/mw.FirefoggHandler.js
___________________________________________________________________
Added: svn:mime-type
1107 + text/plain
Index: branches/uploadwizard-firefogg/resources/mw.UploadWizardUploadInterface.js
@@ -0,0 +1,349 @@
 2+/**
 3+ * Create an interface fragment corresponding to a file input, suitable for Upload Wizard.
 4+ * @param upload
 5+ * @param div to insert file interface
 6+ * @param addInterface interface to add a new one (assumed that we start out there)
 7+ */
 8+mw.UploadWizardUploadInterface = function( upload, filesDiv ) {
 9+ var _this = this;
 10+
 11+ _this.upload = upload;
 12+
 13+ // may need to collaborate with the particular upload type sometimes
 14+ // for the interface, as well as the uploadwizard. OY.
 15+ _this.div = $j('<div class="mwe-upwiz-file"></div>').get(0);
 16+ _this.isFilled = false;
 17+ _this.$fileInputCtrl = $j('<input size="1" class="mwe-upwiz-file-input" name="file" type="file"/>')
 18+ .change( function() {
 19+ _this.fileChanged();
 20+ } );
 21+
 22+ _this.$indicator = $j( '<div class="mwe-upwiz-file-indicator"></div>' );
 23+
 24+ visibleFilenameDiv = $j('<div class="mwe-upwiz-visible-file"></div>')
 25+ .append( _this.$indicator )
 26+ .append( '<div class="mwe-upwiz-visible-file-filename">'
 27+ + '<div class="mwe-upwiz-file-preview"/>'
 28+ + '<div class="mwe-upwiz-file-texts">'
 29+ + '<div class="mwe-upwiz-visible-file-filename-text"/>'
 30+ + '<div class="mwe-upwiz-file-status-line">'
 31+ + '<div class="mwe-upwiz-file-status mwe-upwiz-file-status-line-item"></div>'
 32+ + '</div>'
 33+ + '</div>'
 34+ + '</div>'
 35+ );
 36+
 37+ _this.$removeCtrl = $j.fn.removeCtrl(
 38+ 'mwe-upwiz-remove',
 39+ 'mwe-upwiz-remove-upload',
 40+ function() { _this.upload.remove(); }
 41+ ).addClass( "mwe-upwiz-file-status-line-item" );
 42+
 43+ visibleFilenameDiv.find( '.mwe-upwiz-file-status-line' )
 44+ .append( _this.$removeCtrl );
 45+
 46+ //_this.errorDiv = $j('<div class="mwe-upwiz-upload-error mwe-upwiz-file-indicator" style="display: none;"></div>').get(0);
 47+
 48+ _this.filenameCtrl = $j('<input type="hidden" name="filename" value=""/>').get(0);
 49+
 50+ // this file Ctrl container is placed over other interface elements, intercepts clicks and gives them to the file input control.
 51+ // however, we want to pass hover events to interface elements that we are over, hence the bindings.
 52+ // n.b. not using toggleClass because it often gets this event wrong -- relies on previous state to know what to do
 53+ _this.fileCtrlContainer = $j('<div class="mwe-upwiz-file-ctrl-container">');
 54+/*
 55+ .bind( 'mouseenter', function(e) { _this.addFileCtrlHover(e); } )
 56+ .bind( 'mouseleave', function(e) { _this.removeFileCtrlHover(e); } );
 57+*/
 58+
 59+
 60+ // the css trickery (along with css)
 61+ // here creates a giant size file input control which is contained within a div and then
 62+ // clipped for overflow. The effect is that we have a div (ctrl-container) we can position anywhere
 63+ // which works as a file input. It will be set to opacity:0 and then we can do whatever we want with
 64+ // interface "below".
 65+ // XXX caution -- if the add file input changes size we won't match, unless we add some sort of event to catch this.
 66+ _this.form = $j( '<form method="POST" encType="multipart/form-data" class="mwe-upwiz-form"></form>' )
 67+ .attr( { action: _this.upload.api.url } )
 68+ .append( visibleFilenameDiv )
 69+ .append( _this.fileCtrlContainer
 70+ .append( _this.$fileInputCtrl )
 71+ )
 72+ .append( _this.filenameCtrl )
 73+ .append( _this.thumbnailParam )
 74+ .get( 0 );
 75+
 76+
 77+ $j( _this.div ).append( _this.form );
 78+
 79+ // XXX evil hardcoded
 80+ // we don't really need filesdiv if we do it this way?
 81+ $j( filesDiv ).append( _this.div );
 82+
 83+ // _this.progressBar = ( no progress bar for individual uploads yet )
 84+ // we bind to the ui div since unbind doesn't work for non-DOM objects
 85+ $j( _this.div ).bind( 'transportProgressEvent', function(e) { _this.showTransportProgress(); } );
 86+ // $j( _this.div ).bind( 'transportedEvent', function(e) { _this.showStashed(); } );
 87+
 88+};
 89+
 90+
 91+mw.UploadWizardUploadInterface.prototype = {
 92+ /**
 93+ * Things to do to this interface once we start uploading
 94+ */
 95+ start: function() {
 96+ var _this = this;
 97+ // remove hovering
 98+ $j( _this.div )
 99+ .unbind( 'mouseenter mouseover mouseleave mouseout' );
 100+
 101+ // remove delete control
 102+ $j( _this.div )
 103+ .find( '.mwe-upwiz-remove-ctrl' )
 104+ .unbind( 'mouseenter mouseover mouseleave mouseout' )
 105+ .remove();
 106+ },
 107+
 108+ /**
 109+ * change the graphic indicator at the far end of the row for this file
 110+ * @param String statusClass: corresponds to a class mwe-upwiz-status which changes style of indicator.
 111+ */
 112+ showIndicator: function( statusClass ) {
 113+ this.clearIndicator();
 114+ // add the desired class and make it visible, if it wasn't already.
 115+ this.$indicator.addClass( 'mwe-upwiz-status-' + statusClass )
 116+ .css( 'visibility', 'visible' );
 117+ },
 118+
 119+ /**
 120+ * Reset the graphic indicator
 121+ */
 122+ clearIndicator: function() {
 123+ var _this = this;
 124+ $j.each( _this.$indicator.attr( 'class' ).split( /\s+/ ), function( i, className ) {
 125+ if ( className.match( /^mwe-upwiz-status/ ) ) {
 126+ _this.$indicator.removeClass( className );
 127+ }
 128+ } );
 129+ },
 130+
 131+ /**
 132+ * Set the preview image on the file page for this upload.
 133+ * @param HTMLImageElement
 134+ */
 135+ setPreview: function( image ) {
 136+ // encoding for url here?
 137+ $j( this.div ).find( '.mwe-upwiz-file-preview' ).css( 'background-image', 'url(' + image.src + ')' );
 138+ },
 139+
 140+ /**
 141+ * Set the status line for this upload with an internationalized message string.
 142+ * @param String msgKey: key for the message
 143+ * @param Array args: array of values, in case any need to be fed to the image.
 144+ */
 145+ setStatus: function( msgKey, args ) {
 146+ if ( !mw.isDefined( args ) ) {
 147+ args = [];
 148+ }
 149+ this.setStatusStr( gM( msgKey, args ) );
 150+ },
 151+
 152+ /**
 153+ * Set the status line for this upload
 154+ * @param String str: the string to use
 155+ */
 156+ setStatusStr: function( str ) {
 157+ $j( this.div ).find( '.mwe-upwiz-file-status' ).html( str ).show();
 158+ },
 159+
 160+ /**
 161+ * Clear the status line for this upload (hide it, in case there are paddings and such which offset other things.)
 162+ */
 163+ clearStatus: function() {
 164+ $j( this.div ).find( '.mwe-upwiz-file-status' ).hide();
 165+ },
 166+
 167+ /**
 168+ * Put the visual state of an individual upload ito "progress"
 169+ * @param fraction The fraction of progress. Float between 0 and 1
 170+ */
 171+ showTransportProgress: function( fraction ) {
 172+ // if fraction available, update individual progress bar / estimates, etc.
 173+ this.showIndicator( 'progress' );
 174+ this.setStatus( 'mwe-upwiz-uploading' );
 175+ },
 176+
 177+ /**
 178+ * Show that upload is transported
 179+ */
 180+ showStashed: function() {
 181+ this.$removeCtrl.detach();
 182+ this.$fileInputCtrl.detach();
 183+ this.showIndicator( 'stashed' );
 184+ this.setStatus( 'mwe-upwiz-stashed-upload' ); // this is just "OK", say something more.
 185+ },
 186+
 187+ /**
 188+ * Show that transport has failed
 189+ * @param String code: error code from API
 190+ * @param {String|Object} info: extra info
 191+ */
 192+ showError: function( code, info ) {
 193+ this.showIndicator( 'error' );
 194+ // is this an error that we expect to have a message for?
 195+ var msgKey = 'mwe-upwiz-api-error-unknown-code';
 196+ var args = [ code ];
 197+ if ( $j.inArray( code, mw.Api.errors ) !== -1 ) {
 198+ msgKey = 'mwe-upwiz-api-error-' + code;
 199+ // args may change base on particular error messages.
 200+ // for instance, we are throwing away the extra info right now. Might be nice to surface that in a debug mode
 201+ args = [];
 202+ }
 203+ this.setStatus( msgKey, args );
 204+ },
 205+
 206+ /**
 207+ * Run this when the value of the file input has changed. Check the file for various forms of goodness.
 208+ * If okay, then update the visible filename (due to CSS trickery the real file input is invisible)
 209+ */
 210+ fileChanged: function() {
 211+ var _this = this;
 212+ _this.clearErrors();
 213+ _this.upload.extractLocalFileInfo( _this.$fileInputCtrl.val() );
 214+ if ( _this.isGoodExtension( _this.upload.title.getExtension() ) ) {
 215+ _this.updateFilename();
 216+ } else {
 217+ //_this.error( 'bad-filename-extension', ext );
 218+ alert("bad extension");
 219+ }
 220+ this.clearStatus();
 221+ },
 222+
 223+ /**
 224+ * Move the file input to cover a certain element on the page.
 225+ * We use invisible file inputs because this is the only way to style a file input
 226+ * or otherwise get it to do what you want.
 227+ * It is helpful to sometimes move them to cover certain elements on the page, and
 228+ * even to pass events like hover
 229+ * @param selector jquery-compatible selector, for a single element
 230+ */
 231+ moveFileInputToCover: function( selector ) {
 232+ var $covered = $j( selector );
 233+
 234+ this.fileCtrlContainer
 235+ .css( $covered.position() )
 236+ .css( 'marginTop', $covered.css( 'marginTop' ) )
 237+ .css( 'marginRight', $covered.css( 'marginRight' ) )
 238+ .css( 'marginBottom', $covered.css( 'marginBottom' ) )
 239+ .css( 'marginLeft', $covered.css( 'marginLeft' ) )
 240+ .width( $covered.outerWidth() )
 241+ .height( $covered.outerHeight() );
 242+
 243+ this.fileCtrlContainer.css( { 'z-index': 1 } );
 244+
 245+ // shift the file input over with negative margins,
 246+ // internal to the overflow-containing div, so the div shows all button
 247+ // and none of the textfield-like input
 248+ this.$fileInputCtrl.css( {
 249+ 'margin-left': '-' + ~~( this.$fileInputCtrl.width() - $covered.outerWidth() - 10 ) + 'px',
 250+ 'margin-top' : '-' + ~~( this.$fileInputCtrl.height() - $covered.outerHeight() - 10 ) + 'px'
 251+ } );
 252+
 253+
 254+ },
 255+
 256+ /**
 257+ * this does two things:
 258+ * 1 ) since the file input has been hidden with some clever CSS ( to avoid x-browser styling issues ),
 259+ * update the visible filename
 260+ *
 261+ * 2 ) update the underlying "title" which we are targeting to add to mediawiki.
 262+ * TODO silently fix to have unique filename? unnecessary at this point...
 263+ */
 264+ updateFilename: function() {
 265+ var _this = this;
 266+ var path = _this.$fileInputCtrl.val();
 267+ // get basename of file; some browsers do this C:\fakepath\something
 268+ path = path.replace(/\w:.*\\(.*)$/,'$1');
 269+
 270+ // visible filename
 271+ $j( _this.form ).find( '.mwe-upwiz-visible-file-filename-text' ).html( path );
 272+
 273+ _this.upload.title = new mw.Title( mw.UploadWizardUtil.getBasename( path ), 'file' );
 274+ $j( _this.filenameCtrl ).val( _this.upload.title.getMain() );
 275+
 276+ if ( ! _this.isFilled ) {
 277+ var $div = $j( _this.div );
 278+ _this.isFilled = true;
 279+ $div.addClass( 'filled' );
 280+
 281+ // cover the div with the file input.
 282+ // we use the visible-file div because it has the same offsetParent as the file input
 283+ // the second argument offsets the fileinput to the right so there's room for the close icon to get mouse events
 284+ _this.moveFileInputToCover(
 285+ $div.find( '.mwe-upwiz-visible-file-filename-text' )
 286+ );
 287+
 288+ // Highlight the file on mouseover (and also show controls like the remove control).
 289+ //
 290+ // On Firefox there are bugs related to capturing mouse events on inputs, so we seem to miss the
 291+ // mouseenter or mouseleave events randomly. It's only really bad if we miss mouseleave,
 292+ // and have two highlights visible. so we add another call to REALLY make sure that other highlights
 293+ // are deactivated.
 294+ // http://code.google.com/p/fbug/issues/detail?id=2075
 295+ //
 296+ // ALSO: When file inputs are adjacent, Firefox misses the "mouseenter" and "mouseleave" events.
 297+ // Consequently we have to bind to "mouseover" and "mouseout" as well even though that's not as efficient.
 298+ $div.bind( 'mouseenter mouseover', function() {
 299+ $div.addClass( 'hover' );
 300+ $j( '#mwe-upwiz-filelist' )
 301+ .children()
 302+ .filter( function() { return this !== _this.div; } )
 303+ .removeClass('hover');
 304+ }, false );
 305+ $div.bind( 'mouseleave mouseout', function() {
 306+ $div.removeClass( 'hover' );
 307+ }, false );
 308+ $j( _this.div ).trigger( 'filled' );
 309+ } else {
 310+ $j( _this.div ).trigger( 'filenameAccepted' );
 311+ }
 312+ },
 313+
 314+ /**
 315+ * Remove any complaints we had about errors and such
 316+ * XXX this should be changed to something Theme compatible
 317+ */
 318+ clearErrors: function() {
 319+ var _this = this;
 320+ $j( _this.div ).removeClass( 'mwe-upwiz-upload-error ');
 321+ $j( _this.errorDiv ).hide().empty();
 322+ },
 323+
 324+ /**
 325+ * Show an error with the upload
 326+ */
 327+ error: function() {
 328+ var _this = this;
 329+ var args = Array.prototype.slice.call( arguments ); // copies arguments into a real array
 330+ var msg = 'mwe-upwiz-upload-error-' + args[0];
 331+ $j( _this.errorDiv ).append( $j( '<p class="mwe-upwiz-upload-error">' + gM( msg, args.slice( 1 ) ) + '</p>') );
 332+ // apply a error style to entire did
 333+ $j( _this.div ).addClass( 'mwe-upwiz-upload-error' );
 334+ $j( _this.errorDiv ).show();
 335+ },
 336+
 337+ /**
 338+ * This is used when checking for "bad" extensions in a filename.
 339+ * @param ext
 340+ * @return boolean if extension was acceptable
 341+ */
 342+ isGoodExtension: function( ext ) {
 343+ // ugly but we don't have a base "uploadHandler" class
 344+ if( this.upload.getUploadHandler().isGoodExtension ){
 345+ return this.upload.getUploadHandler().isGoodExtension( ext );
 346+ }
 347+ return $j.inArray( ext.toLowerCase(), mw.UploadWizard.config[ 'fileExtensions' ] ) !== -1;
 348+ }
 349+
 350+};
\ No newline at end of file
Property changes on: branches/uploadwizard-firefogg/resources/mw.UploadWizardUploadInterface.js
___________________________________________________________________
Added: svn:mime-type
1351 + text/plain
Index: branches/uploadwizard-firefogg/resources/mw.DestinationChecker.js
@@ -146,6 +146,7 @@
147147
148148 if ( data.query.pages[-1] ) {
149149 // No conflict found; this file name is unique
 150+ mw.log("mw.DestinationChecker::checkUnique> No pages in checkUnique result");
150151 result = { isUnique: true };
151152
152153 } else {
@@ -156,6 +157,8 @@
157158 }
158159
159160 // Conflict found, this filename is NOT unique
 161+ mw.log( "mw.DestinationChecker::checkUnique> conflict! " );
 162+
160163 var ntitle;
161164 if ( data.query.normalized ) {
162165 ntitle = data.query.normalized[0].to;
Index: branches/uploadwizard-firefogg/resources/mw.UtilitiesTime.js
@@ -15,7 +15,8 @@
1616 */
1717 mw.seconds2npt = function( sec, show_ms ) {
1818 if ( isNaN( sec ) ) {
19 - sec = 0;
 19+ mw.log("mw.seconds2npt> Warning: trying to get npt time on NaN:" + sec);
 20+ return '0:00:00';
2021 }
2122
2223 var tm = mw.seconds2Measurements( sec );
@@ -65,7 +66,8 @@
6667 */
6768 mw.npt2seconds = function ( npt_str ) {
6869 if ( !npt_str ) {
69 - return undefined;
 70+ // mw.log('npt2seconds:not valid ntp:'+ntp);
 71+ return false;
7072 }
7173 // Strip {npt:}01:02:20 or 32{s} from time if present
7274 npt_str = npt_str.replace( /npt:|s/g, '' );
Index: branches/uploadwizard-firefogg/resources/mw.Api.edit.js
@@ -1,5 +1,7 @@
22 // library to assist with edits
33
 4+// dependencies: [ mw.Api, jQuery ]
 5+
46 ( function( mw, $ ) {
57
68 // cached token so we don't have to keep fetching new ones for every single post
@@ -17,27 +19,36 @@
1820 */
1921 postWithEditToken: function( params, ok, err ) {
2022 var api = this;
 23+ var _method = 'mw.api.edit::postWithEditToken> ';
 24+ mw.log( 'post with edit token' );
2125 if ( cachedToken === null ) {
 26+ mw.log( _method + 'no cached token' );
2227 // We don't have a valid cached token, so get a fresh one and try posting.
2328 // We do not trap any 'badtoken' or 'notoken' errors, because we don't want
2429 // an infinite loop. If this fresh token is bad, something else is very wrong.
2530 var useTokenToPost = function( token ) {
 31+ mw.log( _method + 'posting with token = ' + token );
2632 params.token = token;
2733 this.post( params, ok, err );
2834 };
 35+ mw.log( _method + 'getting edit token' );
2936 api.getEditToken( useTokenToPost, err );
3037 } else {
3138 // We do have a token, but it might be expired. So if it is 'bad' then
3239 // start over with a new token.
3340 params.token = cachedToken;
 41+ mw.log( _method + 'we do have a token = ' + params.token );
3442 var getTokenIfBad = function( code, result ) {
 43+ mw.log( _method + "error with posting with token!" );
3544 if ( code === 'badtoken' ) {
 45+ mw.log( _method + "bad token; try again" );
3646 cachedToken = null; // force a new token
3747 api.postWidthEditToken( params, ok, err );
3848 } else {
3949 err( code, result );
4050 }
4151 };
 52+ mw.log ( _method + "posting with the token that was cached " );
4253 api.post( params, ok, getTokenIfBad );
4354 }
4455 },
Index: branches/uploadwizard-firefogg/resources/mw.FirefoggTransport.js
@@ -0,0 +1,247 @@
 2+/**
 3+ * Represents a "transport" for files to upload; in this case an firefogg.
 4+ * XXX dubious whether this is really separated from "ApiUploadHandler", which does a lot of form config.
 5+ *
 6+ * 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.
 7+ * @param form jQuery selector for HTML form
 8+ * @param progressCb callback to execute when we've started. (does not do float here because iframes can't
 9+ * monitor fractional progress).
 10+ * @param transportedCb callback to execute when we've finished the upload
 11+ */
 12+mw.FirefoggTransport = function( $form, fogg, progressCb, transportedCb ) {
 13+ this.$form = $form;
 14+ this.fogg = fogg;
 15+ this.progressCb = progressCb;
 16+ this.transportedCb = transportedCb;
 17+};
 18+
 19+mw.FirefoggTransport.prototype = {
 20+
 21+ passthrough: false,
 22+ /**
 23+ * Do an upload on a given fogg object:
 24+ */
 25+ doUpload: function(){
 26+ // check if the server supports chunks:
 27+ if( this.isChunkUpload() ){
 28+ mw.log("FirefoggTransport::doUpload> Chunks");
 29+ // encode and upload at the same time:
 30+ this.doChunkUpload();
 31+ } else {
 32+ mw.log("FirefoggTransport::doUpload> Encode then upload");
 33+ this.doEncodeThenUpload();
 34+ }
 35+ },
 36+ isChunkUpload: function(){
 37+ return false;
 38+ return ( mw.UploadWizard.config[ 'enableFirefoggChunkUpload' ] );
 39+ },
 40+ /**
 41+ * Check if the asset should be uploaded in passthrough mode ( or if it should be encoded )
 42+ */
 43+ isPassThrough: function(){
 44+ // Check if the server supports raw webm uploads:
 45+ var wembExt = ( $j.inArray( mw.UploadWizard.config[ 'fileExtensions'], 'webm') !== -1 )
 46+ // Determine passthrough mode
 47+ if ( this.isOggFormat() || ( wembExt && isWebMFormat() ) ) {
 48+ // Already Ogg, no need to encode
 49+ return true;
 50+ } else if ( this.isSourceAudio() || this.isSourceVideo() ) {
 51+ // OK to encode
 52+ return false;
 53+ } else {
 54+ // Not audio or video, can't encode
 55+ return true;
 56+ }
 57+ },
 58+
 59+ isSourceAudio: function() {
 60+ return ( this.getSourceFileInfo().contentType.indexOf("audio/") != -1 );
 61+ },
 62+
 63+ isSourceVideo: function() {
 64+ return ( this.getSourceFileInfo().contentType.indexOf("video/") != -1 );
 65+ },
 66+
 67+ isOggFormat: function() {
 68+ var contentType = this.getSourceFileInfo().contentType;
 69+ return ( contentType.indexOf("video/ogg") != -1
 70+ || contentType.indexOf("application/ogg") != -1
 71+ || contentType.indexOf("audio/ogg") != -1);
 72+ },
 73+ isWebMFormat: function() {
 74+ return ( this.getSourceFileInfo().contentType.indexOf('webm') != -1 );
 75+ },
 76+
 77+ /**
 78+ * Get the source file info for the current file selected into this.fogg
 79+ */
 80+ getSourceFileInfo: function() {
 81+ if ( !this.fogg.sourceInfo ) {
 82+ mw.log( 'Error:: No firefogg source info is available' );
 83+ return false;
 84+ }
 85+ try {
 86+ this.sourceFileInfo = JSON.parse( this.fogg.sourceInfo );
 87+ } catch ( e ) {
 88+ mw.log( 'Error :: could not parse fogg sourceInfo' );
 89+ return false;
 90+ }
 91+ return this.sourceFileInfo;
 92+ },
 93+
 94+ // Get the filename
 95+ getFileName: function(){
 96+ // If passthrough don't change it
 97+ if( this.isPassThrough() ){
 98+ return this.fogg.sourceFilename;
 99+ } else {
 100+ if( this.isSourceAudio() ){
 101+ return this.fogg.sourceFilename.split('.').slice(0,-1).join('.') + '.oga';
 102+ }
 103+ if( this.isSourceVideo() ){
 104+ return this.fogg.sourceFilename.split('.').slice(0,-1).join('.') + '.webm';
 105+ }
 106+ }
 107+ },
 108+ getEncodeExt: function(){
 109+ if( this.getEncodeSettings()['videoCodec']
 110+ &&
 111+ this.getEncodeSettings()['videoCodec'] == 'vp8' )
 112+ {
 113+ return 'webm';
 114+ } else {
 115+ return 'ogv';
 116+ }
 117+ },
 118+ /**
 119+ * Get the encode settings from configuration and the current selected video type
 120+ */
 121+ getEncodeSettings: function(){
 122+ var encodeSettings = $j.extend( {}, mw.UploadWizard.config[ 'firefoggEncodeSettings'] , {
 123+ 'passthrough' : this.isPassThrough()
 124+ });
 125+ // Update the format:
 126+ this.fogg.setFormat( ( this.getEncodeExt == 'webm' )? 'webm' : 'ogg' );
 127+
 128+ mw.log("FirefoggTransport::getEncodeSettings> " + JSON.stringify( encodeSettings ) );
 129+ return encodeSettings;
 130+ },
 131+
 132+ /**
 133+ * Encode then upload
 134+ */
 135+ doEncodeThenUpload: function(){
 136+ // If doing passthrough jump direct to upload:
 137+ if( this.isPassThrough() ){
 138+ this.doFoggPost();
 139+ return ;
 140+ }
 141+ this.fogg.encode( JSON.stringify( this.getEncodeSettings() ) );
 142+
 143+ this.monitorProgress();
 144+ },
 145+
 146+ /**
 147+ * do fogg post
 148+ */
 149+ doFoggPost: function(){
 150+ var _this = this;
 151+ // Get the upload request with a callback ( populates the request token )
 152+ this.getUploadRequest( function( request ){
 153+ mw.log("FirefoggTransport::doFoggPost> " + _this.getUploadUrl() + ' req:' +
 154+ JSON.stringify( request ) );
 155+
 156+ _this.fogg.post( _this.getUploadUrl(),
 157+ 'file',
 158+ JSON.stringify( request )
 159+ );
 160+ _this.monitorProgress();
 161+ } );
 162+ },
 163+ /**
 164+ * Encode and upload in chunks
 165+ */
 166+ doChunkUpload: function(){
 167+ var _this = this;
 168+ this.getUploadRequest( function( request ){
 169+ this.fogg.upload(
 170+ JSON.stringify( _this.getEncodeSettings() ),
 171+ _this.getUploadUrl(),
 172+ JSON.stringify( request )
 173+ );
 174+ });
 175+ _this.monitorProgress();
 176+ },
 177+ /**
 178+ * Get the upload url
 179+ */
 180+ getUploadUrl: function(){
 181+ return mw.UploadWizard.config['apiUrl'];
 182+ },
 183+
 184+ /**
 185+ * Get the upload settings
 186+ * @param {function} callback function to send the request object
 187+ */
 188+ getUploadRequest: function( callback ){
 189+ var _this = this;
 190+ // ugly probably would be nice to have base refrence to the upload class so we can use the
 191+ new mw.Api( {
 192+ 'url' : _this.getUploadUrl()
 193+ } )
 194+ .getEditToken( function( token ) {
 195+ callback( {
 196+ 'action' : ( _this.isChunkUpload() )? 'firefoggupload' : 'upload',
 197+ 'stash' :1,
 198+ 'comment' : 'DUMMY TEXT',
 199+ 'format' : 'json',
 200+ 'filename' : _this.getFileName(),
 201+ 'token' : token
 202+ } );
 203+ }, function( code, info ) {
 204+ _this.upload.setError( code, info );
 205+ } );
 206+ },
 207+ /**
 208+ * Monitor progress on an upload:
 209+ */
 210+ monitorProgress: function(){
 211+ var _this = this;
 212+ var fogg = this.fogg;
 213+ var progress = fogg.progress();
 214+ var state = fogg.state;
 215+
 216+ mw.log("FirefoggTransport::monitorProgress> " + progress + ' state: ' + state + ' status: ' + this.fogg.status() + ' rt: ' + this.getResponseText() );
 217+ this.progressCb( progress );
 218+
 219+ if( state == 'encoding done' && ! this.isChunkUpload() ){
 220+ // ( if encoding done, we are in a two step encode then upload process )
 221+ this.doFoggPost();
 222+ return ;
 223+ }
 224+ // If state is 'in progress' ... fire monitor progress
 225+ if( state == 'encoding' || state == 'uploading' || state == '' ){
 226+ setTimeout( function(){
 227+ _this.monitorProgress();
 228+ }, mw.UploadWizard.config['uploadProgressInterval'] );
 229+ }
 230+ // return the api result:
 231+ if( state == 'done' || state == 'upload done' ){
 232+ this.transportedCb( this.getResponseText() );
 233+ }
 234+
 235+ },
 236+
 237+ getResponseText: function(){
 238+ var _this = this;
 239+ try {
 240+ var pstatus = JSON.parse( _this.fogg.uploadstatus() );
 241+ return pstatus["responseText"];
 242+ } catch( e ) {
 243+ mw.log( "Error:: Firefogg could not parse uploadstatus / could not get responseText: " + e );
 244+ }
 245+ }
 246+};
 247+
 248+
Property changes on: branches/uploadwizard-firefogg/resources/mw.FirefoggTransport.js
___________________________________________________________________
Added: svn:mime-type
1249 + text/plain
Index: branches/uploadwizard-firefogg/resources/mw.UploadWizard.js
@@ -22,17 +22,17 @@
2323 this.transportWeight = 1; // default
2424 this.detailsWeight = 1; // default
2525
26 - // details
 26+ // details
2727 this.ui = new mw.UploadWizardUploadInterface( this, filesDiv );
2828
2929 // handler -- usually ApiUploadHandler
30 - // this.handler = new ( mw.UploadWizard.config[ 'uploadHandlerClass' ] )( this );
31 - // this.handler = new mw.MockUploadHandler( this );
32 - this.handler = new mw.ApiUploadHandler( this, api );
 30+ this.handler = this.getUploadHandler();
3331 };
3432
3533 mw.UploadWizardUpload.prototype = {
36 -
 34+ // Upload handler for the UploadWizardUpload
 35+ uploadHandler: null, // lazy init
 36+
3737 acceptDeed: function( deed ) {
3838 var _this = this;
3939 _this.deed.applyDeed( _this );
@@ -49,7 +49,7 @@
5050 },
5151
5252 /**
53 - * remove this upload. n.b. we trigger a removeUpload this is usually triggered from
 53+ * Remove this upload. n.b. we trigger a removeUpload this is usually triggered from
5454 */
5555 remove: function() {
5656 this.state = 'aborted';
@@ -95,10 +95,11 @@
9696 setTransported: function( result ) {
9797 var _this = this;
9898 if ( _this.state == 'aborted' ) {
99 - return;
 99+ return ;
100100 }
101101
102102 if ( result.upload && result.upload.imageinfo ) {
 103+ mw.log( 'UploadWizard::setTransported> process api imageinfo' );
103104 // success
104105 _this.state = 'transported';
105106 _this.transportProgress = 1;
@@ -106,7 +107,7 @@
107108 _this.extractUploadInfo( result );
108109
109110 // use blocking preload for thumbnail, no loading spinner.
110 - _this.getThumbnail(
 111+ _this.getThumbnail(
111112 function( image ) {
112113 _this.ui.setPreview( image );
113114 _this.deedPreview.setup();
@@ -199,8 +200,27 @@
200201 */
201202 }
202203 },
203 -
204204 /**
 205+ * Set the upload handler per browser capabilities
 206+ */
 207+ getUploadHandler: function(){
 208+ if( !this.uploadHandler ){
 209+ if( typeof( Firefogg ) != 'undefined'
 210+ &&
 211+ mw.UploadWizard.config[ 'enableFirefogg' ]
 212+ ) {
 213+ mw.log("mw.UploadWizard::getUploadHandler> FirefoggHandler");
 214+ this.uploadHandler = new mw.FirefoggHandler( this );
 215+ } else {
 216+ // By default use the apiUploadHandler
 217+ mw.log("mw.UploadWizard::getUploadHandler> ApiUploadHandler");
 218+ this.uploadHandler = new mw.ApiUploadHandler( this );
 219+ }
 220+ }
 221+ return this.uploadHandler;
 222+ },
 223+
 224+ /**
205225 * Fetch a thumbnail for a stashed upload of the desired width.
206226 * It is assumed you don't call this until it's been transported.
207227 *
@@ -262,7 +282,7 @@
263283
264284 var _this = this;
265285 if ( typeof width === 'undefined' || width === null || width <= 0 ) {
266 - width = mw.UploadWizard.config[ 'thumbnailWidth' ];
 286+ width = mw.UploadWizard.config[ 'thumbnailWidth' ];
267287 }
268288 width = parseInt( width, 10 );
269289 height = null;
@@ -319,38 +339,6 @@
320340 stepNames: [ 'tutorial', 'file', 'deeds', 'details', 'thanks' ],
321341 currentStepName: undefined,
322342
323 - /*
324 - // list possible upload handlers in order of preference
325 - // these should all be in the mw.* namespace
326 - // hardcoded for now. maybe some registry system might work later, like, all
327 - // things which subclass off of UploadHandler
328 - uploadHandlers: [
329 - 'FirefoggUploadHandler',
330 - 'XhrUploadHandler',
331 - 'ApiIframeUploadHandler',
332 - 'SimpleUploadHandler',
333 - 'NullUploadHandler'
334 - ],
335 -
336 - * We can use various UploadHandlers based on the browser's capabilities. Let's pick one.
337 - * For example, the ApiUploadHandler should work just about everywhere, but XhrUploadHandler
338 - * allows for more fine-grained upload progress
339 - * @return valid JS upload handler class constructor function
340 - getUploadHandlerClass: function() {
341 - // return mw.MockUploadHandler;
342 - return mw.ApiUploadHandler;
343 - var _this = this;
344 - for ( var i = 0; i < uploadHandlers.length; i++ ) {
345 - var klass = mw[uploadHandlers[i]];
346 - if ( klass != undefined && klass.canRun( this.config )) {
347 - return klass;
348 - }
349 - }
350 - // this should never happen; NullUploadHandler should always work
351 - return null;
352 - },
353 - */
354 -
355343 /**
356344 * Reset the entire interface so we can upload more stuff
357345 * Depending on whether we split uploading / detailing, it may actually always be as simple as loading a URL
@@ -594,9 +582,13 @@
595583 $j( upload.ui.div ).bind( 'filenameAccepted', function(e) { _this.updateFileCounts(); e.stopPropagation(); } );
596584 $j( upload.ui.div ).bind( 'removeUploadEvent', function(e) { _this.removeUpload( upload ); e.stopPropagation(); } );
597585 $j( upload.ui.div ).bind( 'filled', function(e) {
 586+ mw.log( "mw.UploadWizardUpload::newUpload> filled! received!" );
598587 _this.newUpload();
 588+ mw.log( "mw.UploadWizardUpload::newUpload> filled! new upload!" );
599589 _this.setUploadFilled(upload);
 590+ mw.log( "mw.UploadWizardUpload::newUpload> filled! set upload filled!" );
600591 e.stopPropagation();
 592+ mw.log( "mw.UploadWizardUpload::newUpload> filled! stop propagation!" );
601593 } );
602594 // XXX bind to some error state
603595
Index: branches/uploadwizard-firefogg/resources/mw.UploadWizardDetails.js
@@ -463,6 +463,7 @@
464464 */
465465 populate: function() {
466466 var _this = this;
 467+ mw.log( "mw.UploadWizardUpload::populate> populating details from upload" );
467468 _this.upload.setThumbnail( _this.thumbnailDiv, mw.UploadWizard.config['thumbnailWidth'], mw.UploadWizard.config['thumbnailMaxHeight'] );
468469 _this.prefillDate();
469470 _this.prefillSource();
@@ -712,6 +713,7 @@
713714
714715 // XXX check state of details for okayness ( license selected, at least one desc, sane filename )
715716 var wikiText = _this.getWikiText();
 717+ mw.log( "mw.UploadWizardUpload::submit> submiting wikiText:\n" + wikiText );
716718
717719 var params = {
718720 action: 'upload',
@@ -726,7 +728,10 @@
727729 _this.completeDetailsSubmission();
728730 };
729731
 732+ mw.log( "mw.UploadWizardUpload::submit> uploading: \n" + params );
730733 var callback = function( result ) {
 734+ mw.log( "mw.UploadWizardUpload::submit> result:\n" + result );
 735+ mw.log( "mw.UploadWizardUpload::submit> successful upload" );
731736 finalCallback( result );
732737 };
733738
@@ -735,6 +740,41 @@
736741 _this.upload.api.postWithEditToken( params, callback );
737742 },
738743
 744+
 745+ /**
 746+ * Get new image info, for instance, after we renamed... or? published? an image
 747+ * XXX deprecated?
 748+ * XXX move to mw.API
 749+ *
 750+ * @param upload an UploadWizardUpload object
 751+ * @param title title to look up remotely
 752+ * @param endCallback execute upon completion
 753+ */
 754+ getImageInfo: function( upload, callback ) {
 755+ var params = {
 756+ 'titles': upload.title.toString(),
 757+ 'prop': 'imageinfo',
 758+ 'iiprop': 'timestamp|url|user|size|sha1|mime|metadata'
 759+ };
 760+ // XXX timeout callback?
 761+ this.api.get( params, function( data ) {
 762+ if ( data && data.query && data.query.pages ) {
 763+ if ( ! data.query.pages[-1] ) {
 764+ for ( var page_id in data.query.pages ) {
 765+ var page = data.query.pages[ page_id ];
 766+ if ( ! page.imageinfo ) {
 767+ alert("unimplemented error check, missing imageinfo");
 768+ // XXX not found? error
 769+ } else {
 770+ upload.extractImageInfo( page.imageinfo[0] );
 771+ }
 772+ }
 773+ }
 774+ }
 775+ callback();
 776+ } );
 777+ },
 778+
739779 completeDetailsSubmission: function() {
740780 var _this = this;
741781 _this.upload.state = 'complete';
Index: branches/uploadwizard-firefogg/resources/mw.ApiUploadHandler.js
@@ -10,9 +10,9 @@
1111 * Represents an object which configures a form to upload its files via an iframe talking to the MediaWiki API.
1212 * @param an UploadInterface object, which contains a .form property which points to a real HTML form in the DOM
1313 */
14 -mw.ApiUploadHandler = function( upload, api ) {
 14+mw.ApiUploadHandler = function( upload ) {
1515 this.upload = upload;
16 - this.api = api;
 16+ this.api = upload.api;
1717 this.$form = $j( this.upload.ui.form );
1818 this.configureForm();
1919
@@ -39,6 +39,7 @@
4040 */
4141 configureForm: function() {
4242 var _this = this;
 43+ mw.log( "configuring form for Upload API" );
4344
4445 _this.addFormInputIfMissing( 'action', 'upload' );
4546
@@ -50,8 +51,14 @@
5152
5253 // we use JSON in HTML because according to mdale, some browsers cannot handle just JSON
5354 _this.addFormInputIfMissing( 'format', 'jsonfm' );
54 - },
55 -
 55+
 56+ // XXX only for testing, so it stops complaining about dupes
 57+ /*
 58+ if ( mw.UploadWizard.DEBUG ) {
 59+ _this.addFormInputIfMissing( 'ignorewarnings', '1' );
 60+ }
 61+ */
 62+ },
5663 /**
5764 * Modify our form to have a fresh edit token.
5865 * If successful, return true to a callback.
@@ -85,6 +92,7 @@
8693 start: function() {
8794 var _this = this;
8895 var ok = function() {
 96+ mw.log( "api: upload start!" );
8997 _this.beginTime = ( new Date() ).getTime();
9098 _this.upload.ui.setStatus( 'mwe-upwiz-transport-started' );
9199 _this.upload.ui.showTransportProgress();
Index: branches/uploadwizard-firefogg/resources/mw.IframeTransport.js
@@ -42,20 +42,21 @@
4343 * Ensure callback on completion of upload
4444 */
4545 configureForm: function() {
 46+ mw.log( "mw.IframeTransport::configureForm> configuring form for iframe transport" );
4647 // Set the form target to the iframe
4748 this.$form.attr( 'target', this.iframeId );
4849
4950 // attach an additional handler to the form, so, when submitted, it starts showing the progress
5051 // XXX this is lame .. there should be a generic way to indicate busy status...
5152 this.$form.submit( function() {
52 - //mw.log( "mw.IframeTransport::configureForm> submitting to iframe..." );
 53+ mw.log( "mw.IframeTransport::configureForm> submitting to iframe..." );
5354 return true;
5455 } );
5556
5657 // Set up the completion callback
5758 var _this = this;
5859 $j( '#' + this.iframeId ).load( function() {
59 - //mw.log( "mw.IframeTransport::configureForm> received result in iframe" );
 60+ mw.log( "mw.IframeTransport::configureForm> received result in iframe" );
6061 _this.progressCb( 1.0 );
6162 _this.processIframeResult( $j( this ).get( 0 ) );
6263 } );
@@ -72,13 +73,13 @@
7374 var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document;
7475 // Fix for Opera 9.26
7576 if ( doc.readyState && doc.readyState != 'complete' ) {
76 - //mw.log( "mw.IframeTransport::processIframeResult> not complete" );
 77+ mw.log( "mw.IframeTransport::processIframeResult> not complete" );
7778 return;
7879 }
7980
8081 // Fix for Opera 9.64
8182 if ( doc.body && doc.body.innerHTML == "false" ) {
82 - //mw.log( "mw.IframeTransport::processIframeResult> innerhtml" );
 83+ mw.log( "mw.IframeTransport::processIframeResult> innerhtml" );
8384 return;
8485 }
8586 var response;
@@ -91,7 +92,7 @@
9293 // according to mdale we need to do this
9394 // because IE does not load JSON properly in an iframe
9495 json = $j( doc.body ).find( 'pre' ).text();
95 - // mw.log( "mw.IframeTransport::processIframeResult> iframe:json::" + json );
 96+ mw.log( "mw.IframeTransport::processIframeResult> iframe:json::" + json );
9697 // check that the JSON is not an XML error message
9798 // (this happens when user aborts upload, we get the API docs in XML wrapped in HTML)
9899 if ( json && json.substring(0, 5) !== '<?xml' ) {
Index: branches/uploadwizard-firefogg/resources/mw.Log.js
@@ -2,43 +2,43 @@
33
44 ( function( mw, $j ) {
55
6 - function pad( d, n ) {
7 - var s = d.toString(); return s.length == n ? s : pad( '0' + s, n );
8 - }
9 -
106 /**
11 - * Log a string msg to the console
12 - *
13 - * @param {String} string String to output to console
14 - */
 7+ * Log a string msg to the console
 8+ *
 9+ * @param {String} string String to output to console
 10+ */
1511 mw.log = function( s, level ) {
1612
1713 if ( typeof level === 'undefined' ) {
18 - level = mw.log.INFO;
 14+ level = 30;
1915 }
2016
2117 if ( level > mw.log.level ) {
2218 return;
2319 }
 20+
 21+ // Add any prepend debug ss if necessary
 22+ if ( mw.log.preAppendLog ) {
 23+ s = mw.log.preAppendLog + s;
 24+ }
2425
2526 if ( typeof window.console !== 'undefined' && typeof window.console.log === 'function' ) {
2627 window.console.log( s );
2728 } else {
28 - // Set timestamp
29 - var d = new Date();
30 - var time = ( pad( d.getHours(), 2 ) + ':' + pad( d.getMinutes(), 2 ) + pad( d.getSeconds(), 2 ) + pad( d.getMilliseconds(), 3 ) );
 29+/*
3130 // Show a log box for console-less browsers
3231 var $log = $( '#mw-log-console' );
3332 if ( !$log.length ) {
3433 $log = $( '<div id="mw-log-console"></div>' )
3534 .css( {
36 - 'position': 'fixed',
 35+ 'position': 'absolute',
3736 'overflow': 'auto',
3837 'z-index': 500,
3938 'bottom': '0px',
4039 'left': '0px',
4140 'right': '0px',
42 - 'height': '150px',
 41+ 'height': '100px',
 42+ 'width': '100%',
4343 'background-color': 'white',
4444 'border-top': 'solid 2px #ADADAD'
4545 } )
@@ -52,22 +52,13 @@
5353 'font-family': 'monospace',
5454 'padding': '0.125em 0.25em'
5555 } )
56 - .text( string )
57 - .append( '<span style="float:right">[' + time + ']</span>' )
 56+ .text( s )
5857 );
 58+*/
5959 }
6060 };
6161
62 - /**
63 - * Convenience function for logging cases where you want a prefix, or to log at a particular level.
64 - */
65 - mw.log.logger = function( prefix, level ) {
66 - return function( s ) {
67 - mw.log( prefix + '> ' + s, level );
68 - }
69 - };
70 -
71 - mw.log.SILENT = 0;
 62+ mw.log.level = mw.log.NONE = 0;
7263 mw.log.FATAL = 10;
7364 mw.log.WARN = 20;
7465 mw.log.INFO = 30;
@@ -82,7 +73,6 @@
8374 mw.log.info = function( s ) {
8475 mw.log( s, mw.log.INFO );
8576 };
86 -
8777 mw.log.level = mw.log.ALL;
8878
8979 } )( window.mediaWiki, jQuery );

Status & tagging log