summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/MsUpload/MsUpload.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/MsUpload/MsUpload.js')
-rw-r--r--www/wiki/extensions/MsUpload/MsUpload.js510
1 files changed, 510 insertions, 0 deletions
diff --git a/www/wiki/extensions/MsUpload/MsUpload.js b/www/wiki/extensions/MsUpload/MsUpload.js
new file mode 100644
index 00000000..7836e22d
--- /dev/null
+++ b/www/wiki/extensions/MsUpload/MsUpload.js
@@ -0,0 +1,510 @@
+( function ( $, mw ) {
+ var msuVars = mw.config.get( 'msuVars' );
+ var MsUpload = {
+
+ fileError: function ( uploader, file, errorText ) {
+ file.li.warning.text( errorText );
+ file.li.addClass( 'yellow' );
+ file.li.type.addClass( 'error' );
+ file.li.click( function () { // Remove li at click
+ file.li.fadeOut( 'fast', function () {
+ $( this ).remove();
+ uploader.trigger( 'CheckFiles' );
+ } );
+ } );
+ },
+
+ galleryArray: [],
+ insertGallery: function () {
+ var galleryText = 'File:' + MsUpload.galleryArray.join( '\nFile:' );
+ MsUpload.insertText( '<gallery>\n' + galleryText + '\n</gallery>\n' );
+ },
+
+ filesArray: [],
+ insertFiles: function () {
+ MsUpload.insertText( '[[File:' + MsUpload.filesArray.join( ']]\n[[File:' ) + ']]\n' );
+ },
+
+ insertLinks: function () {
+ if ( msuVars.useMsLinks === true ) {
+ MsUpload.insertText( '*{{#l:' + MsUpload.filesArray.join( '}}\n*{{#l:' ) + '}}\n' );
+ } else {
+ MsUpload.insertText( '*[[:File:' + MsUpload.filesArray.join( ']]\n*[[:File:' ) + ']]\n' );
+ }
+ },
+
+ /**
+ * Add text to selection in the main textarea.
+ *
+ * @param {string} text
+ */
+ insertText: function ( text ) {
+ $( '#wpTextbox1' ).textSelection( 'encapsulateSelection', { pre: text } );
+ },
+
+ unconfirmedReplacements: 0,
+ warningText: function ( fileItem, warning, uploader ) {
+ switch ( warning ) {
+ case '':
+ case '&nbsp;':
+ case '&#160;':
+ $( fileItem.warning ).empty()
+ .siblings( '.file-name' ).show()
+ .siblings( '.file-name-input' ).hide()
+ .siblings( '.file-extension' ).hide();
+ break;
+
+ case 'Error: Unknown result from API':
+ case 'Error: Request failed':
+ $( fileItem.warning ).text( warning );
+ break;
+
+ default:
+ // IMPORTANT! The code below assumes that every warning not captured by the code above is about a file being replaced
+ $( fileItem.warning ).html( warning );
+
+ // We break when the particula warning when a file name starts with IMG
+ if ( warning.indexOf( 'The name of the file you are uploading begins with' ) === 0 ) {
+ break; // When the file name starts with "IMG", MediaWiki issues this warning. Display it and continue.
+ }
+ if ( warning.indexOf( 'Der Dateiname beginnt mit' ) === 0 ) {
+ break; // Make it work for German too. Must be done this way because the error response doesn't include an error code.
+ }
+
+ // When hovering over the link to the file about to be replaced, show the thumbnail
+ $( fileItem.warning ).find( 'a' ).mouseover( function () {
+ $( fileItem.warning ).find( 'div.thumb' ).show();
+ } ).mouseout( function () {
+ $( fileItem.warning ).find( 'div.thumb' ).hide();
+ } );
+
+ /**
+ * If a file with the same name already exists, add a checkbox to confirm the replacement
+ * This checkbox will also appear when the file name differs only in the file extension
+ * so the confirmation message must be kept generic enough
+ */
+ if ( msuVars.confirmReplace ) {
+
+ MsUpload.unconfirmedReplacements++;
+
+ var title = $( fileItem.warning ).siblings( '.file-name' );
+
+ var checkbox = $( '<input>' ).attr( 'type', 'checkbox' ).click( function () {
+ if ( $( this ).is( ':checked' ) ) {
+ title.show().next().hide();
+ MsUpload.unconfirmedReplacements--;
+ } else {
+ title.hide().next().show().select();
+ MsUpload.unconfirmedReplacements++;
+ }
+ uploader.trigger( 'CheckFiles' );
+ } );
+ $( '<label>' ).append( checkbox ).append( mw.msg( 'msu-continue' ) ).appendTo( fileItem.warning );
+ }
+ break;
+ }
+ uploader.trigger( 'CheckFiles' );
+ fileItem.loading.hide();
+ },
+
+ checkUploadWarning: function ( filename, fileItem, uploader ) {
+ $.ajax( { url: mw.util.wikiScript( 'api' ), dataType: 'json', type: 'POST',
+ data: {
+ format: 'json',
+ action: 'query',
+ titles: 'File:' + filename,
+ prop: 'imageinfo',
+ iiprop: 'uploadwarning'
+ }, success: function ( data ) {
+ if ( data && data.query && data.query.pages ) {
+ var pages = data.query.pages;
+ $.each( pages, function ( index, value ) {
+ MsUpload.warningText( fileItem, value.imageinfo[ 0 ].html, uploader ); // Pass on the warning message
+ return false; // Break out
+ } );
+ } else {
+ MsUpload.warningText( fileItem, 'Error: Unknown result from API', uploader );
+ }
+ }, error: function () {
+ MsUpload.warningText( fileItem, 'Error: Request failed', uploader );
+ } } );
+ },
+
+ build: function ( file, uploader ) {
+
+ // Auto category
+ if ( msuVars.showAutoCat && mw.config.get( 'wgNamespaceNumber' ) === 14 ) {
+ file.cat = msuVars.checkAutoCat; // Predefine
+ $( '<input>' ).attr( {
+ 'class': 'msupload-check-index',
+ type: 'checkbox',
+ checked: file.cat
+ } ).change( function () {
+ file.cat = this.checked; // Save
+ } ).appendTo( file.li );
+
+ $( '<span>' ).attr( 'class', 'msupload-check-span' ).text( mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ) ).appendTo( file.li );
+ }
+
+ // Insert an input field for changing the file title
+ var fileNameInput = $( '<input>' ).attr( {
+ 'class': 'file-name-input',
+ size: file.name.length,
+ name: 'filename',
+ value: file.name.substr( 0, file.name.length - file.extension.length - 1 )
+ } ).change( function () {
+ file.name = this.value + '.' + file.extension;
+ $( this ).prev().text( file.name );
+ MsUpload.unconfirmedReplacements = 0; // Hack! If the user renames a file to avoid replacing it, this forces the Upload button to appear, but it also does when a user just renames a file that wasn't about to replace another
+ MsUpload.checkUploadWarning( this.value, file.li, uploader );
+ } ).keydown( function ( event ) {
+ // For convenience, when pressing enter, save the new title
+ if ( event.keyCode === 13 ) {
+ $( this ).change();
+ event.preventDefault();
+ }
+ } ).hide().insertAfter( file.li.title );
+
+ var fileExtension = $( '<span>' ).addClass( 'file-extension' ).text( '.' + file.extension ).hide().insertAfter( fileNameInput );
+
+ file.li.title.click( function () {
+ file.li.title.hide();
+ fileNameInput.show().select();
+ fileExtension.show();
+ } );
+
+ // Insert the progress bar
+ var progressState = $( '<span>' ).addClass( 'file-progress-state' );
+ file.li.children().first().after( progressState );
+ },
+
+ checkExtension: function ( file, uploader ) {
+ mw.log( file );
+
+ file.li.loading.show();
+ file.extension = file.name.split( '.' ).pop().toLowerCase();
+
+ if ( $.inArray( file.extension, mw.config.get( 'wgFileExtensions' ) ) !== -1 ) {
+ switch ( file.extension ) {
+ case 'jpg': case 'jpeg': case 'png': case 'gif': case 'bmp': case 'tif': case 'tiff':
+ file.group = 'image';
+ try {
+ var image = new o.Image();
+ image.onload = function () {
+ this.embed( file.li.type.get( 0 ), {
+ width: 30,
+ height: 30,
+ crop: true
+ } );
+ };
+ image.load( file.getSource() );
+ file.li.type.addClass( 'file-load' );
+ } catch ( event ) {
+ file.li.type.addClass( 'image' );
+ }
+ break;
+
+ case 'mov': case 'avi':
+ file.group = 'video';
+ file.li.type.addClass( 'video' );
+ break;
+
+ case 'pdf':
+ file.li.type.addClass( 'pdf' );
+ break;
+ }
+ MsUpload.checkUploadWarning( file.name, file.li, uploader );
+
+ file.li.cancel = $( '<span>' ).attr( { 'class': 'file-cancel', title: mw.msg( 'msu-cancel-upload' ) } );
+ file.li.cancel.click( function () {
+ uploader.removeFile( file );
+ if ( file.group === 'image' ) {
+ var index = $.inArray( file.name, MsUpload.galleryArray );
+ if ( index !== -1 ) {
+ MsUpload.galleryArray.splice( index, 1 );
+ }
+ uploader.trigger( 'CheckFiles' );
+ }
+ file.li.fadeOut( 'fast', function () {
+ $( this ).remove();
+ uploader.trigger( 'CheckFiles' );
+ } );
+ } );
+ file.li.prepend( file.li.cancel );
+
+ MsUpload.build( file, uploader );
+ } else { // Wrong datatype
+ file.li.loading.hide( 'fast', function () {
+ uploader.removeFile( file );
+ uploader.refresh();
+ } );
+ MsUpload.fileError( uploader, file, mw.msg( 'msu-ext-not-allowed', mw.config.get( 'wgFileExtensions' ).length ) + ' ' + mw.config.get( 'wgFileExtensions' ).join( ',' ) );
+ }
+ },
+
+ cleanAll: function () {
+ MsUpload.galleryArray.length = 0; // Reset
+ MsUpload.uploader.splice( 0, MsUpload.uploader.files.length );
+ $( '#msupload-list .file' ).hide( 'fast', function () {
+ $( this ).remove();
+ $( '#msupload-insert-gallery' ).unbind( 'click' );
+ $( '#msupload-bottom' ).hide();
+ } );
+ },
+
+ uploader: null,
+ createUploader: function () {
+ // Define the GUI elements
+ var uploadDiv = $( '<div>' ).attr( 'id', 'msupload-div' ),
+ uploadContainer = $( '<div>' ).attr( { id: 'msupload-container', 'class': 'start-loading', title: mw.msg( 'msu-button-title' ) } ),
+ uploadButton = $( '<div>' ).attr( 'id', 'msupload-select' ),
+ statusDiv = $( '<div>' ).attr( 'id', 'msupload-status' ).hide(),
+ uploadList = $( '<ul>' ).attr( 'id', 'msupload-list' ),
+ bottomDiv = $( '<div>' ).attr( 'id', 'msupload-bottom' ).hide(),
+ startButton = $( '<a>' ).attr( 'id', 'msupload-files' ).hide(),
+ cleanAll = $( '<a>' ).attr( 'id', 'msupload-clean-all' ).text( mw.msg( 'msu-clean-all' ) ).hide(),
+ galleryInsert = $( '<a>' ).attr( 'id', 'msupload-insert-gallery' ).hide(),
+ filesInsert = $( '<a>' ).attr( 'id', 'msupload-insert-files' ).hide(),
+ linksInsert = $( '<a>' ).attr( 'id', 'msupload-insert-links' ).hide(),
+ uploadDrop = $( '<div>' ).attr( 'id', 'msupload-dropzone' ).hide();
+
+ // Add them to the DOM
+ bottomDiv.append( startButton, cleanAll, galleryInsert, filesInsert, linksInsert );
+ uploadDiv.append( statusDiv, uploadDrop, uploadList, bottomDiv );
+ $( '#wikiEditor-ui-toolbar' ).after( uploadDiv );
+ uploadContainer.append( uploadButton );
+ $( '#wikiEditor-ui-toolbar .group-insert' ).append( uploadContainer );
+
+ // Create the Uploader object
+ MsUpload.uploader = new plupload.Uploader( {
+ runtimes: 'html5,flash,silverlight,html4',
+ browse_button: 'msupload-select',
+ container: 'msupload-container',
+ max_file_size: msuVars.uploadsize,
+ drop_element: 'msupload-dropzone',
+ url: msuVars.scriptPath + '/api.php',
+ flash_swf_url: msuVars.flash_swf_url,
+ silverlight_xap_url: msuVars.silverlight_xap_url
+ } );
+
+ // Bind events
+ MsUpload.uploader.bind( 'PostInit', MsUpload.onPostInit );
+ MsUpload.uploader.bind( 'FilesAdded', MsUpload.onFilesAdded );
+ MsUpload.uploader.bind( 'QueueChanged', MsUpload.onQueueChanged );
+ MsUpload.uploader.bind( 'StateChanged', MsUpload.onStateChanged );
+ MsUpload.uploader.bind( 'FilesRemoved', MsUpload.onFilesRemoved );
+ MsUpload.uploader.bind( 'BeforeUpload', MsUpload.onBeforeUpload );
+ MsUpload.uploader.bind( 'UploadProgress', MsUpload.onUploadProgress );
+ MsUpload.uploader.bind( 'Error', MsUpload.onError );
+ MsUpload.uploader.bind( 'FileUploaded', MsUpload.onFileUploaded );
+ MsUpload.uploader.bind( 'CheckFiles', MsUpload.onCheckFiles );
+ MsUpload.uploader.bind( 'UploadComplete', MsUpload.onCheckFiles );
+
+ startButton.click( function ( event ) {
+ MsUpload.uploader.start();
+ event.preventDefault();
+ } );
+
+ // Initialise
+ MsUpload.uploader.init();
+ },
+
+ onPostInit: function ( uploader ) {
+ mw.log( 'MsUpload DEBUG: runtime: ' + uploader.runtime + ' features: ' + JSON.stringify( uploader.features ) );
+ $( '#msupload-container' ).removeClass( 'start-loading' );
+ if ( uploader.features.dragdrop && msuVars.useDragDrop ) {
+ $( '#msupload-dropzone' ).text( mw.msg( 'msu-dropzone' ) ).show();
+ $( '#msupload-dropzone' ).bind( 'dragover', function () {
+ $( this ).addClass( 'drop-over' ).css( 'padding', 20 );
+ } ).bind( 'dragleave', function () {
+ $( this ).removeClass( 'drop-over' ).css( 'padding', 0 );
+ } ).bind( 'drop', function () {
+ $( this ).removeClass( 'drop-over' ).css( 'padding', 0 );
+ } );
+ } else {
+ $( '#msupload-div' ).addClass( 'nodragdrop' );
+ }
+ },
+
+ onFilesAdded: function ( uploader, files ) {
+ $.each( files, function ( i, file ) {
+ // iOS6 by SLBoat
+ if ( ( navigator.platform === 'iPad' || navigator.platform === 'iPhone' ) ) {
+ if ( file.name.indexOf( 'image' ) !== -1 && file.name.length < 11 ) {
+ var heute = new Date(),
+ fileNameApple = navigator.platform + '_image_' + heute.getFullYear() + '-' + heute.getMonth() + '-' + heute.getDate() + '-' + heute.getTime(); // Because each image is named 'image.jpg' in iOS6
+ file.name = fileNameApple + '_' + i + '.' + file.name.split( '.' ).pop(); // image_Y-M-D_0.jpg
+ }
+ }
+ file.li = $( '<li>' ).attr( 'id', file.id ).addClass( 'file' ).appendTo( $( '#msupload-list' ) );
+ file.li.type = $( '<span>' ).addClass( 'file-type' ).appendTo( file.li );
+ file.li.title = $( '<span>' ).addClass( 'file-name' ).text( file.name ).appendTo( file.li );
+ file.li.size = $( '<span>' ).addClass( 'file-size' ).text( plupload.formatSize( file.size ) ).appendTo( file.li );
+ file.li.loading = $( '<span>' ).addClass( 'file-loading' ).appendTo( file.li );
+ file.li.warning = $( '<span>' ).addClass( 'file-warning' ).appendTo( file.li );
+ MsUpload.checkExtension( file, uploader );
+ } );
+ uploader.refresh(); // Reposition Flash/Silverlight
+ uploader.trigger( 'CheckFiles' );
+ },
+
+ onQueueChanged: function ( uploader ) {
+ uploader.trigger( 'CheckFiles' );
+ },
+
+ onStateChanged: function ( uploader ) {
+ mw.log( uploader.state );
+ if ( uploader.files.length === ( uploader.total.uploaded + uploader.total.failed ) ) {
+ // mw.log( 'State: ' + uploader.files.length ) // All files uploaded
+ }
+ },
+
+ onFilesRemoved: function ( /* uploader, files */ ) {
+ mw.log( 'Files removed' );
+ // uploader.trigger( 'CheckFiles' );
+ },
+
+ onBeforeUpload: function ( uploader, file ) {
+ file.li.title.text( file.name ).show(); // Show title
+ $( '#' + file.id + ' .file-name-input' ).hide(); // Hide the file name input
+ $( '#' + file.id + ' .file-extension' ).hide(); // Hide the file extension
+ uploader.settings.multipart_params = {
+ filename: file.name,
+ token: mw.user.tokens.get( 'editToken' ),
+ action: 'upload',
+ ignorewarnings: true,
+ comment: mw.message( 'msu-comment' ).plain(),
+ format: 'json'
+ }; // Set multipart_params
+ $( '#' + file.id + ' .file-progress-state' ).text( '0%' );
+ },
+
+ onUploadProgress: function ( uploader, file ) {
+ $( '#' + file.id + ' .file-progress-state' ).text( file.percent + '%' );
+ },
+
+ onError: function ( uploader, error ) {
+ mw.log( error );
+ $( '#' + error.file.id + ' .file-warning' ).html(
+ 'Error ' + error.code + ', ' + error.message + ( error.file ? ', File: ' + error.file.name : '' )
+ );
+ $( '#msupload-status' ).append( error.message );
+ uploader.refresh(); // Reposition Flash/Silverlight
+ },
+
+ onFileUploaded: function ( uploader, file, success ) {
+ mw.log( success );
+ file.li.title.unbind( 'click' );
+ file.li.title.unbind( 'mouseover' );
+ $( '#' + file.id + ' .file-cancel' ).fadeOut( 'fast' );
+ $( '#' + file.id + ' .file-progress-state' ).fadeOut( 'fast' );
+
+ try {
+ var result = $.parseJSON( success.response );
+ if ( result.error ) {
+ MsUpload.fileError( uploader, file, result.error.info );
+ } else {
+ file.li.type.addClass( 'ok' );
+ file.li.addClass( 'green' );
+ file.li.warning.fadeOut( 'fast' );
+
+ if ( file.cat && mw.config.get( 'wgNamespaceNumber' ) === 14 ) { // Should the categroy be set?
+ $.get( mw.util.wikiScript(), {
+ action: 'ajax',
+ rs: 'MsUpload::saveCat',
+ rsargs: [ file.name, mw.config.get( 'wgPageName' ) ]
+ }, 'json' );
+ }
+ $( '<a>' ).text( mw.msg( 'msu-insert-link' ) ).click( function () {
+ if ( msuVars.useMsLinks === true ) {
+ MsUpload.insertText( '{{#l:' + file.name + '}}' ); // Insert link
+ } else {
+ MsUpload.insertText( '[[:File:' + file.name + ']]' ); // Insert link
+ }
+ } ).appendTo( file.li );
+ if ( file.group === 'image' ) {
+ MsUpload.galleryArray.push( file.name );
+ if ( MsUpload.galleryArray.length === 2 ) { // Bind click function only the first time
+ $( '#msupload-insert-gallery' ).click( MsUpload.insertGallery ).text( mw.msg( 'msu-insert-gallery' ) ).show();
+ }
+ $( '<span>' ).text( ' | ' ).appendTo( file.li );
+ $( '<a>' ).text( mw.msg( 'msu-insert-image' ) ).click( function () {
+ MsUpload.insertText( '[[File:' + file.name + msuVars.imgParams + ']]' );
+ } ).appendTo( file.li );
+ } else if ( file.group === 'video' ) {
+ $( '<span>' ).text( ' | ' ).appendTo( file.li );
+ $( '<a>' ).text( mw.msg( 'msu-insert-video' ) ).click( function () {
+ MsUpload.insertText( '[[File:' + file.name + ']]' );
+ } ).appendTo( file.li );
+ }
+ MsUpload.filesArray.push( file.name );
+ if ( MsUpload.filesArray.length === 2 ) { // Bind click function only the first time
+ $( '#msupload-insert-files' ).click( MsUpload.insertFiles ).text( mw.msg( 'msu-insert-files' ) ).show();
+ $( '#msupload-insert-links' ).click( MsUpload.insertLinks ).text( mw.msg( 'msu-insert-links' ) ).show();
+ }
+ }
+ } catch ( error ) {
+ MsUpload.fileError( uploader, file, 'Error: ' + success.response.replace( /(<([^>]+)>)/ig, '' ) ); // Remove html tags
+ }
+ uploader.removeFile( file ); // For preventing a second upload afterwards
+ },
+
+ onCheckFiles: function ( uploader ) {
+ var filesLength = uploader.files.length,
+ listLength = $( '#msupload-list li' ).length;
+
+ mw.log( 'files: ' + filesLength + ', gallery: ' + MsUpload.galleryArray.length + ', list: ' + listLength );
+
+ if ( filesLength ) {
+ $( '#msupload-bottom' ).show();
+ if ( filesLength === 1 ) {
+ $( '#msupload-files' ).text( mw.msg( 'msu-upload-this' ) ).show();
+ } else {
+ $( '#msupload-files' ).text( mw.msg( 'msu-upload-all' ) ).show();
+ }
+ } else {
+ $( '#msupload-files' ).hide();
+ }
+
+ if ( MsUpload.unconfirmedReplacements ) {
+ $( '#msupload-files' ).hide();
+ }
+
+ if ( MsUpload.filesArray.length > 1 ) {
+ $( '#msupload-insert-files' ).show();
+ $( '#msupload-insert-links' ).show();
+ } else {
+ $( '#msupload-insert-files' ).hide();
+ $( '#msupload-insert-links' ).hide();
+ }
+
+ if ( MsUpload.galleryArray.length > 1 ) {
+ $( '#msupload-insert-gallery' ).show();
+ $( '#msupload-bottom' ).show();
+ } else {
+ $( '#msupload-insert-gallery' ).hide();
+ }
+
+ if ( listLength ) {
+ $( '#msupload-bottom' ).show();
+ $( '#msupload-clean-all' ).text( mw.msg( 'msu-clean-all' ) ).click( MsUpload.cleanAll ).show();
+ } else {
+ $( '#msupload-bottom' ).hide();
+ }
+ uploader.refresh(); // Reposition Flash/Silverlight
+ },
+
+ init: function () {
+ if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) {
+ mw.loader.using( 'user.options', function () {
+ if ( mw.user.options.get( 'usebetatoolbar' ) ) {
+ $.when( mw.loader.using( 'ext.wikiEditor' ), $.ready )
+ .then( MsUpload.createUploader );
+ }
+ } );
+ }
+ }
+ };
+
+ $( MsUpload.init );
+}( jQuery, mediaWiki ) );