File: /storage/v6964/gopalak/public_html/wp-content/plugins/buddypress/bp-core/js/avatar.js
/* global BP_Uploader, _, Backbone */
window.bp = window.bp || {};
( function( bp, $ ) {
// Bail if not set.
if ( typeof BP_Uploader === 'undefined' ) {
return;
}
bp.Models = bp.Models || {};
bp.Collections = bp.Collections || {};
bp.Views = bp.Views || {};
bp.Avatar = {
start: function() {
var self = this;
/**
* Remove the bp-legacy UI
*
* bp.Avatar successfully loaded, we can now
* safely remove the Legacy UI.
*/
this.removeLegacyUI();
// Init some vars.
this.views = new Backbone.Collection();
this.jcropapi = {};
this.warning = null;
// Set up nav.
this.setupNav();
// Avatars are uploaded files.
this.avatars = bp.Uploader.filesUploaded;
// The Avatar Attachment object.
this.Attachment = new Backbone.Model();
// The Avatars history.
this.historicAvatars = null;
// Wait till the queue is reset.
bp.Uploader.filesQueue.on( 'reset', this.cropView, this );
/**
* In Administration screens we're using Thickbox
* We need to make sure to reset the views if it's closed or opened
*/
$( 'body.wp-admin' ).on( 'tb_unload', '#TB_window', function() {
self.resetViews();
} );
$( 'body.wp-admin' ).on( 'click', '.bp-members-avatar-user-edit', function() {
self.resetViews();
} );
},
removeLegacyUI: function() {
// User.
if ( $( '#avatar-upload-form' ).length ) {
$( '#avatar-upload' ).remove();
$( '#avatar-upload-form p' ).remove();
// Group Manage.
} else if ( $( '#group-settings-form' ).length ) {
$( '#group-settings-form p' ).each( function( i ) {
if ( 0 !== i ) {
$( this ).remove();
}
} );
if ( $( '#delete-group-avatar-button' ).length ) {
$( '#delete-group-avatar-button' ).remove();
}
// Group Create.
} else if ( $( '#group-create-body' ).length ) {
$( '.main-column p #file' ).remove();
$( '.main-column p #upload' ).remove();
// Member Admin.
} else if ( $( '#bp_members_user_admin_avatar a.bp-members-avatar-user-admin' ).length ) {
$( '#bp_members_user_admin_avatar a.bp-members-avatar-user-admin' ).remove();
}
},
setView: function( view ) {
// Clear views.
if ( ! _.isUndefined( this.views.models ) ) {
_.each( this.views.models, function( model ) {
model.get( 'view' ).remove();
}, this );
}
// Reset Views.
this.views.reset();
// Reset Avatars (file uploaded).
if ( ! _.isUndefined( this.avatars ) ) {
this.avatars.reset();
}
// Reset the Jcrop API.
if ( ! _.isEmpty( this.jcropapi ) ) {
this.jcropapi.destroy();
this.jcropapi = {};
}
// Load the required view.
switch ( view ) {
case 'upload':
this.uploaderView();
break;
case 'delete':
this.deleteView();
break;
case 'recycle':
this.recycleView();
break;
}
},
resetViews: function() {
// Reset to the uploader view.
this.nav.trigger( 'bp-avatar-view:changed', 'upload' );
// Reset to the uploader nav.
_.each( this.navItems.models, function( model ) {
if ( model.id === 'upload' ) {
model.set( { active: 1 } );
} else {
model.set( { active: 0 } );
}
} );
},
setupNav: function() {
var self = this,
initView, activeView;
this.navItems = new Backbone.Collection();
_.each( BP_Uploader.settings.nav, function( item, index ) {
if ( ! _.isObject( item ) ) {
return;
}
// Reset active View.
activeView = 0;
if ( 0 === index ) {
initView = item.id;
activeView = 1;
}
self.navItems.add( {
id : item.id,
name : item.caption,
href : '#',
active : activeView,
hide : _.isUndefined( item.hide ) ? 0 : item.hide
} );
} );
this.nav = new bp.Views.Nav( { collection: this.navItems } );
this.nav.inject( '.bp-avatar-nav' );
// Activate the initial view (uploader).
this.setView( initView );
// Listen to nav changes (it's like a do_action!).
this.nav.on( 'bp-avatar-view:changed', _.bind( this.setView, this ) );
},
uploaderView: function() {
// Listen to the Queued uploads.
bp.Uploader.filesQueue.on( 'add', this.uploadProgress, this );
// Create the BuddyPress Uploader.
var uploader = new bp.Views.Uploader();
// Add it to views.
this.views.add( { id: 'upload', view: uploader } );
// Display it.
uploader.inject( '.bp-avatar' );
},
uploadProgress: function() {
// Create the Uploader status view.
var avatarStatus = new bp.Views.uploaderStatus( { collection: bp.Uploader.filesQueue } );
if ( ! _.isUndefined( this.views.get( 'status' ) ) ) {
this.views.set( { id: 'status', view: avatarStatus } );
} else {
this.views.add( { id: 'status', view: avatarStatus } );
}
// Display it.
avatarStatus.inject( '.bp-avatar-status' );
},
cropView: function() {
var status;
// Bail there was an error during the Upload.
if ( _.isEmpty( this.avatars.models ) ) {
return;
}
// Make sure to remove the uploads status.
if ( ! _.isUndefined( this.views.get( 'status' ) ) ) {
status = this.views.get( 'status' );
status.get( 'view' ).remove();
this.views.remove( { id: 'status', view: status } );
}
// Create the Avatars view.
var avatar = new bp.Views.Avatars( { collection: this.avatars } );
this.views.add( { id: 'crop', view: avatar } );
avatar.inject( '.bp-avatar' );
},
setAvatar: function( avatar ) {
var self = this,
crop;
// Remove the crop view.
if ( ! _.isUndefined( this.views.get( 'crop' ) ) ) {
// Remove the JCrop API.
if ( ! _.isEmpty( this.jcropapi ) ) {
this.jcropapi.destroy();
this.jcropapi = {};
}
crop = this.views.get( 'crop' );
crop.get( 'view' ).remove();
this.views.remove( { id: 'crop', view: crop } );
}
// Set the avatar !
bp.ajax.post( 'bp_avatar_set', {
json: true,
original_file: avatar.get( 'url' ),
crop_w: avatar.get( 'w' ),
crop_h: avatar.get( 'h' ),
crop_x: avatar.get( 'x' ),
crop_y: avatar.get( 'y' ),
item_id: avatar.get( 'item_id' ),
object: avatar.get( 'object' ),
type: _.isUndefined( avatar.get( 'type' ) ) ? 'crop' : avatar.get( 'type' ),
nonce: avatar.get( 'nonces' ).set
} ).done( function( response ) {
var avatarStatus = new bp.Views.AvatarStatus( {
value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
type : 'success'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
// Update each avatars of the page.
$( '.' + avatar.get( 'object' ) + '-' + response.item_id + '-avatar' ).each( function() {
$(this).prop( 'src', response.avatar );
} );
// Inject the Delete nav.
bp.Avatar.navItems.get( 'delete' ).set( { hide: 0 } );
/**
* Set the Attachment object
*
* You can run extra actions once the avatar is set using:
* bp.Avatar.Attachment.on( 'change:url', function( data ) { your code } );
*
* In this case data.attributes will include the url to the newly
* uploaded avatar, the object and the item_id concerned.
*/
self.Attachment.set( _.extend(
_.pick( avatar.attributes, ['object', 'item_id'] ),
{ url: response.avatar, action: 'uploaded' }
) );
} ).fail( function( response ) {
var feedback = BP_Uploader.strings.default_error;
if ( ! _.isUndefined( response ) ) {
feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ];
}
var avatarStatus = new bp.Views.AvatarStatus( {
value : feedback,
type : 'error'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
} );
},
deleteView: function() {
// Create the delete model.
var delete_model = new Backbone.Model( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
'object',
'item_id',
'nonces'
) );
// Create the delete view.
var deleteView = new bp.Views.DeleteAvatar( { model: delete_model } );
// Add it to views.
this.views.add( { id: 'delete', view: deleteView } );
// Display it.
deleteView.inject( '.bp-avatar' );
},
deleteAvatar: function( model ) {
var self = this,
deleteView;
// Remove the delete view.
if ( ! _.isUndefined( this.views.get( 'delete' ) ) ) {
deleteView = this.views.get( 'delete' );
deleteView.get( 'view' ).remove();
this.views.remove( { id: 'delete', view: deleteView } );
}
// Remove the avatar!
bp.ajax.post( 'bp_avatar_delete', {
json: true,
item_id: model.get( 'item_id' ),
object: model.get( 'object' ),
nonce: model.get( 'nonces' ).remove
} ).done( function( response ) {
var avatarStatus = new bp.Views.AvatarStatus( {
value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
type : 'success'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
// Update each avatars of the page.
$( '.' + model.get( 'object' ) + '-' + response.item_id + '-avatar').each( function() {
$( this ).prop( 'src', response.avatar );
} );
// Remove the Delete nav.
bp.Avatar.navItems.get( 'delete' ).set( { active: 0, hide: 1 } );
/**
* Reset the Attachment object.
*
* You can run extra actions once the avatar is set using:
* bp.Avatar.Attachment.on( 'change:url', function( data ) { your code } );
*
* In this case data.attributes will include the url to the gravatar,
* the object and the item_id concerned.
*/
self.Attachment.set( _.extend(
_.pick( model.attributes, ['object', 'item_id'] ),
{ url: response.avatar, action: 'deleted' }
) );
} ).fail( function( response ) {
var feedback = BP_Uploader.strings.default_error;
if ( ! _.isUndefined( response ) ) {
feedback = BP_Uploader.strings.feedback_messages[ response.feedback_code ];
}
var avatarStatus = new bp.Views.AvatarStatus( {
value : feedback,
type : 'error'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
} );
},
removeWarning: function() {
if ( ! _.isNull( this.warning ) ) {
this.warning.remove();
}
},
displayWarning: function( message ) {
this.removeWarning();
this.warning = new bp.Views.uploaderWarning( {
value: message
} );
this.warning.inject( '.bp-avatar-status' );
},
recycleView: function() {
if ( ! this.historicAvatars ) {
this.historicAvatars = new Backbone.Collection( BP_Uploader.settings.history );
}
// Create the recycle view.
var recycleView = new bp.Views.RecycleAvatar( { collection: this.historicAvatars } );
// Add it to views.
this.views.add( { id: 'recycle', view: recycleView } );
// Display it.
recycleView.inject( '.bp-avatar' );
},
recycleHistoricAvatar: function( model ) {
var self = this;
model.set( 'selected', false );
// Recycle the avatar.
bp.ajax.post( 'bp_avatar_recycle_previous', {
json: true,
item_id: BP_Uploader.settings.defaults.multipart_params.bp_params.item_id,
avatar_id: model.get( 'id' ),
object: BP_Uploader.settings.defaults.multipart_params.bp_params.object,
nonce: BP_Uploader.settings.historyNonces.recylePrevious
} ).done( function( response ) {
if ( response.historicalAvatar ) {
model.collection.add( response.historicalAvatar );
}
model.collection.remove( model );
if ( response.feedback_code ) {
var avatarStatus = new bp.Views.AvatarStatus( {
value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
type : 'success'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
}
// Update each avatars of the page.
$( '.' + BP_Uploader.settings.defaults.multipart_params.bp_params.object + '-' + response.item_id + '-avatar' ).each( function() {
$( this ).prop( 'src', response.avatar );
} );
} ).fail( function( response ) {
var error_message = BP_Uploader.strings.default_error;
if ( response && response.message ) {
error_message = response.message;
}
var avatarStatus = new bp.Views.AvatarStatus( {
value : error_message,
type : 'error'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
} );
},
deletePreviousAvatar: function( model ) {
var self = this;
model.set( 'selected', false );
// Recycle the avatar.
bp.ajax.post( 'bp_avatar_delete_previous', {
json: true,
item_id: BP_Uploader.settings.defaults.multipart_params.bp_params.item_id,
avatar_id: model.get( 'id' ),
object: BP_Uploader.settings.defaults.multipart_params.bp_params.object,
nonce: BP_Uploader.settings.historyNonces.deletePrevious
} ).done( function( response ) {
model.collection.remove( model );
if ( response.feedback_code ) {
var avatarStatus = new bp.Views.AvatarStatus( {
value : BP_Uploader.strings.feedback_messages[ response.feedback_code ],
type : 'success'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
}
} ).fail( function( response ) {
var error_message = BP_Uploader.strings.default_error;
if ( response && response.message ) {
error_message = response.message;
}
var avatarStatus = new bp.Views.AvatarStatus( {
value : error_message,
type : 'error'
} );
self.views.add( {
id : 'status',
view : avatarStatus
} );
avatarStatus.inject( '.bp-avatar-status' );
} );
}
};
// Main Nav view.
bp.Views.Nav = bp.View.extend( {
tagName: 'ul',
className: 'avatar-nav-items',
events: {
'click .bp-avatar-nav-item' : 'toggleView'
},
initialize: function() {
var hasAvatar = _.findWhere( this.collection.models, { id: 'delete' } );
// Display a message to inform about the delete tab.
if ( 1 !== hasAvatar.get( 'hide' ) ) {
bp.Avatar.displayWarning( BP_Uploader.strings.has_avatar_warning );
}
_.each( this.collection.models, this.addNavItem, this );
this.collection.on( 'change:hide', this.showHideNavItem, this );
},
addNavItem: function( item ) {
/**
* The delete nav is not added if no avatar
* is set for the object.
*/
if ( 1 === item.get( 'hide' ) ) {
return;
}
this.views.add( new bp.Views.NavItem( { model: item } ) );
},
showHideNavItem: function( item ) {
var isRendered = null;
/**
* Loop in views to show/hide the nav item
* BuddyPress is only using this for the delete nav
*/
_.each( this.views._views[''], function( view ) {
if ( 1 === view.model.get( 'hide' ) ) {
view.remove();
}
// Check to see if the nav is not already rendered.
if ( item.get( 'id' ) === view.model.get( 'id' ) ) {
isRendered = true;
}
} );
// Add the Delete nav if not rendered.
if ( ! _.isBoolean( isRendered ) ) {
this.addNavItem( item );
}
},
toggleView: function( event ) {
event.preventDefault();
// First make sure to remove all warnings.
bp.Avatar.removeWarning();
var active = $( event.target ).data( 'nav' );
_.each( this.collection.models, function( model ) {
if ( model.id === active ) {
model.set( { active: 1 } );
this.trigger( 'bp-avatar-view:changed', model.id );
} else {
model.set( { active: 0 } );
}
}, this );
}
} );
// Nav item view.
bp.Views.NavItem = bp.View.extend( {
tagName: 'li',
className: 'avatar-nav-item',
template: bp.template( 'bp-avatar-nav' ),
initialize: function() {
if ( 1 === this.model.get( 'active' ) ) {
this.el.className += ' current';
}
this.el.id += 'bp-avatar-' + this.model.get( 'id' );
this.model.on( 'change:active', this.setCurrentNav, this );
},
setCurrentNav: function( model ) {
if ( 1 === model.get( 'active' ) ) {
this.$el.addClass( 'current' );
} else {
this.$el.removeClass( 'current' );
}
}
} );
// Avatars view.
bp.Views.Avatars = bp.View.extend( {
className: 'items',
initialize: function() {
_.each( this.collection.models, this.addItemView, this );
},
addItemView: function( item ) {
// Defaults to 150.
var full_d = { full_h: 150, full_w: 150 };
// Make sure to take in account bp_core_avatar_full_height or bp_core_avatar_full_width php filters.
if ( ! _.isUndefined( BP_Uploader.settings.crop.full_h ) && ! _.isUndefined( BP_Uploader.settings.crop.full_w ) ) {
full_d.full_h = BP_Uploader.settings.crop.full_h;
full_d.full_w = BP_Uploader.settings.crop.full_w;
}
// Set the avatar model.
item.set( _.extend( _.pick( BP_Uploader.settings.defaults.multipart_params.bp_params,
'object',
'item_id',
'nonces'
), full_d ) );
// Add the view.
this.views.add( new bp.Views.Avatar( { model: item } ) );
}
} );
// Avatar view.
bp.Views.Avatar = bp.View.extend( {
className: 'item',
template: bp.template( 'bp-avatar-item' ),
events: {
'click .avatar-crop-submit': 'cropAvatar'
},
initialize: function() {
_.defaults( this.options, {
full_h: BP_Uploader.settings.crop.full_h,
full_w: BP_Uploader.settings.crop.full_w,
aspectRatio : 1
} );
// Display a warning if the image is smaller than minimum advised.
if ( false !== this.model.get( 'feedback' ) ) {
bp.Avatar.displayWarning( this.model.get( 'feedback' ) );
}
this.on( 'ready', this.initCropper );
},
initCropper: function() {
var self = this,
tocrop = this.$el.find( '#avatar-to-crop img' ),
availableWidth = this.$el.width(),
selection = {}, crop_top, crop_bottom, crop_left, crop_right, nh, nw;
if ( ! _.isUndefined( this.options.full_h ) && ! _.isUndefined( this.options.full_w ) ) {
this.options.aspectRatio = this.options.full_w / this.options.full_h;
}
selection.w = this.model.get( 'width' );
selection.h = this.model.get( 'height' );
/**
* Make sure the crop preview is at the right of the avatar
* if the available width allowes it.
*/
if ( this.options.full_w + selection.w + 20 < availableWidth ) {
$( '#avatar-to-crop' ).addClass( 'adjust' );
this.$el.find( '.avatar-crop-management' ).addClass( 'adjust' );
}
if ( selection.h <= selection.w ) {
crop_top = Math.round( selection.h / 4 );
nh = nw = Math.round( selection.h / 2 );
crop_bottom = nh + crop_top;
crop_left = ( selection.w - nw ) / 2;
crop_right = nw + crop_left;
} else {
crop_left = Math.round( selection.w / 4 );
nh = nw = Math.round( selection.w / 2 );
crop_right = nw + crop_left;
crop_top = ( selection.h - nh ) / 2;
crop_bottom = nh + crop_top;
}
// Add the cropping interface.
tocrop.Jcrop( {
onChange: _.bind( self.showPreview, self ),
onSelect: _.bind( self.showPreview, self ),
aspectRatio: self.options.aspectRatio,
setSelect: [ crop_left, crop_top, crop_right, crop_bottom ]
}, function() {
// Get the Jcrop API.
bp.Avatar.jcropapi = this;
} );
},
cropAvatar: function( event ) {
event.preventDefault();
bp.Avatar.setAvatar( this.model );
},
showPreview: function( coords ) {
if ( ! coords.w || ! coords.h ) {
return;
}
if ( parseInt( coords.w, 10 ) > 0 ) {
var fw = this.options.full_w;
var fh = this.options.full_h;
var rx = fw / coords.w;
var ry = fh / coords.h;
// Update the model.
this.model.set( { x: coords.x, y: coords.y, w: coords.w, h: coords.h } );
$( '#avatar-crop-preview' ).css( {
maxWidth:'none',
width: Math.round( rx * this.model.get( 'width' ) )+ 'px',
height: Math.round( ry * this.model.get( 'height' ) )+ 'px',
marginLeft: '-' + Math.round( rx * this.model.get( 'x' ) ) + 'px',
marginTop: '-' + Math.round( ry * this.model.get( 'y' ) ) + 'px'
} );
}
}
} );
// BuddyPress Avatar Feedback view.
bp.Views.AvatarStatus = bp.View.extend( {
tagName: 'p',
className: 'updated',
id: 'bp-avatar-feedback',
initialize: function() {
this.el.className += ' ' + this.options.type;
this.value = this.options.value;
},
render: function() {
this.$el.html( this.value );
return this;
}
} );
// BuddyPress Avatar Delete view
bp.Views.DeleteAvatar = bp.View.extend( {
tagName: 'div',
id: 'bp-delete-avatar-container',
template: bp.template( 'bp-avatar-delete' ),
events: {
'click #bp-delete-avatar': 'deleteAvatar'
},
deleteAvatar: function( event ) {
event.preventDefault();
bp.Avatar.deleteAvatar( this.model );
}
} );
bp.Views.HistoryAvatarsItem = bp.View.extend( {
tagName: 'tr',
className: 'historic-avatar',
template: bp.template( 'bp-avatar-recycle-history-item' ),
events: {
'change input[name="avatar_id"]': 'selectAvatar'
},
initialize: function() {
this.model.on( 'change:selected', this.toggleSelection, this );
this.model.on( 'remove', this.clearView, this );
},
toggleSelection: function( model, selected ) {
if ( true === selected ) {
this.$el.parent().find( '#' + model.get( 'id' ) ).addClass( 'selected' );
} else {
this.$el.parent().find( '#' + model.get( 'id' ) ).removeClass( 'selected' );
this.$el.parent().find( '#avatar_' + model.get( 'id' ) ).prop( 'checked', false );
}
},
selectAvatar: function( event ) {
event.preventDefault();
if ( event.currentTarget.checked ) {
var self = this;
_.each( this.model.collection.models, function( model ) {
self.$el.parent().find( '#' + model.id ).removeClass( 'selected' );
model.set( 'selected', false, { silent: true } );
} );
this.model.set( 'selected', true );
}
},
clearView: function() {
this.views.view.remove();
}
} );
bp.Views.RecycleAvatar = bp.View.extend( {
tagName: 'div',
id: 'bp-avatars-history-container',
template: bp.template( 'bp-avatar-recycle' ),
events: {
'click button.avatar-history-action': 'doAvatarAction'
},
initialize: function() {
_.each( this.collection.models, function( model ) {
this.views.add( '#bp-avatars-history-list', new bp.Views.HistoryAvatarsItem( { model: model } ) );
}, this );
this.collection.on( 'change:selected', this.updateButtonStatus, this );
this.collection.on( 'add', this.addView, this );
},
addView: function( model ) {
this.views.add( '#bp-avatars-history-list', new bp.Views.HistoryAvatarsItem( { model: model } ) );
},
updateButtonStatus: function( model ) {
if ( true === model.get( 'selected' ) ) {
this.$el.find( 'button.disabled' ).removeClass( 'disabled' );
}
},
doAvatarAction: function( event ) {
event.preventDefault();
var buttonClasses = event.currentTarget.classList,
selected = this.collection.findWhere( { selected: true } );
if ( ! buttonClasses.contains( 'disabled' ) && selected ) {
// Make sure it's not possible to fire 2 actions at the same time.
this.$el.find( 'button.avatar-history-action' ).addClass( 'disabled' );
if ( buttonClasses.contains( 'recycle' ) ) {
bp.Avatar.recycleHistoricAvatar( selected );
} else if ( buttonClasses.contains( 'delete' ) ) {
bp.Avatar.deletePreviousAvatar( selected );
}
}
}
} );
bp.Avatar.start();
})( window.bp, jQuery );