/**
* JavaScript for Special:Upload
- * Note that additional code still lives in skins/common/upload.js
+ *
+ * @private
+ * @class mw.special.upload
+ * @singleton
*/
( function ( mw, $ ) {
- /**
- * Add a preview to the upload form
- */
+ var ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
+ $license = $( '#wpLicense' ), uploadWarning, uploadLicense;
+
+ window.wgUploadWarningObj = uploadWarning = {
+ responseCache: { '': ' ' },
+ nameToCheck: '',
+ typing: false,
+ delay: 500, // ms
+ timeoutID: false,
+
+ keypress: function () {
+ if ( !ajaxUploadDestCheck ) {
+ return;
+ }
+
+ // Find file to upload
+ if ( !$( '#wpDestFile' ).length || !$( '#wpDestFile-warning' ).length ) {
+ return;
+ }
+
+ this.nameToCheck = $( '#wpDestFile' ).val();
+
+ // Clear timer
+ if ( this.timeoutID ) {
+ clearTimeout( this.timeoutID );
+ }
+ // Check response cache
+ if ( this.responseCache.hasOwnProperty( this.nameToCheck ) ) {
+ this.setWarning( this.responseCache[this.nameToCheck] );
+ return;
+ }
+
+ this.timeoutID = setTimeout( function () {
+ uploadWarning.timeout();
+ }, this.delay );
+ },
+
+ checkNow: function ( fname ) {
+ if ( !ajaxUploadDestCheck ) {
+ return;
+ }
+ if ( this.timeoutID ) {
+ clearTimeout( this.timeoutID );
+ }
+ this.nameToCheck = fname;
+ this.timeout();
+ },
+
+ timeout: function () {
+ var $spinnerDestCheck;
+ if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
+ return;
+ }
+ $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
+
+ ( new mw.Api() ).get( {
+ action: 'query',
+ titles: ( new mw.Title( this.nameToCheck, mw.config.get( 'wgNamespaceIds' ).file ) ).getPrefixedText(),
+ prop: 'imageinfo',
+ iiprop: 'uploadwarning',
+ indexpageids: ''
+ } ).done( function ( result ) {
+ var resultOut = '';
+ if ( result.query ) {
+ resultOut = result.query.pages[result.query.pageids[0]].imageinfo[0];
+ }
+ $spinnerDestCheck.remove();
+ uploadWarning.processResult( resultOut, uploadWarning.nameToCheck );
+ } );
+ },
+
+ processResult: function ( result, fileName ) {
+ this.setWarning( result.html );
+ this.responseCache[fileName] = result.html;
+ },
+
+ setWarning: function ( warning ) {
+ $( '#wpDestFile-warning' ).html( warning );
+
+ // Set a value in the form indicating that the warning is acknowledged and
+ // doesn't need to be redisplayed post-upload
+ if ( !warning ) {
+ $( '#wpDestFileWarningAck' ).val( '' );
+ } else {
+ $( '#wpDestFileWarningAck' ).val( '1' );
+ }
+
+ }
+ };
+
+ uploadLicense = {
+
+ responseCache: { '': '' },
+
+ fetchPreview: function ( license ) {
+ var $spinnerLicense;
+ if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
+ return;
+ }
+ if ( this.responseCache.hasOwnProperty( license ) ) {
+ this.showPreview( this.responseCache[license] );
+ return;
+ }
+
+ $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
+
+ ( new mw.Api() ).get( {
+ action: 'parse',
+ text: '{{' + license + '}}',
+ title: $( '#wpDestFile' ).val() || 'File:Sample.jpg',
+ prop: 'text',
+ pst: ''
+ } ).done( function ( result ) {
+ $spinnerLicense.remove();
+ uploadLicense.processResult( result, license );
+ } );
+ },
+
+ processResult: function ( result, license ) {
+ this.responseCache[license] = result.parse.text['*'];
+ this.showPreview( this.responseCache[license] );
+ },
+
+ showPreview: function ( preview ) {
+ $( '#mw-license-preview' ).html( preview );
+ }
+
+ };
+
+ $( function () {
+ // Disable URL box if the URL copy upload source type is not selected
+ if ( !$( '#wpSourceTypeurl' ).prop( 'checked' ) ) {
+ $( '#wpUploadFileURL' ).prop( 'disabled', true );
+ }
+
+ // AJAX wpDestFile warnings
+ if ( ajaxUploadDestCheck ) {
+ // Insert an event handler that fetches upload warnings when wpDestFile
+ // has been changed
+ $( '#wpDestFile' ).change( function () {
+ uploadWarning.checkNow( $( this ).val() );
+ } );
+ // Insert a row where the warnings will be displayed just below the
+ // wpDestFile row
+ $( '#mw-htmlform-description tbody' ).append(
+ $( '<tr>' ).append(
+ $( '<td>' )
+ .attr( 'id', 'wpDestFile-warning' )
+ .attr( 'colspan', 2 )
+ )
+ );
+ }
+
+ if ( mw.config.get( 'wgAjaxLicensePreview' ) && $license.length ) {
+ // License selector check
+ $license.change( function () {
+ // We might show a preview
+ uploadLicense.fetchPreview( $license.val() );
+ } );
+
+ // License selector table row
+ $license.closest( 'tr' ).after(
+ $( '<tr>' ).append(
+ $( '<td>' ),
+ $( '<td>' ).attr( 'id', 'mw-license-preview' )
+ )
+ );
+ }
+
+ // fillDestFile setup
+ $.each( mw.config.get( 'wgUploadSourceIds' ), function ( index, sourceId ) {
+ $( '#' + sourceId ).change( function () {
+ var path, slash, backslash, fname;
+ if ( !mw.config.get( 'wgUploadAutoFill' ) ) {
+ return;
+ }
+ // Remove any previously flagged errors
+ $( '#mw-upload-permitted' ).attr( 'class', '' );
+ $( '#mw-upload-prohibited' ).attr( 'class', '' );
+
+ path = $( this ).val();
+ // Find trailing part
+ slash = path.lastIndexOf( '/' );
+ backslash = path.lastIndexOf( '\\' );
+ if ( slash === -1 && backslash === -1 ) {
+ fname = path;
+ } else if ( slash > backslash ) {
+ fname = path.slice( slash + 1 );
+ } else {
+ fname = path.slice( backslash + 1 );
+ }
+
+ // Clear the filename if it does not have a valid extension.
+ // URLs are less likely to have a useful extension, so don't include them in the
+ // extension check.
+ if (
+ mw.config.get( 'wgStrictFileExtensions' ) &&
+ mw.config.get( 'wgFileExtensions' ) &&
+ $( this ).attr( 'id' ) !== 'wpUploadFileURL'
+ ) {
+ if (
+ fname.lastIndexOf( '.' ) === -1 ||
+ $.inArray(
+ fname.slice( fname.lastIndexOf( '.' ) + 1 ).toLowerCase(),
+ $.map( mw.config.get( 'wgFileExtensions' ), function ( element ) {
+ return element.toLowerCase();
+ } )
+ ) === -1
+ ) {
+ // Not a valid extension
+ // Clear the upload and set mw-upload-permitted to error
+ $( this ).val( '' );
+ $( '#mw-upload-permitted' ).attr( 'class', 'error' );
+ $( '#mw-upload-prohibited' ).attr( 'class', 'error' );
+ // Clear wpDestFile as well
+ $( '#wpDestFile' ).val( '' );
+
+ return false;
+ }
+ }
+
+ // Replace spaces by underscores
+ fname = fname.replace( / /g, '_' );
+ // Capitalise first letter if needed
+ if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
+ fname = fname.charAt( 0 ).toUpperCase().concat( fname.slice( 1 ) );
+ }
+
+ // Output result
+ if ( $( '#wpDestFile' ).length ) {
+ // Call decodeURIComponent function to remove possible URL-encoded characters
+ // from the file name (bug 30390). Especially likely with upload-form-url.
+ // decodeURIComponent can throw an exception if input is invalid utf-8
+ try {
+ $( '#wpDestFile' ).val( decodeURIComponent( fname ) );
+ } catch ( err ) {
+ $( '#wpDestFile' ).val( fname );
+ }
+ uploadWarning.checkNow( fname );
+ }
+ } );
+ } );
+ } );
+
+ // Add a preview to the upload form
$( function () {
/**
* Is the FileAPI available with sufficient functionality?
* Check if this is a recognizable image type...
* Also excludes files over 10M to avoid going insane on memory usage.
*
- * @todo is there a way we can ask the browser what's supported in <img>s?
- * @todo put SVG back after working around Firefox 7 bug <https://bugzilla.wikimedia.org/show_bug.cgi?id=31643>
+ * TODO: Is there a way we can ask the browser what's supported in `<img>`s?
+ *
+ * TODO: Put SVG back after working around Firefox 7 bug <https://bugzilla.wikimedia.org/show_bug.cgi?id=31643>
*
* @param {File} file
* @return boolean
* in browsers supporting HTML5 FileAPI.
*
* As of this writing, known good:
+ *
* - Firefox 3.6+
* - Chrome 7.something
*
- * @todo check file size limits and warn of likely failures
+ * TODO: Check file size limits and warn of likely failures
*
* @param {File} file
*/
* to do preprocessing on the binary data first.
*
* @param {File} file
- * @param {function} callback
- * @param {function} callbackBinary
+ * @param {Function} callback
+ * @param {Function} callbackBinary
*/
function fetchPreview( file, callback, callbackBinary ) {
var reader = new FileReader();
/**
* Format a file size attractively.
- * @todo match numeric formatting
+ *
+ * TODO: Match numeric formatting
*
* @param {number} s
- * @return string
+ * @return {string}
*/
function prettySize( s ) {
var sizeMsgs = ['size-bytes', 'size-kilobytes', 'size-megabytes', 'size-gigabytes'];
return true;
}
- /**
- * Initialization
- */
+ /* Initialization */
if ( hasFileAPI() ) {
// Update thumbnail when the file selection control is updated.
$( '#wpUploadFile' ).change( function () {
}
} );
- /**
- * Disable all upload source fields except the selected one
- */
+ // Disable all upload source fields except the selected one
$( function () {
var i, $row,
$rows = $( '.mw-htmlform-field-UploadSourceField' );
+ /**
+ * @param {jQuery} $currentRow
+ * @return {Function} Handler
+ * @return {jQuery.Event} return.e
+ */
function createHandler( $currentRow ) {
- /**
- * @param {jQuery.Event}
- */
return function () {
$( '.mw-upload-source-error' ).remove();
if ( this.checked ) {