mw.ForeignStructuredUpload.BookletLayout.parent.prototype.initialize.call( this )
.done( function () {
// Point the CategorySelector to the right wiki
- this.upload.apiPromise.done( function ( api ) {
+ this.upload.getApi().done( function ( api ) {
// If this is a ForeignApi, it will have a apiUrl, otherwise we don't need to do anything
if ( api.apiUrl ) {
// Can't reuse the same object, CategorySelector calls #abort on its mw.Api instance
this.selectFileWidget.on( 'change', onUploadFormChange.bind( this ) );
this.ownWorkCheckbox.on( 'change', onUploadFormChange.bind( this ) );
+ this.selectFileWidget.on( 'change', function () {
+ var file = layout.getFile();
+
+ // Set the date to lastModified once we have the file
+ if ( layout.getDateFromLastModified( file ) !== undefined ) {
+ layout.dateWidget.setValue( layout.getDateFromLastModified( file ) );
+ }
+
+ // Check if we have EXIF data and set to that where available
+ layout.getDateFromExif( file ).done( function ( date ) {
+ layout.dateWidget.setValue( date );
+ } );
+ } );
+
return this.uploadForm;
};
multiline: true,
autosize: true
} );
- this.dateWidget = new mw.widgets.DateInputWidget( {
- $overlay: this.$overlay,
- required: true,
- mustBeBefore: moment().add( 1, 'day' ).locale( 'en' ).format( 'YYYY-MM-DD' ) // Tomorrow
- } );
this.categoriesWidget = new mw.widgets.CategorySelector( {
// Can't be done here because we don't know the target wiki yet... done in #initialize.
// api: new mw.ForeignApi( ... ),
$overlay: this.$overlay
} );
+ this.dateWidget = new mw.widgets.DateInputWidget( {
+ $overlay: this.$overlay,
+ required: true,
+ mustBeBefore: moment().add( 1, 'day' ).locale( 'en' ).format( 'YYYY-MM-DD' ) // Tomorrow
+ } );
fieldset = new OO.ui.FieldsetLayout( {
label: mw.msg( 'upload-form-label-infoform-title' )
fieldset.addItems( [
new OO.ui.FieldLayout( this.filenameWidget, {
label: mw.msg( 'upload-form-label-infoform-name' ),
- align: 'top'
+ align: 'top',
+ help: mw.msg( 'upload-form-label-infoform-name-tooltip' )
} ),
new OO.ui.FieldLayout( this.descriptionWidget, {
label: mw.msg( 'upload-form-label-infoform-description' ),
- align: 'top'
+ align: 'top',
+ help: mw.msg( 'upload-form-label-infoform-description-tooltip' )
} ),
new OO.ui.FieldLayout( this.categoriesWidget, {
label: mw.msg( 'foreign-structured-upload-form-label-infoform-categories' ),
return this.upload.getText();
};
+ /**
+ * Get original date from EXIF data
+ *
+ * @param {Object} file
+ * @return {jQuery.Promise} Promise resolved with the EXIF date
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromExif = function ( file ) {
+ var fileReader,
+ deferred = $.Deferred();
+
+ if ( file && file.type === 'image/jpeg' ) {
+ fileReader = new FileReader();
+ fileReader.onload = function () {
+ var fileStr, arr, i, metadata;
+
+ if ( typeof fileReader.result === 'string' ) {
+ fileStr = fileReader.result;
+ } else {
+ // Array buffer; convert to binary string for the library.
+ arr = new Uint8Array( fileReader.result );
+ fileStr = '';
+ for ( i = 0; i < arr.byteLength; i++ ) {
+ fileStr += String.fromCharCode( arr[ i ] );
+ }
+ }
+
+ try {
+ metadata = mw.libs.jpegmeta( this.result, file.name );
+ } catch ( e ) {
+ metadata = null;
+ }
+
+ if ( metadata !== null && metadata.exif !== undefined && metadata.exif.DateTimeOriginal ) {
+ deferred.resolve( moment( metadata.exif.DateTimeOriginal, 'YYYY:MM:DD' ).format( 'YYYY-MM-DD' ) );
+ } else {
+ deferred.reject();
+ }
+ };
+
+ if ( 'readAsBinaryString' in fileReader ) {
+ fileReader.readAsBinaryString( file );
+ } else if ( 'readAsArrayBuffer' in fileReader ) {
+ fileReader.readAsArrayBuffer( file );
+ } else {
+ // We should never get here
+ deferred.reject();
+ throw new Error( 'Cannot read thumbnail as binary string or array buffer.' );
+ }
+ }
+
+ return deferred.promise();
+ };
+
+ /**
+ * Get last modified date from file
+ *
+ * @param {Object} file
+ * @return {Object} Last modified date from file
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromLastModified = function ( file ) {
+ if ( file && file.lastModified ) {
+ return moment( file.lastModified ).format( 'YYYY-MM-DD' );
+ }
+ };
+
/* Setters */
/**
*/
mw.Upload.BookletLayout.prototype.initialize = function () {
var
- apiPromise,
booklet = this,
deferred = $.Deferred();
this.upload = this.createUpload();
this.setPage( 'upload' );
- apiPromise = this.upload.apiPromise || $.Deferred().resolve( this.upload.api );
- apiPromise.done( function ( api ) {
+ this.upload.getApi().done( function ( api ) {
// If the user can't upload anything, don't give them the option to.
api.getUserInfo().done( function ( userInfo ) {
if ( userInfo.rights.indexOf( 'upload' ) === -1 ) {
layout = this,
file = this.getFile();
- this.filenameWidget.setValue( file.name );
+ this.setFilename( file.name );
+
this.setPage( 'info' );
if ( this.shouldRecordBucket ) {
}
this.upload.setFile( file );
- // Explicitly set the filename so that the old filename isn't used in case of retry
- this.upload.setFilenameFromFile();
+ // The original file name might contain invalid characters, so use our sanitized one
+ this.upload.setFilename( this.getFilename() );
this.uploadPromise = this.upload.uploadToStash();
this.uploadPromise.then( function () {
} else if ( warnings.badfilename !== undefined ) {
// Change the name if the current name isn't acceptable
// TODO This might not really be the best place to do this
- this.filenameWidget.setValue( warnings.badfilename );
+ this.setFilename( warnings.badfilename );
return new OO.ui.Error(
$( '<p>' ).msg( 'badfilename', warnings.badfilename )
);
fieldset.addItems( [
new OO.ui.FieldLayout( this.filenameWidget, {
label: mw.msg( 'upload-form-label-infoform-name' ),
- align: 'top'
+ align: 'top',
+ help: mw.msg( 'upload-form-label-infoform-name-tooltip' )
} ),
new OO.ui.FieldLayout( this.descriptionWidget, {
label: mw.msg( 'upload-form-label-infoform-description' ),
- align: 'top'
+ align: 'top',
+ help: mw.msg( 'upload-form-label-infoform-description-tooltip' )
} )
] );
this.infoForm = new OO.ui.FormLayout( { items: [ fieldset ] } );
* @return {string}
*/
mw.Upload.BookletLayout.prototype.getFilename = function () {
- return this.filenameWidget.getValue();
+ var filename = this.filenameWidget.getValue();
+ if ( this.filenameExtension ) {
+ filename += '.' + this.filenameExtension;
+ }
+ return filename;
+ };
+
+ /**
+ * Prefills the {@link #infoForm information form} with the given filename.
+ *
+ * @protected
+ * @param {string} filename
+ */
+ mw.Upload.BookletLayout.prototype.setFilename = function ( filename ) {
+ var title = mw.Title.newFromFileName( filename );
+
+ if ( title ) {
+ this.filenameWidget.setValue( title.getNameText() );
+ this.filenameExtension = mw.Title.normalizeExtension( title.getExtension() );
+ } else {
+ // Seems to happen for files with no extension, which should fail some checks anyway...
+ this.filenameWidget.setValue( filename );
+ this.filenameExtension = null;
+ }
};
/**