[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-core/js/ -> bp-plupload.js (source)

   1  /* global plupload, BP_Uploader, _, JSON, Backbone */
   2  
   3  window.wp = window.wp || {};
   4  window.bp = window.bp || {};
   5  
   6  ( function( bp, $ ) {
   7  
   8      // Bail if not set.
   9      if ( typeof BP_Uploader === 'undefined' ) {
  10          return;
  11      }
  12  
  13      /**
  14       * Extend the bp global with what we need from the wp one.
  15       * and make sure previously defined BuddyPress attributes
  16       * are not removed (eg: bp.mentions)
  17       */
  18      _.extend( bp, _.pick( wp, 'Backbone', 'ajax', 'template' ) );
  19  
  20      // Init Models, Collections, Views and the BuddyPress Uploader.
  21      bp.Models      = bp.Models || {};
  22      bp.Collections = bp.Collections || {};
  23      bp.Views       = bp.Views || {};
  24      bp.Uploader    = {};
  25  
  26      /**
  27       * BuddyPress Uploader.
  28       *
  29       * This is an adapted version of wp.Uploader.
  30       */
  31      bp.Uploader.uploader = function() {
  32          var self = this,
  33              isIE = navigator.userAgent.indexOf('Trident/') !== -1 || navigator.userAgent.indexOf('MSIE ') !== -1;
  34  
  35          this.params  = BP_Uploader.settings;
  36          this.strings = BP_Uploader.strings;
  37  
  38          this.supports = {
  39              upload: this.params.browser.supported
  40          };
  41  
  42          this.supported = this.supports.upload;
  43  
  44          if ( ! this.supported ) {
  45              /*jshint -W020 */
  46              BP_Uploader = undefined;
  47              return;
  48          }
  49  
  50          // Make sure flash sends cookies (seems in IE it does without switching to urlstream mode).
  51          if ( ! isIE && 'flash' === plupload.predictRuntime( this.params.defaults ) &&
  52              ( ! this.params.defaults.required_features || ! this.params.defaults.required_features.hasOwnProperty( 'send_binary_string' ) ) ) {
  53  
  54              this.params.defaults.required_features = this.params.defaults.required_features || {};
  55              this.params.defaults.required_features.send_binary_string = true;
  56          }
  57  
  58          this.uploader = new plupload.Uploader( this.params.defaults );
  59  
  60          /**
  61           * After the Uploader has been initialized, initialize some behaviors for the dropzone.
  62           *
  63           * @event Init
  64           * @param {plupload.Uploader} uploader Uploader instance.
  65           */
  66          this.uploader.bind( 'Init', function( uploader ) {
  67              var container    = $( '#' + self.params.defaults.container ),
  68                  drop_element = $( '#' + self.params.defaults.drop_element );
  69  
  70              if ( 'html4' === uploader.runtime ) {
  71                  uploader.settings.multipart_params.html4 = true;
  72              }
  73  
  74              /**
  75               * Avatars need to be cropped, by default we are using an original
  76               * max width of 450px, but there can be cases when this max width
  77               * is larger than the one of the Avatar UI (eg: on mobile). To avoid any
  78               * difficulties, we're adding a ui_available_width argument to the bp_params
  79               * object and set it according to the container width. This value will be
  80               * checked during the upload process to eventually adapt the resized avatar.
  81               */
  82              if ( 'bp_avatar_upload' ===  uploader.settings.multipart_params.action ) {
  83                  uploader.settings.multipart_params.bp_params.ui_available_width = container.width();
  84              }
  85  
  86              if ( uploader.features.dragdrop && ! self.params.browser.mobile ) {
  87                  container.addClass( 'drag-drop' );
  88  
  89                  drop_element.on( 'dragover.wp-uploader', function() {
  90                      container.addClass( 'drag-over' );
  91                  } );
  92  
  93                  drop_element.on( 'dragleave.wp-uploader, drop.wp-uploader', function() {
  94                      container.removeClass( 'drag-over' );
  95                  } );
  96              } else {
  97                  container.removeClass( 'drag-drop' );
  98                  drop_element.off( '.wp-uploader' );
  99              }
 100  
 101          } );
 102  
 103          // See https://core.trac.wordpress.org/ticket/37039.
 104          this.uploader.bind( 'postinit', function( up ) {
 105              up.refresh();
 106          });
 107  
 108          // Init BuddyPress Uploader.
 109          this.uploader.init();
 110  
 111          /**
 112           * Feedback callback.
 113           *
 114           * Add a new message to the errors collection, so it's possible
 115           * to give some feedback to the user.
 116           *
 117           * @param  {string}        message
 118           * @param  {object}        data
 119           * @param  {plupload.File} file     File that was uploaded.
 120           */
 121          this.feedback = function( message, data, file ) {
 122              if ( ! _.isNull( file ) && file.item ) {
 123                  file.item.clear();
 124              }
 125  
 126              bp.Uploader.filesError.unshift( {
 127                  message: message,
 128                  data:    data,
 129                  file:    file
 130              } );
 131          };
 132  
 133          /**
 134           * After files were filtered and added to the queue, create a model for each.
 135           *
 136           * @event FilesAdded
 137           * @param {plupload.Uploader} uploader Uploader instance.
 138           * @param {Array}             files    Array of file objects that were added to queue by the user.
 139           */
 140          this.uploader.bind( 'FilesAdded', function( uploader, files ) {
 141              var hundredmb = 100 * 1024 * 1024, max = parseInt( uploader.settings.max_file_size, 10 ),
 142                  _this = this;
 143  
 144              /**
 145               * In case the multiple selection is false (eg: avatar) stop the process and send
 146               * and event containing a warning.
 147               */
 148              if ( ! uploader.settings.multi_selection && files.length > 1 ) {
 149                  for ( var i in files ) {
 150                      uploader.removeFile( files[i] );
 151                  }
 152  
 153                  $( self ).trigger( 'bp-uploader-warning', self.strings.unique_file_warning );
 154                  return;
 155              }
 156  
 157              _.each( files, function( file ) {
 158                  var attributes;
 159  
 160                  // Ignore failed uploads.
 161                  if ( plupload.FAILED === file.status ) {
 162                      return;
 163                  }
 164  
 165                  if ( max > hundredmb && file.size > hundredmb && uploader.runtime !== 'html5' ) {
 166                      _this.uploadSizeError( uploader, file, true );
 167                  } else {
 168                      attributes = _.extend( {
 169                          id:        file.id,
 170                          file:      file,
 171                          uploading: true,
 172                          date:      new Date(),
 173                          filename:  file.name
 174                      }, _.pick( file, 'loaded', 'size', 'percent' ) );
 175  
 176                      file.item = new bp.Models.File( attributes );
 177                      bp.Uploader.filesQueue.add( file.item );
 178                  }
 179  
 180              } );
 181  
 182              uploader.refresh();
 183              uploader.start();
 184          } );
 185  
 186          /**
 187           * Update each file item on progress.
 188           *
 189           * @event UploadProgress
 190           * @param {plupload.Uploader} uploader Uploader instance.
 191           * @param {Object}            file
 192           */
 193          this.uploader.bind( 'UploadProgress', function( uploader, file ) {
 194              file.item.set( _.pick( file, 'loaded', 'percent' ) );
 195          } );
 196  
 197          /**
 198           * After a file is successfully uploaded, update its model.
 199           *
 200           * @event FileUploaded
 201           * @param {plupload.Uploader} uploader Uploader instance.
 202           * @param {plupload.File}     file     File that was uploaded.
 203           * @param {Object}            response Object with response properties.
 204           * @return {mixed}
 205           */
 206          this.uploader.bind( 'FileUploaded', function( uploader, file, response ) {
 207              var message = self.strings.default_error;
 208  
 209              try {
 210                  response = JSON.parse( response.response );
 211              } catch ( e ) {
 212                  return self.feedback( message, e, file );
 213              }
 214  
 215              if ( ! _.isObject( response ) || _.isUndefined( response.success ) ) {
 216                  return self.feedback( message, null, file );
 217              } else if ( ! response.success ) {
 218                  if ( response.data && response.data.message ) {
 219                      message = response.data.message;
 220                  }
 221  
 222                  return self.feedback( message, response.data, file );
 223              }
 224  
 225              _.each(['file','loaded','size','percent'], function( key ) {
 226                  file.item.unset( key );
 227              } );
 228  
 229              file.item.set( _.extend( response.data, { uploading: false } ) );
 230  
 231              //  Add the file to the Uploaded ones.
 232              bp.Uploader.filesUploaded.add( file.item );
 233  
 234          } );
 235  
 236          /**
 237           * Trigger an event to inform a new upload is being processed.
 238           *
 239           * Mainly used to remove an eventual warning.
 240           *
 241           * @event BeforeUpload
 242           * @param {plupload.Uploader} uploader Uploader instance.
 243           * @param {Array}             files    Array of file objects that were added to queue by the user.
 244           */
 245          this.uploader.bind( 'BeforeUpload', function( uploader, files ) {
 246              $( self ).trigger( 'bp-uploader-new-upload', uploader, files );
 247          } );
 248  
 249          /**
 250           * Reset the filesQueue once the upload is complete.
 251           *
 252           * @event BeforeUpload
 253           * @param {plupload.Uploader} uploader Uploader instance.
 254           * @param {Array}             files    Array of file objects that were added to queue by the user.
 255           */
 256          this.uploader.bind( 'UploadComplete', function( uploader, files ) {
 257              $( self ).trigger( 'bp-uploader-upload-complete', uploader, files );
 258              bp.Uploader.filesQueue.reset();
 259          } );
 260  
 261          /**
 262           * Map Plupload errors & Create a warning when plupload failed.
 263           *
 264           * @event Error
 265           * @param {plupload.Uploader} uploader Uploader instance.
 266           * @param {Object}            pluploadError Plupload error
 267           */
 268          this.uploader.bind( 'Error', function( uploader, pluploadError ) {
 269              var message = self.strings.default_error,
 270                  key,
 271                  errors = {
 272                      'FAILED':                 self.strings.upload_failed,
 273                      'FILE_EXTENSION_ERROR':   self.strings.invalid_filetype,
 274                      'IMAGE_FORMAT_ERROR':     self.strings.not_an_image,
 275                      'IMAGE_MEMORY_ERROR':     self.strings.image_memory_exceeded,
 276                      'IMAGE_DIMENSIONS_ERROR': self.strings.image_dimensions_exceeded,
 277                      'GENERIC_ERROR':          self.strings.upload_failed,
 278                      'IO_ERROR':               self.strings.io_error,
 279                      'HTTP_ERROR':             self.strings.http_error,
 280                      'SECURITY_ERROR':         self.strings.security_error,
 281                      'FILE_SIZE_ERROR':        self.strings.file_exceeds_size_limit.replace( '%s' , $( '<span />' ).text( pluploadError.file.name ).html() )
 282                  };
 283  
 284              // Check for plupload errors.
 285              for ( key in errors ) {
 286                  if ( pluploadError.code === plupload[ key ] ) {
 287                      message = errors[ key ];
 288                      break;
 289                  }
 290              }
 291  
 292              $( self ).trigger( 'bp-uploader-warning', message );
 293              uploader.refresh();
 294          } );
 295      };
 296  
 297      // Create a very generic Model for files.
 298      bp.Models.File = Backbone.Model.extend( {
 299          file: {}
 300      } );
 301  
 302      // Add Collections to store queue, uploaded files and errors.
 303      $.extend( bp.Uploader, {
 304          filesQueue    : new Backbone.Collection(),
 305          filesUploaded : new Backbone.Collection(),
 306          filesError    : new Backbone.Collection()
 307      } );
 308  
 309      // Extend wp.Backbone.View with .prepare() and .inject().
 310      bp.View = bp.Backbone.View.extend( {
 311          inject: function( selector ) {
 312              this.render();
 313              $(selector).html( this.el );
 314              this.views.ready();
 315          },
 316  
 317          prepare: function() {
 318              if ( ! _.isUndefined( this.model ) && _.isFunction( this.model.toJSON ) ) {
 319                  return this.model.toJSON();
 320              } else {
 321                  return {};
 322              }
 323          }
 324      } );
 325  
 326      // BuddyPress Uploader main view.
 327      bp.Views.Uploader = bp.View.extend( {
 328          className: 'bp-uploader-window',
 329          template: bp.template( 'upload-window' ),
 330  
 331          defaults: _.pick( BP_Uploader.settings.defaults, 'container', 'drop_element', 'browse_button' ),
 332  
 333          initialize: function() {
 334              this.warnings = [];
 335              this.model    = new Backbone.Model( this.defaults );
 336              this.on( 'ready', this.initUploader );
 337          },
 338  
 339          initUploader: function() {
 340              this.uploader = new bp.Uploader.uploader();
 341              $( this.uploader ).on( 'bp-uploader-warning', _.bind( this.setWarning, this ) );
 342              $( this.uploader ).on( 'bp-uploader-new-upload', _.bind( this.resetWarning, this ) );
 343          },
 344  
 345          setWarning: function( event, message ) {
 346              if ( _.isUndefined( message ) ) {
 347                  return;
 348              }
 349  
 350              var warning = new bp.Views.uploaderWarning( {
 351                  value: message
 352              } ).render();
 353  
 354              this.warnings.push( warning );
 355  
 356              this.$el.after( warning.el );
 357          },
 358  
 359          resetWarning: function() {
 360              if ( 0 === this.warnings.length ) {
 361                  return;
 362              }
 363  
 364              // Remove all warning views.
 365              _.each( this.warnings, function( view ) {
 366                  view.remove();
 367              } );
 368  
 369              // Reset Warnings.
 370              this.warnings = [];
 371          }
 372      } );
 373  
 374      // BuddyPress Uploader warning view.
 375      bp.Views.uploaderWarning = bp.View.extend( {
 376          tagName: 'p',
 377          className: 'warning',
 378  
 379          initialize: function() {
 380              this.value = this.options.value;
 381          },
 382  
 383          render: function() {
 384              this.$el.html( this.value );
 385              return this;
 386          }
 387      } );
 388  
 389      // BuddyPress Uploader Files view.
 390      bp.Views.uploaderStatus = bp.View.extend( {
 391          className: 'files',
 392  
 393          initialize: function() {
 394              _.each( this.collection.models, this.addFile, this );
 395              this.collection.on( 'change:percent', this.progress, this );
 396              bp.Uploader.filesError.on( 'add', this.feedback, this );
 397          },
 398  
 399          addFile: function( file ) {
 400              this.views.add( new bp.Views.uploaderProgress( { model: file } ) );
 401          },
 402  
 403          progress:function( model ) {
 404              if ( ! _.isUndefined( model.get( 'percent' ) ) ) {
 405                  $( '#' + model.get('id') + ' .bp-progress .bp-bar' ).css( 'width', model.get('percent') + '%' );
 406              }
 407          },
 408  
 409          feedback: function( model ) {
 410              if ( ! _.isUndefined( model.get( 'message' ) ) && ! _.isUndefined( model.get( 'file' ) ) ) {
 411                  $( '#' + model.get( 'file' ).id ).html( model.get( 'message' ) ).addClass( 'error' );
 412              }
 413          }
 414      } );
 415  
 416      // BuddyPress Uploader File progress view.
 417      bp.Views.uploaderProgress = bp.View.extend( {
 418          className: 'bp-uploader-progress',
 419          template: bp.template( 'progress-window' )
 420      } );
 421  
 422  })( window.bp, jQuery );


Generated: Wed Apr 24 01:01:03 2024 Cross-referenced by PHPXref 0.7.1