File: /storage/v6964/gopalak/public_html/wp-content/plugins/buddypress/bp-core/js/bp-plupload.js
/* global plupload, BP_Uploader, _, JSON, Backbone */
window.wp = window.wp || {};
window.bp = window.bp || {};
( function( bp, $ ) {
// Bail if not set.
if ( typeof BP_Uploader === 'undefined' ) {
return;
}
/**
* Extend the bp global with what we need from the wp one.
* and make sure previously defined BuddyPress attributes
* are not removed (eg: bp.mentions)
*/
_.extend( bp, _.pick( wp, 'Backbone', 'ajax', 'template' ) );
// Init Models, Collections, Views and the BuddyPress Uploader.
bp.Models = bp.Models || {};
bp.Collections = bp.Collections || {};
bp.Views = bp.Views || {};
bp.Uploader = {};
/**
* BuddyPress Uploader.
*
* This is an adapted version of wp.Uploader.
*/
bp.Uploader.uploader = function() {
var self = this,
isIE = navigator.userAgent.indexOf('Trident/') !== -1 || navigator.userAgent.indexOf('MSIE ') !== -1;
this.params = BP_Uploader.settings;
this.strings = BP_Uploader.strings;
this.supports = {
upload: this.params.browser.supported
};
this.supported = this.supports.upload;
if ( ! this.supported ) {
/*jshint -W020 */
BP_Uploader = undefined;
return;
}
// Make sure flash sends cookies (seems in IE it does without switching to urlstream mode).
if ( ! isIE && 'flash' === plupload.predictRuntime( this.params.defaults ) &&
( ! this.params.defaults.required_features || ! this.params.defaults.required_features.hasOwnProperty( 'send_binary_string' ) ) ) {
this.params.defaults.required_features = this.params.defaults.required_features || {};
this.params.defaults.required_features.send_binary_string = true;
}
this.uploader = new plupload.Uploader( this.params.defaults );
/**
* After the Uploader has been initialized, initialize some behaviors for the dropzone.
*
* @event Init
* @param {plupload.Uploader} uploader Uploader instance.
*/
this.uploader.bind( 'Init', function( uploader ) {
var container = $( '#' + self.params.defaults.container ),
drop_element = $( '#' + self.params.defaults.drop_element );
if ( 'html4' === uploader.runtime ) {
uploader.settings.multipart_params.html4 = true;
}
/**
* Avatars need to be cropped, by default we are using an original
* max width of 450px, but there can be cases when this max width
* is larger than the one of the Avatar UI (eg: on mobile). To avoid any
* difficulties, we're adding a ui_available_width argument to the bp_params
* object and set it according to the container width. This value will be
* checked during the upload process to eventually adapt the resized avatar.
*/
if ( 'bp_avatar_upload' === uploader.settings.multipart_params.action ) {
uploader.settings.multipart_params.bp_params.ui_available_width = container.width();
}
if ( uploader.features.dragdrop && ! self.params.browser.mobile ) {
container.addClass( 'drag-drop' );
drop_element.on( 'dragover.wp-uploader', function() {
container.addClass( 'drag-over' );
} );
drop_element.on( 'dragleave.wp-uploader, drop.wp-uploader', function() {
container.removeClass( 'drag-over' );
} );
} else {
container.removeClass( 'drag-drop' );
drop_element.off( '.wp-uploader' );
}
} );
// See https://core.trac.wordpress.org/ticket/37039.
this.uploader.bind( 'postinit', function( up ) {
up.refresh();
});
// Init BuddyPress Uploader.
this.uploader.init();
/**
* Feedback callback.
*
* Add a new message to the errors collection, so it's possible
* to give some feedback to the user.
*
* @param {string} message
* @param {object} data
* @param {plupload.File} file File that was uploaded.
*/
this.feedback = function( message, data, file ) {
if ( ! _.isNull( file ) && file.item ) {
file.item.clear();
}
bp.Uploader.filesError.unshift( {
message: message,
data: data,
file: file
} );
};
/**
* After files were filtered and added to the queue, create a model for each.
*
* @event FilesAdded
* @param {plupload.Uploader} uploader Uploader instance.
* @param {Array} files Array of file objects that were added to queue by the user.
*/
this.uploader.bind( 'FilesAdded', function( uploader, files ) {
var hundredmb = 100 * 1024 * 1024, max = parseInt( uploader.settings.max_file_size, 10 ),
_this = this;
/**
* In case the multiple selection is false (eg: avatar) stop the process and send
* and event containing a warning.
*/
if ( ! uploader.settings.multi_selection && files.length > 1 ) {
for ( var i in files ) {
uploader.removeFile( files[i] );
}
$( self ).trigger( 'bp-uploader-warning', self.strings.unique_file_warning );
return;
}
_.each( files, function( file ) {
var attributes;
// Ignore failed uploads.
if ( plupload.FAILED === file.status ) {
return;
}
if ( file.type === 'image/webp' && uploader.settings.webp_upload_error ) {
// Disallow uploading of WebP images if the server cannot edit them.
$( self ).trigger( 'bp-uploader-warning', self.strings.noneditable_image );
uploader.removeFile( file );
return;
}
if ( max > hundredmb && file.size > hundredmb && uploader.runtime !== 'html5' ) {
_this.uploadSizeError( uploader, file, true );
} else {
attributes = _.extend( {
id: file.id,
file: file,
uploading: true,
date: new Date(),
filename: file.name
}, _.pick( file, 'loaded', 'size', 'percent' ) );
file.item = new bp.Models.File( attributes );
bp.Uploader.filesQueue.add( file.item );
}
} );
uploader.refresh();
uploader.start();
} );
/**
* Update each file item on progress.
*
* @event UploadProgress
* @param {plupload.Uploader} uploader Uploader instance.
* @param {Object} file
*/
this.uploader.bind( 'UploadProgress', function( uploader, file ) {
file.item.set( _.pick( file, 'loaded', 'percent' ) );
} );
/**
* After a file is successfully uploaded, update its model.
*
* @event FileUploaded
* @param {plupload.Uploader} uploader Uploader instance.
* @param {plupload.File} file File that was uploaded.
* @param {Object} response Object with response properties.
* @return {mixed}
*/
this.uploader.bind( 'FileUploaded', function( uploader, file, response ) {
var message = self.strings.default_error;
try {
response = JSON.parse( response.response );
} catch ( e ) {
return self.feedback( message, e, file );
}
if ( ! _.isObject( response ) || _.isUndefined( response.success ) ) {
return self.feedback( message, null, file );
} else if ( ! response.success ) {
if ( response.data && response.data.message ) {
message = response.data.message;
}
return self.feedback( message, response.data, file );
}
_.each(['file','loaded','size','percent'], function( key ) {
file.item.unset( key );
} );
file.item.set( _.extend( response.data, { uploading: false } ) );
// Add the file to the Uploaded ones.
bp.Uploader.filesUploaded.add( file.item );
} );
/**
* Trigger an event to inform a new upload is being processed.
*
* Mainly used to remove an eventual warning.
*
* @event BeforeUpload
* @param {plupload.Uploader} uploader Uploader instance.
* @param {Array} files Array of file objects that were added to queue by the user.
*/
this.uploader.bind( 'BeforeUpload', function( uploader, files ) {
$( self ).trigger( 'bp-uploader-new-upload', uploader, files );
} );
/**
* Reset the filesQueue once the upload is complete.
*
* @event BeforeUpload
* @param {plupload.Uploader} uploader Uploader instance.
* @param {Array} files Array of file objects that were added to queue by the user.
*/
this.uploader.bind( 'UploadComplete', function( uploader, files ) {
$( self ).trigger( 'bp-uploader-upload-complete', uploader, files );
bp.Uploader.filesQueue.reset();
} );
/**
* Map Plupload errors & Create a warning when plupload failed.
*
* @event Error
* @param {plupload.Uploader} uploader Uploader instance.
* @param {Object} pluploadError Plupload error
*/
this.uploader.bind( 'Error', function( uploader, pluploadError ) {
var message = self.strings.default_error,
key,
errors = {
'FAILED': self.strings.upload_failed,
'FILE_EXTENSION_ERROR': self.strings.invalid_filetype,
'IMAGE_FORMAT_ERROR': self.strings.not_an_image,
'IMAGE_MEMORY_ERROR': self.strings.image_memory_exceeded,
'IMAGE_DIMENSIONS_ERROR': self.strings.image_dimensions_exceeded,
'GENERIC_ERROR': self.strings.upload_failed,
'IO_ERROR': self.strings.io_error,
'HTTP_ERROR': self.strings.http_error,
'SECURITY_ERROR': self.strings.security_error,
'FILE_SIZE_ERROR': self.strings.file_exceeds_size_limit.replace( '%s' , $( '<span />' ).text( pluploadError.file.name ).html() )
};
// Check for plupload errors.
for ( key in errors ) {
if ( pluploadError.code === plupload[ key ] ) {
message = errors[ key ];
break;
}
}
$( self ).trigger( 'bp-uploader-warning', message );
uploader.refresh();
} );
};
// Create a very generic Model for files.
bp.Models.File = Backbone.Model.extend( {
file: {}
} );
// Add Collections to store queue, uploaded files and errors.
$.extend( bp.Uploader, {
filesQueue : new Backbone.Collection(),
filesUploaded : new Backbone.Collection(),
filesError : new Backbone.Collection()
} );
// Extend wp.Backbone.View with .prepare() and .inject().
bp.View = bp.Backbone.View.extend( {
inject: function( selector ) {
this.render();
$(selector).html( this.el );
this.views.ready();
},
prepare: function() {
if ( ! _.isUndefined( this.model ) && _.isFunction( this.model.toJSON ) ) {
return this.model.toJSON();
} else {
return {};
}
}
} );
// BuddyPress Uploader main view.
bp.Views.Uploader = bp.View.extend( {
className: 'bp-uploader-window',
template: bp.template( 'upload-window' ),
defaults: _.pick( BP_Uploader.settings.defaults, 'container', 'drop_element', 'browse_button' ),
initialize: function() {
this.warnings = [];
this.model = new Backbone.Model( this.defaults );
this.on( 'ready', this.initUploader );
},
initUploader: function() {
this.uploader = new bp.Uploader.uploader();
$( this.uploader ).on( 'bp-uploader-warning', _.bind( this.setWarning, this ) );
$( this.uploader ).on( 'bp-uploader-new-upload', _.bind( this.resetWarning, this ) );
},
setWarning: function( event, message ) {
if ( _.isUndefined( message ) ) {
return;
}
var warning = new bp.Views.uploaderWarning( {
value: message
} ).render();
this.warnings.push( warning );
this.$el.after( warning.el );
},
resetWarning: function() {
if ( 0 === this.warnings.length ) {
return;
}
// Remove all warning views.
_.each( this.warnings, function( view ) {
view.remove();
} );
// Reset Warnings.
this.warnings = [];
}
} );
// BuddyPress Uploader warning view.
bp.Views.uploaderWarning = bp.View.extend( {
tagName: 'p',
className: 'warning',
initialize: function() {
this.value = this.options.value;
},
render: function() {
this.$el.html( this.value );
return this;
}
} );
// BuddyPress Uploader Files view.
bp.Views.uploaderStatus = bp.View.extend( {
className: 'files',
initialize: function() {
_.each( this.collection.models, this.addFile, this );
this.collection.on( 'change:percent', this.progress, this );
bp.Uploader.filesError.on( 'add', this.feedback, this );
},
addFile: function( file ) {
this.views.add( new bp.Views.uploaderProgress( { model: file } ) );
},
progress:function( model ) {
if ( ! _.isUndefined( model.get( 'percent' ) ) ) {
$( '#' + model.get('id') + ' .bp-progress .bp-bar' ).css( 'width', model.get('percent') + '%' );
}
},
feedback: function( model ) {
if ( ! _.isUndefined( model.get( 'message' ) ) && ! _.isUndefined( model.get( 'file' ) ) ) {
$( '#' + model.get( 'file' ).id ).html( model.get( 'message' ) ).addClass( 'error' );
}
}
} );
// BuddyPress Uploader File progress view.
bp.Views.uploaderProgress = bp.View.extend( {
className: 'bp-uploader-progress',
template: bp.template( 'progress-window' )
} );
})( window.bp, jQuery );