[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-templates/bp-nouveau/js/ -> buddypress-messages.js (source)

   1  /* global wp, BP_Nouveau, _, Backbone, tinymce, tinyMCE */
   2  /* jshint devel: true */
   3  /* @since 3.0.0 */
   4  /* @version 10.3.0 */
   5  window.wp = window.wp || {};
   6  window.bp = window.bp || {};
   7  
   8  ( function( bp, $ ) {
   9  
  10      // Bail if not set.
  11      if ( typeof BP_Nouveau === 'undefined' ) {
  12          return;
  13      }
  14  
  15      _.extend( bp, _.pick( wp, 'Backbone', 'ajax', 'template' ) );
  16  
  17      bp.Models      = bp.Models || {};
  18      bp.Collections = bp.Collections || {};
  19      bp.Views       = bp.Views || {};
  20  
  21      bp.Nouveau = bp.Nouveau || {};
  22  
  23      /**
  24       * [Nouveau description]
  25       * @type {Object}
  26       */
  27      bp.Nouveau.Messages = {
  28          /**
  29           * [start description]
  30           * @return {[type]} [description]
  31           */
  32          start: function() {
  33              this.views    = new Backbone.Collection();
  34              this.threads  = new bp.Collections.Threads();
  35              this.messages = new bp.Collections.Messages();
  36              this.router   = new bp.Nouveau.Messages.Router();
  37              this.box      = 'inbox';
  38  
  39              // Set up supported routes.
  40              this.supportedRoutes = BP_Nouveau.messages.supportedRoutes;
  41  
  42              this.setupNav();
  43  
  44              Backbone.history.start( {
  45                  pushState: true,
  46                  root: BP_Nouveau.messages.rootUrl
  47              } );
  48          },
  49  
  50          setupNav: function() {
  51              var self = this;
  52  
  53              // First adapt the compose nav.
  54              $( '#compose-personal-li' ).addClass( 'last' );
  55  
  56              // Then listen to nav click and load the appropriate view.
  57              $( '#subnav a' ).on( 'click', function( event ) {
  58                  var view_id = $( event.target ).prop( 'id' ),
  59                      supportedView = _.keys( self.supportedRoutes );
  60  
  61                  if ( -1 === _.indexOf( supportedView, view_id ) || 'unsupported' === self.box ) {
  62                      return event;
  63                  }
  64  
  65                  event.preventDefault();
  66  
  67                  // Remove the editor to be sure it will be added dynamically later.
  68                  self.removeTinyMCE();
  69  
  70                  // The compose view is specific (toggle behavior).
  71                  if ( 'compose' === view_id ) {
  72                      // If it exists, it means the user wants to remove it.
  73                      if ( ! _.isUndefined( self.views.get( 'compose' ) ) ) {
  74                          var form = self.views.get( 'compose' );
  75                          form.get( 'view' ).remove();
  76                          self.views.remove( { id: 'compose', view: form } );
  77  
  78                          // Back to inbox.
  79                          if ( 'single' === self.box ) {
  80                              self.box = 'inbox';
  81                          }
  82  
  83                          // Navigate back to current box.
  84                          self.router.navigate( self.supportedRoutes[ self.box ] + '/', { trigger: true } );
  85  
  86                      // Otherwise load it.
  87                      } else {
  88                          self.router.navigate( self.supportedRoutes.compose + '/', { trigger: true } );
  89                      }
  90  
  91                  // Other views are classic.
  92                  } else {
  93  
  94                      if ( self.box !== view_id || ! _.isUndefined( self.views.get( 'compose' ) ) ) {
  95                          self.clearViews();
  96  
  97                          self.router.navigate( self.supportedRoutes[ view_id ] + '/', { trigger: true } );
  98                      }
  99                  }
 100              } );
 101          },
 102  
 103          updateNav: function( view ) {
 104              var currentView = this.box;
 105  
 106              if ( view ) {
 107                  currentView = view;
 108              }
 109  
 110              // Activate the appropriate nav.
 111              $( '#subnav ul li' ).each( function( l, li ) {
 112                  $( li ).removeClass( 'current selected' );
 113              } );
 114  
 115              $( '#subnav a#' + currentView ).closest( 'li' ).addClass( 'current selected' );
 116          },
 117  
 118          removeTinyMCE: function() {
 119              if ( typeof tinymce !== 'undefined' ) {
 120                  var editor = tinymce.get( 'message_content' );
 121  
 122                  if ( editor !== null ) {
 123                      tinymce.EditorManager.execCommand( 'mceRemoveEditor', true, 'message_content' );
 124                  }
 125              }
 126          },
 127  
 128          tinyMCEinit: function() {
 129              if ( typeof window.tinyMCE === 'undefined' || window.tinyMCE.activeEditor === null || typeof window.tinyMCE.activeEditor === 'undefined' ) {
 130                  return;
 131              } else {
 132                  // Mentions isn't available, so bail.
 133                  if ( _.isEmpty( bp.mentions ) ) {
 134                      return;
 135                  }
 136  
 137                  $( window.tinyMCE.activeEditor.contentDocument.activeElement )
 138                      .atwho( 'setIframe', $( '#message_content_ifr' )[0] )
 139                      .bp_mentions( {
 140                          data: [],
 141                          suffix: ' '
 142                      } );
 143              }
 144          },
 145  
 146          removeFeedback: function() {
 147              var feedback;
 148  
 149              if ( ! _.isUndefined( this.views.get( 'feedback' ) ) ) {
 150                  feedback = this.views.get( 'feedback' );
 151                  feedback.get( 'view' ).remove();
 152                  this.views.remove( { id: 'feedback', view: feedback } );
 153              }
 154          },
 155  
 156          displayFeedback: function( message, type ) {
 157              var feedback;
 158  
 159              // Make sure to remove the feedbacks.
 160              this.removeFeedback();
 161  
 162              if ( ! message ) {
 163                  return;
 164              }
 165  
 166              feedback = new bp.Views.Feedback( {
 167                  value: message,
 168                  type:  type || 'info'
 169              } );
 170  
 171              this.views.add( { id: 'feedback', view: feedback } );
 172  
 173              feedback.inject( '.bp-messages-feedback' );
 174          },
 175  
 176          clearViews: function() {
 177              // Clear views.
 178              if ( ! _.isUndefined( this.views.models ) ) {
 179                  _.each( this.views.models, function( model ) {
 180                      model.get( 'view' ).remove();
 181                  }, this );
 182  
 183                  this.views.reset();
 184              }
 185          },
 186  
 187          composeView: function() {
 188              // Remove all existing views.
 189              this.clearViews();
 190              this.updateNav( 'compose' );
 191  
 192              // Create the loop view.
 193              var form = new bp.Views.messageForm( {
 194                  model: new bp.Models.Message()
 195              } );
 196  
 197              this.views.add( { id: 'compose', view: form } );
 198  
 199              form.inject( '.bp-messages-content' );
 200          },
 201  
 202          threadsView: function() {
 203              this.updateNav();
 204  
 205              // Create the loop view.
 206              var threads_list = new bp.Views.userThreads( { collection: this.threads, box: this.box } );
 207  
 208              this.views.add( { id: 'threads', view: threads_list } );
 209  
 210              threads_list.inject( '.bp-messages-content' );
 211  
 212              // Attach filters.
 213              this.displayFilters( this.threads );
 214          },
 215  
 216          displayFilters: function( collection ) {
 217              var filters_view;
 218  
 219              // Create the model.
 220              this.filters = new Backbone.Model( {
 221                  'page'         : 1,
 222                  'total_page'   : 0,
 223                  'search_terms' : '',
 224                  'box'          : this.box
 225              } );
 226  
 227              // Use it in the filters viex.
 228              filters_view = new bp.Views.messageFilters( { model: this.filters, threads: collection } );
 229  
 230              this.views.add( { id: 'filters', view: filters_view } );
 231  
 232              filters_view.inject( '.bp-messages-filters' );
 233          },
 234  
 235          singleView: function( thread ) {
 236              // Remove all existing views.
 237              this.clearViews();
 238  
 239              this.box = 'single';
 240  
 241              // Create the single thread view.
 242              var single_thread = new bp.Views.userMessages( { collection: this.messages, thread: thread } );
 243  
 244              this.views.add( { id: 'single', view: single_thread } );
 245  
 246              single_thread.inject( '.bp-messages-content' );
 247          }
 248      };
 249  
 250      bp.Models.Message = Backbone.Model.extend( {
 251          defaults: {
 252              send_to         : [],
 253              subject         : '',
 254              message_content : '',
 255              meta            : {}
 256          },
 257  
 258          sendMessage: function() {
 259              var sent = bp.ajax.post(
 260                  'messages_send_message',
 261                  _.extend(
 262                      { nonce: BP_Nouveau.messages.nonces.send },
 263                      this.attributes
 264                  )
 265              );
 266  
 267              return sent;
 268          }
 269      } );
 270  
 271      bp.Models.Thread = Backbone.Model.extend( {
 272          defaults: {
 273              id            : 0,
 274              message_id    : 0,
 275              subject       : '',
 276              excerpt       : '',
 277              content       : '',
 278              unread        : true,
 279              sender_name   : '',
 280              sender_link   : '',
 281              sender_avatar : '',
 282              count         : 0,
 283              date          : 0,
 284              display_date  : '',
 285              recipients    : []
 286          },
 287  
 288          updateReadState: function( options ) {
 289              options = options || {};
 290              options.data = _.extend(
 291                  _.pick( this.attributes, ['id', 'message_id'] ),
 292                  {
 293                      action : 'messages_thread_read',
 294                      nonce  : BP_Nouveau.nonces.messages
 295                  }
 296              );
 297  
 298              return bp.ajax.send( options );
 299          }
 300      } );
 301  
 302      bp.Models.messageThread = Backbone.Model.extend( {
 303          defaults: {
 304              id            : 0,
 305              content       : '',
 306              sender_id     : 0,
 307              sender_name   : '',
 308              sender_link   : '',
 309              sender_avatar : '',
 310              date          : 0,
 311              display_date  : ''
 312          }
 313      } );
 314  
 315      bp.Collections.Threads = Backbone.Collection.extend( {
 316          model: bp.Models.Thread,
 317  
 318          initialize : function() {
 319              this.options = { page: 1, total_page: 0 };
 320          },
 321  
 322          sync: function( method, model, options ) {
 323              options         = options || {};
 324              options.context = this;
 325              options.data    = options.data || {};
 326  
 327              // Add generic nonce.
 328              options.data.nonce = BP_Nouveau.nonces.messages;
 329  
 330              if ( 'read' === method ) {
 331                  options.data = _.extend( options.data, {
 332                      action: 'messages_get_user_message_threads'
 333                  } );
 334  
 335                  return bp.ajax.send( options );
 336              }
 337          },
 338  
 339          parse: function( resp ) {
 340  
 341              if ( ! _.isArray( resp.threads ) ) {
 342                  resp.threads = [resp.threads];
 343              }
 344  
 345              _.each( resp.threads, function( value, index ) {
 346                  if ( _.isNull( value ) ) {
 347                      return;
 348                  }
 349  
 350                  resp.threads[index].id            = value.id;
 351                  resp.threads[index].message_id    = value.message_id;
 352                  resp.threads[index].subject       = value.subject;
 353                  resp.threads[index].excerpt       = value.excerpt;
 354                  resp.threads[index].content       = value.content;
 355                  resp.threads[index].unread        = value.unread;
 356                  resp.threads[index].sender_name   = value.sender_name;
 357                  resp.threads[index].sender_link   = value.sender_link;
 358                  resp.threads[index].sender_avatar = value.sender_avatar;
 359                  resp.threads[index].count         = value.count;
 360                  resp.threads[index].date          = new Date( value.date );
 361                  resp.threads[index].display_date  = value.display_date;
 362                  resp.threads[index].recipients    = value.recipients;
 363                  resp.threads[index].star_link     = value.star_link;
 364                  resp.threads[index].is_starred    = value.is_starred;
 365              } );
 366  
 367              if ( ! _.isUndefined( resp.meta ) ) {
 368                  this.options.page       = resp.meta.page;
 369                  this.options.total_page = resp.meta.total_page;
 370              }
 371  
 372              if ( bp.Nouveau.Messages.box ) {
 373                  this.options.box = bp.Nouveau.Messages.box;
 374              }
 375  
 376              if ( ! _.isUndefined( resp.extraContent ) ) {
 377                  _.extend( this.options, _.pick( resp.extraContent, [
 378                      'beforeLoop',
 379                      'afterLoop'
 380                  ] ) );
 381              }
 382  
 383              return resp.threads;
 384          },
 385  
 386          doAction: function( action, ids, options ) {
 387              options         = options || {};
 388              options.context = this;
 389              options.data    = options.data || {};
 390  
 391              options.data = _.extend( options.data, {
 392                  action: 'messages_' + action,
 393                  nonce : BP_Nouveau.nonces.messages,
 394                  id    : ids
 395              } );
 396  
 397              return bp.ajax.send( options );
 398          }
 399      } );
 400  
 401      bp.Collections.Messages = Backbone.Collection.extend( {
 402          model: bp.Models.messageThread,
 403          options: {},
 404  
 405          sync: function( method, model, options ) {
 406              options         = options || {};
 407              options.context = this;
 408              options.data    = options.data || {};
 409  
 410              // Add generic nonce.
 411              options.data.nonce = BP_Nouveau.nonces.messages;
 412  
 413              if ( 'read' === method ) {
 414                  options.data = _.extend( options.data, {
 415                      action: 'messages_get_thread_messages'
 416                  } );
 417  
 418                  return bp.ajax.send( options );
 419              }
 420  
 421              if ( 'create' === method ) {
 422                  options.data = _.extend( options.data, {
 423                      action : 'messages_send_reply',
 424                      nonce  : BP_Nouveau.messages.nonces.send
 425                  }, model || {} );
 426  
 427                  return bp.ajax.send( options );
 428              }
 429          },
 430  
 431          parse: function( resp ) {
 432  
 433              if ( ! _.isArray( resp.messages ) ) {
 434                  resp.messages = [resp.messages];
 435              }
 436  
 437              _.each( resp.messages, function( value, index ) {
 438                  if ( _.isNull( value ) ) {
 439                      return;
 440                  }
 441  
 442                  resp.messages[index].id            = value.id;
 443                  resp.messages[index].content       = value.content;
 444                  resp.messages[index].sender_id     = value.sender_id;
 445                  resp.messages[index].sender_name   = value.sender_name;
 446                  resp.messages[index].sender_link   = value.sender_link;
 447                  resp.messages[index].sender_avatar = value.sender_avatar;
 448                  resp.messages[index].date          = new Date( value.date );
 449                  resp.messages[index].display_date  = value.display_date;
 450                  resp.messages[index].star_link     = value.star_link;
 451                  resp.messages[index].is_starred    = value.is_starred;
 452              } );
 453  
 454              if ( ! _.isUndefined( resp.thread ) ) {
 455                  this.options.thread_id      = resp.thread.id;
 456                  this.options.thread_subject = resp.thread.subject;
 457                  this.options.recipients     = resp.thread.recipients;
 458              }
 459  
 460              return resp.messages;
 461          }
 462      } );
 463  
 464      // Extend wp.Backbone.View with .prepare() and .inject().
 465      bp.Nouveau.Messages.View = bp.Backbone.View.extend( {
 466          inject: function( selector ) {
 467              this.render();
 468              $(selector).html( this.el );
 469              this.views.ready();
 470          },
 471  
 472          prepare: function() {
 473              if ( ! _.isUndefined( this.model ) && _.isFunction( this.model.toJSON ) ) {
 474                  return this.model.toJSON();
 475              } else {
 476                  return {};
 477              }
 478          }
 479      } );
 480  
 481      // Feedback view.
 482      bp.Views.Feedback = bp.Nouveau.Messages.View.extend( {
 483          tagName: 'div',
 484          className: 'bp-messages bp-user-messages-feedback',
 485          template  : bp.template( 'bp-messages-feedback' ),
 486  
 487          initialize: function() {
 488              this.model = new Backbone.Model( {
 489                  type: this.options.type || 'info',
 490                  message: this.options.value
 491              } );
 492          }
 493      } );
 494  
 495      // Hook view.
 496      bp.Views.Hook = bp.Nouveau.Messages.View.extend( {
 497          tagName: 'div',
 498          template  : bp.template( 'bp-messages-hook' ),
 499  
 500          initialize: function() {
 501              this.model = new Backbone.Model( {
 502                  extraContent: this.options.extraContent
 503              } );
 504  
 505              this.el.className = 'bp-messages-hook';
 506  
 507              if ( this.options.className ) {
 508                  this.el.className += ' ' + this.options.className;
 509              }
 510          }
 511      } );
 512  
 513      bp.Views.messageEditor = bp.Nouveau.Messages.View.extend( {
 514          template  : bp.template( 'bp-messages-editor' ),
 515  
 516          initialize: function() {
 517              this.on( 'ready', this.activateTinyMce, this );
 518          },
 519  
 520          activateTinyMce: function() {
 521              if ( typeof tinymce !== 'undefined' ) {
 522                  tinymce.EditorManager.execCommand( 'mceAddEditor', true, 'message_content' );
 523              }
 524          }
 525      } );
 526  
 527      bp.Views.messageForm = bp.Nouveau.Messages.View.extend( {
 528          tagName   : 'form',
 529          id        : 'send_message_form',
 530          className : 'standard-form',
 531          template  : bp.template( 'bp-messages-form' ),
 532  
 533          events: {
 534              'click #bp-messages-send'  : 'sendMessage',
 535              'click #bp-messages-reset' : 'resetForm'
 536          },
 537  
 538          initialize: function() {
 539              // Clone the model to set the resetted one.
 540              this.resetModel = this.model.clone();
 541  
 542              // Add the editor view.
 543              this.views.add( '#bp-message-content', new bp.Views.messageEditor() );
 544  
 545              this.model.on( 'change', this.resetFields, this );
 546  
 547              // Activate bp_mentions.
 548              this.on( 'ready', this.addMentions, this );
 549          },
 550  
 551          addMentions: function() {
 552              var sendToInput = $( this.el ).find( '#send-to-input' ),
 553                  mention = bp.Nouveau.getLinkParams( null, 'r' ) || null;
 554  
 555              // Add autocomplete to send_to field.
 556              sendToInput.bp_mentions( {
 557                  data: [],
 558                  suffix: ' '
 559              } );
 560  
 561              // Check for mention.
 562              if ( ! _.isNull( mention ) ) {
 563                  sendToInput.val( '@' + _.escape( mention ) + ' ' );
 564                  sendToInput.trigger( 'focus' );
 565              }
 566          },
 567  
 568          resetFields: function( model ) {
 569              // Clean inputs.
 570              _.each( model.previousAttributes(), function( value, input ) {
 571                  if ( 'message_content' === input ) {
 572                      // tinyMce.
 573                      if ( undefined !== tinyMCE.activeEditor && null !== tinyMCE.activeEditor ) {
 574                          tinyMCE.activeEditor.setContent( '' );
 575                      }
 576  
 577                  // All except meta or empty value.
 578                  } else if ( 'meta' !== input && false !== value ) {
 579                      $( 'input[name="' + input + '"]' ).val( '' );
 580                  }
 581              } );
 582  
 583              // Listen to this to eventually reset your custom inputs.
 584              $( this.el ).trigger( 'message:reset', _.pick( model.previousAttributes(), 'meta' ) );
 585          },
 586  
 587          sendMessage: function( event ) {
 588              var meta = {}, errors = [], self = this,
 589                  button = event.currentTarget;
 590  
 591              event.preventDefault();
 592  
 593              bp.Nouveau.Messages.removeFeedback();
 594              $( button ).addClass( 'disabled' ).prop( 'disabled', true );
 595  
 596              // Set the content and meta.
 597              _.each( this.$el.serializeArray(), function( pair ) {
 598                  pair.name = pair.name.replace( '[]', '' );
 599  
 600                  // Group extra fields in meta.
 601                  if ( -1 === _.indexOf( ['send_to', 'subject', 'message_content'], pair.name ) ) {
 602                      if ( _.isUndefined( meta[ pair.name ] ) ) {
 603                          meta[ pair.name ] = pair.value;
 604                      } else {
 605                          if ( ! _.isArray( meta[ pair.name ] ) ) {
 606                              meta[ pair.name ] = [ meta[ pair.name ] ];
 607                          }
 608  
 609                          meta[ pair.name ].push( pair.value );
 610                      }
 611  
 612                  // Prepare the core model.
 613                  } else {
 614                      // Send to.
 615                      if ( 'send_to' === pair.name ) {
 616                          var usernames = pair.value.match( /(^|[^@\w\-])@([a-zA-Z0-9_\-]{1,50})\b/g );
 617  
 618                          if ( ! usernames ) {
 619                              errors.push( 'send_to' );
 620                          } else {
 621                              usernames = usernames.map( function( username ) {
 622                                  username = username.trim();
 623                                  return username;
 624                              } );
 625  
 626                              if ( ! usernames || ! _.isArray( usernames ) ) {
 627                                  errors.push( 'send_to' );
 628                              }
 629  
 630                              this.model.set( 'send_to', usernames, { silent: true } );
 631                          }
 632  
 633                      // Subject and content.
 634                      } else {
 635                          // Message content.
 636                          if ( 'message_content' === pair.name && undefined !== tinyMCE.activeEditor ) {
 637                              pair.value = tinyMCE.activeEditor.getContent();
 638                          }
 639  
 640                          if ( ! pair.value ) {
 641                              errors.push( pair.name );
 642                          } else {
 643                              this.model.set( pair.name, pair.value, { silent: true } );
 644                          }
 645                      }
 646                  }
 647  
 648              }, this );
 649  
 650              if ( errors.length ) {
 651                  var feedback = '';
 652                  _.each( errors, function( e ) {
 653                      feedback += BP_Nouveau.messages.errors[ e ] + '<br/>';
 654                  } );
 655  
 656                  bp.Nouveau.Messages.displayFeedback( feedback, 'error' );
 657                  return;
 658              }
 659  
 660              // Prevents multiple frenetic clicks!
 661              if ( true === this.model.get( 'sending' ) ) {
 662                  return;
 663              }
 664  
 665              // Set meta.
 666              this.model.set(
 667                  {
 668                      sending: true,
 669                      meta: meta
 670                  },
 671                  {
 672                      silent: true
 673                  }
 674              );
 675  
 676              // Send the message.
 677              this.model.sendMessage().done( function( response ) {
 678                  // Reset the model.
 679                  self.model.set( self.resetModel );
 680  
 681                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
 682  
 683                  // Remove tinyMCE.
 684                  bp.Nouveau.Messages.removeTinyMCE();
 685  
 686                  // Remove the form view.
 687                  var form = bp.Nouveau.Messages.views.get( 'compose' );
 688                  form.get( 'view' ).remove();
 689                  bp.Nouveau.Messages.views.remove( { id: 'compose', view: form } );
 690  
 691                  bp.Nouveau.Messages.router.navigate( bp.Nouveau.Messages.supportedRoutes.sentbox + '/', { trigger: true } );
 692              } ).fail( function( response ) {
 693                  if ( response.feedback ) {
 694                      bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
 695                  }
 696              } ).always( function() {
 697                  self.model.set( 'sending', false, { silent: true } );
 698                  $( button ).removeClass( 'disabled' ).prop( 'disabled', false );
 699              } );
 700          },
 701  
 702          resetForm: function( event ) {
 703              event.preventDefault();
 704  
 705              this.model.set( this.resetModel );
 706          }
 707      } );
 708  
 709      bp.Views.userThreads = bp.Nouveau.Messages.View.extend( {
 710          tagName   : 'div',
 711  
 712          events: {
 713              'click .subject' : 'changePreview'
 714          },
 715  
 716          initialize: function() {
 717              var Views = [
 718                  new bp.Nouveau.Messages.View( { tagName: 'ul', id: 'message-threads', className: 'message-lists' } ),
 719                  new bp.Views.previewThread( { collection: this.collection } )
 720              ];
 721  
 722              _.each( Views, function( view ) {
 723                  this.views.add( view );
 724              }, this );
 725  
 726              // Load threads for the active view.
 727              this.requestThreads();
 728  
 729              this.collection.on( 'reset', this.cleanContent, this );
 730              this.collection.on( 'add', this.addThread, this );
 731          },
 732  
 733          requestThreads: function() {
 734              this.collection.reset();
 735  
 736              bp.Nouveau.Messages.displayFeedback( BP_Nouveau.messages.loading, 'loading' );
 737  
 738              this.collection.fetch( {
 739                  data    : _.pick( this.options, 'box' ),
 740                  success : _.bind( this.threadsFetched, this ),
 741                  error   : this.threadsFetchError
 742              } );
 743          },
 744  
 745          threadsFetched: function() {
 746              bp.Nouveau.Messages.removeFeedback();
 747  
 748              // Display the bp_after_member_messages_loop hook.
 749              if ( this.collection.options.afterLoop ) {
 750                  this.views.add( new bp.Views.Hook( { extraContent: this.collection.options.afterLoop, className: 'after-messages-loop' } ), { at: 1 } );
 751              }
 752  
 753              // Display the bp_before_member_messages_loop hook.
 754              if ( this.collection.options.beforeLoop ) {
 755                  this.views.add( new bp.Views.Hook( { extraContent: this.collection.options.beforeLoop, className: 'before-messages-loop' } ), { at: 0 } );
 756              }
 757  
 758              // Inform the user about how to use the UI.
 759              bp.Nouveau.Messages.displayFeedback( BP_Nouveau.messages.howto, 'info' );
 760          },
 761  
 762          threadsFetchError: function( collection, response ) {
 763              bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
 764          },
 765  
 766          cleanContent: function() {
 767              _.each( this.views._views['#message-threads'], function( view ) {
 768                  view.remove();
 769              } );
 770          },
 771  
 772          addThread: function( thread ) {
 773              var selected = this.collection.findWhere( { active: true } );
 774  
 775              if ( _.isUndefined( selected ) ) {
 776                  thread.set( 'active', true );
 777              }
 778  
 779              this.views.add( '#message-threads', new bp.Views.userThread( { model: thread } ) );
 780          },
 781  
 782          setActiveThread: function( active ) {
 783              if ( ! active ) {
 784                  return;
 785              }
 786  
 787              _.each( this.collection.models, function( thread ) {
 788                  if ( thread.id === active ) {
 789                      thread.set( 'active', true );
 790                  } else {
 791                      thread.unset( 'active' );
 792                  }
 793              }, this );
 794          },
 795  
 796          changePreview: function( event ) {
 797              var target = $( event.currentTarget );
 798  
 799              event.preventDefault();
 800              bp.Nouveau.Messages.removeFeedback();
 801  
 802              // If the click is done on an active conversation, open it.
 803              if ( target.closest( '.thread-item' ).hasClass( 'selected' ) ) {
 804                  bp.Nouveau.Messages.router.navigate(
 805                      'view/' + target.closest( '.thread-content' ).data( 'thread-id' ) + '/',
 806                      { trigger: true }
 807                  );
 808  
 809              // Otherwise activate the conversation and display its preview.
 810              } else {
 811                  this.setActiveThread( target.closest( '.thread-content' ).data( 'thread-id' ) );
 812  
 813                  $( '.message-action-view' ).focus();
 814              }
 815          }
 816      } );
 817  
 818      bp.Views.userThread = bp.Nouveau.Messages.View.extend( {
 819          tagName   : 'li',
 820          template  : bp.template( 'bp-messages-thread' ),
 821          className : 'thread-item',
 822  
 823          events: {
 824              'click .message-check' : 'singleSelect'
 825          },
 826  
 827          initialize: function() {
 828              if ( this.model.get( 'active' ) ) {
 829                  this.el.className += ' selected';
 830              }
 831  
 832              if ( this.model.get( 'unread' ) ) {
 833                  this.el.className += ' unread';
 834              }
 835  
 836              if ( 'sentbox' === bp.Nouveau.Messages.box ) {
 837                  var recipientsCount = this.model.get( 'recipients' ).length, toOthers = '';
 838  
 839                  if ( 2 === recipientsCount ) {
 840                      toOthers = BP_Nouveau.messages.toOthers.one;
 841                  } else if ( 2 < recipientsCount ) {
 842                      toOthers = BP_Nouveau.messages.toOthers.more.replace( '%d', Number( recipientsCount - 1 ) );
 843                  }
 844  
 845                  this.model.set( {
 846                      recipientsCount: recipientsCount,
 847                      toOthers: toOthers
 848                  }, { silent: true } );
 849              } else if ( this.model.get( 'recipientsCount' )  ) {
 850                  this.model.unset( 'recipientsCount', { silent: true } );
 851              }
 852  
 853              this.model.on( 'change:active', this.toggleClass, this );
 854              this.model.on( 'change:unread', this.updateReadState, this );
 855              this.model.on( 'change:checked', this.bulkSelect, this );
 856              this.model.on( 'remove', this.cleanView, this );
 857          },
 858  
 859          toggleClass: function( model ) {
 860              if ( true === model.get( 'active' ) ) {
 861                  $( this.el ).addClass( 'selected' );
 862              } else {
 863                  $( this.el ).removeClass( 'selected' );
 864              }
 865          },
 866  
 867          updateReadState: function( model, state ) {
 868              if ( false === state ) {
 869                  $( this.el ).removeClass( 'unread' );
 870              } else {
 871                  $( this.el ).addClass( 'unread' );
 872              }
 873          },
 874  
 875          bulkSelect: function( model ) {
 876              if ( $( '#bp-message-thread-' + model.get( 'id' ) ).length ) {
 877                  $( '#bp-message-thread-' + model.get( 'id' ) ).prop( 'checked',model.get( 'checked' ) );
 878              }
 879          },
 880  
 881          singleSelect: function( event ) {
 882              var isChecked = $( event.currentTarget ).prop( 'checked' );
 883  
 884              // To avoid infinite loops.
 885              this.model.set( 'checked', isChecked, { silent: true } );
 886  
 887              var hasChecked = false;
 888  
 889              _.each( this.model.collection.models, function( model ) {
 890                  if ( true === model.get( 'checked' ) ) {
 891                      hasChecked = true;
 892                  }
 893              } );
 894  
 895              if ( hasChecked ) {
 896                  $( '#user-messages-bulk-actions' ).closest( '.bulk-actions-wrap' ).removeClass( 'bp-hide' );
 897  
 898                  // Inform the user about how to use the bulk actions.
 899                  bp.Nouveau.Messages.displayFeedback( BP_Nouveau.messages.howtoBulk, 'info' );
 900              } else {
 901                  $( '#user-messages-bulk-actions' ).closest( '.bulk-actions-wrap' ).addClass( 'bp-hide' );
 902  
 903                  bp.Nouveau.Messages.removeFeedback();
 904              }
 905          },
 906  
 907          cleanView: function() {
 908              this.views.view.remove();
 909          }
 910      } );
 911  
 912      bp.Views.previewThread = bp.Nouveau.Messages.View.extend( {
 913          tagName: 'div',
 914          id: 'thread-preview',
 915          template  : bp.template( 'bp-messages-preview' ),
 916  
 917          events: {
 918              'click .actions button' : 'doAction',
 919              'click .actions a'      : 'doAction'
 920          },
 921  
 922          initialize: function() {
 923              this.collection.on( 'change:active', this.setPreview, this );
 924              this.collection.on( 'change:is_starred', this.updatePreview, this );
 925              this.collection.on( 'reset', this.emptyPreview, this );
 926              this.collection.on( 'remove', this.emptyPreview, this );
 927          },
 928  
 929          render: function() {
 930              // Only render if we have some content to render.
 931              if ( _.isUndefined( this.model ) || true !== this.model.get( 'active' ) ) {
 932                  return;
 933              }
 934  
 935              bp.Nouveau.Messages.View.prototype.render.apply( this, arguments );
 936          },
 937  
 938          setPreview: function( model ) {
 939              var self = this;
 940  
 941              this.model = model;
 942  
 943              if ( true === model.get( 'unread' ) ) {
 944                  this.model.updateReadState().done( function() {
 945                      self.model.set( 'unread', false );
 946                  } );
 947              }
 948  
 949              this.render();
 950          },
 951  
 952          updatePreview: function( model ) {
 953              if ( true === model.get( 'active' ) ) {
 954                  this.render();
 955              }
 956          },
 957  
 958          emptyPreview: function() {
 959              $( this.el ).html( '' );
 960          },
 961  
 962          doAction: function( event ) {
 963              var action = $( event.currentTarget ).data( 'bp-action' ), self = this, options = {}, mid,
 964                  feedback = BP_Nouveau.messages.doingAction;
 965  
 966              if ( ! action ) {
 967                  return event;
 968              }
 969  
 970              event.preventDefault();
 971  
 972              var model = this.collection.findWhere( { active: true } );
 973  
 974              if ( ! model.get( 'id' ) ) {
 975                  return;
 976              }
 977  
 978              mid = model.get( 'id' );
 979  
 980              // Open the full conversation.
 981              if ( 'view' === action ) {
 982                  bp.Nouveau.Messages.router.navigate(
 983                      'view/' + mid + '/',
 984                      { trigger: true }
 985                  );
 986  
 987                  return;
 988  
 989              // Star/Unstar actions needs to use a specific id and nonce.
 990              } else if ( 'star' === action || 'unstar' === action ) {
 991                  options.data = {
 992                      'star_nonce' : model.get( 'star_nonce' )
 993                  };
 994  
 995                  mid = model.get( 'starred_id' );
 996              }
 997  
 998              if ( ! _.isUndefined( feedback[ action ] ) ) {
 999                  bp.Nouveau.Messages.displayFeedback( feedback[ action ], 'loading' );
1000              }
1001  
1002              this.collection.doAction( action, mid, options ).done( function( response ) {
1003                  // Remove previous feedback.
1004                  bp.Nouveau.Messages.removeFeedback();
1005  
1006                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1007  
1008                  if ( 'delete' === action || 'exit' === action || ( 'starred' === self.collection.options.box && 'unstar' === action ) ) {
1009                      // Remove from the list of messages.
1010                      self.collection.remove( model.get( 'id' ) );
1011  
1012                      // And Requery.
1013                      self.collection.fetch( {
1014                          data : _.pick( self.collection.options, ['box', 'search_terms', 'page'] )
1015                      } );
1016                  } else if ( 'unstar' === action || 'star' === action ) {
1017                      // Update the model attributes--updates the star icon.
1018                      _.each( response.messages, function( updated ) {
1019                          model.set( updated );
1020                      } );
1021                      model.set( _.first( response.messages ) );
1022                  } else if ( response.messages ) {
1023                      model.set( _.first( response.messages ) );
1024                  }
1025              } ).fail( function( response ) {
1026                  // Remove previous feedback.
1027                  bp.Nouveau.Messages.removeFeedback();
1028  
1029                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1030              } );
1031          }
1032      } );
1033  
1034      bp.Views.Pagination = bp.Nouveau.Messages.View.extend( {
1035          tagName   : 'li',
1036          className : 'last filter',
1037          template  :  bp.template( 'bp-messages-paginate' )
1038      } );
1039  
1040      bp.Views.BulkActions = bp.Nouveau.Messages.View.extend( {
1041          tagName   : 'div',
1042          template  :  bp.template( 'bp-bulk-actions' ),
1043  
1044          events : {
1045              'click #user_messages_select_all' : 'bulkSelect',
1046              'click .bulk-apply'               : 'doBulkAction'
1047          },
1048  
1049          bulkSelect: function( event ) {
1050              var isChecked = $( event.currentTarget ).prop( 'checked' );
1051  
1052              if ( isChecked ) {
1053                  $( this.el ).find( '.bulk-actions-wrap' ).removeClass( 'bp-hide' ).addClass( 'bp-show' );
1054  
1055                  // Inform the user about how to use the bulk actions.
1056                  bp.Nouveau.Messages.displayFeedback( BP_Nouveau.messages.howtoBulk, 'info' );
1057              } else {
1058                  $( this.el ).find( '.bulk-actions-wrap' ).addClass( 'bp-hide' );
1059  
1060                  bp.Nouveau.Messages.removeFeedback();
1061              }
1062  
1063              _.each( this.collection.models, function( model ) {
1064                  model.set( 'checked', isChecked );
1065              } );
1066          },
1067  
1068          doBulkAction: function( event ) {
1069              var self = this, options = {}, ids, attr = 'id',
1070                  feedback = BP_Nouveau.messages.doingAction;
1071  
1072              event.preventDefault();
1073  
1074              var action = $( '#user-messages-bulk-actions' ).val();
1075  
1076              if ( ! action ) {
1077                  return;
1078              }
1079  
1080              var threads    = this.collection.where( { checked: true } );
1081              var thread_ids = _.map( threads, function( model ) {
1082                  return model.get( 'id' );
1083              } );
1084  
1085              // Default to thread ids.
1086              ids = thread_ids;
1087  
1088              // We need to get the starred ids.
1089              if ( 'star' === action || 'unstar' === action ) {
1090                  ids = _.map( threads, function( model ) {
1091                      return model.get( 'starred_id' );
1092                  } );
1093  
1094                  if ( 1 === ids.length ) {
1095                      options.data = {
1096                          'star_nonce' : threads[0].get( 'star_nonce' )
1097                      };
1098                  }
1099  
1100                  // Map with first message starred in the thread.
1101                  attr = 'starred_id';
1102              }
1103  
1104              // Message id to Thread id.
1105              var m_tid = _.object( _.map( threads, function (model) {
1106                  return [model.get( attr ), model.get( 'id' )];
1107              } ) );
1108  
1109              if ( ! _.isUndefined( feedback[ action ] ) ) {
1110                  bp.Nouveau.Messages.displayFeedback( feedback[ action ], 'loading' );
1111              }
1112  
1113              this.collection.doAction( action, ids, options ).done( function( response ) {
1114                  // Remove previous feedback.
1115                  bp.Nouveau.Messages.removeFeedback();
1116  
1117                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1118  
1119                  if ( 'delete' === action || 'exit' === action || ( 'starred' === self.collection.options.box && 'unstar' === action ) ) {
1120                      // Remove from the list of messages.
1121                      self.collection.remove( thread_ids );
1122  
1123                      // And Requery.
1124                      self.collection.fetch( {
1125                          data : _.pick( self.collection.options, ['box', 'search_terms', 'page'] )
1126                      } );
1127                  } else if ( response.messages ) {
1128                      // Update each model attributes.
1129                      _.each( response.messages, function( updated, id ) {
1130                          var model = self.collection.get( m_tid[id] );
1131                          model.set( updated );
1132                      } );
1133                  }
1134              } ).fail( function( response ) {
1135                  // Remove previous feedback.
1136                  bp.Nouveau.Messages.removeFeedback();
1137  
1138                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1139              } );
1140          }
1141      } );
1142  
1143      bp.Views.messageFilters = bp.Nouveau.Messages.View.extend( {
1144          tagName: 'ul',
1145          template:  bp.template( 'bp-messages-filters' ),
1146  
1147          events : {
1148              'search #user_messages_search'      : 'resetSearchTerms',
1149              'submit #user_messages_search_form' : 'setSearchTerms',
1150              'click #bp-messages-next-page'      : 'nextPage',
1151              'click #bp-messages-prev-page'      : 'prevPage'
1152          },
1153  
1154          initialize: function() {
1155              this.model.on( 'change', this.filterThreads, this );
1156              this.options.threads.on( 'sync', this.addPaginatation, this );
1157          },
1158  
1159          addPaginatation: function( collection ) {
1160              _.each( this.views._views, function( view ) {
1161                  if ( ! _.isUndefined( view ) ) {
1162                      _.first( view ).remove();
1163                  }
1164              } );
1165  
1166              this.views.add( new bp.Views.Pagination( { model: new Backbone.Model( collection.options ) } ) );
1167  
1168              this.views.add( '.user-messages-bulk-actions', new bp.Views.BulkActions( {
1169                  model: new Backbone.Model( BP_Nouveau.messages.bulk_actions ),
1170                  collection : collection
1171              } ) );
1172          },
1173  
1174          filterThreads: function() {
1175              bp.Nouveau.Messages.displayFeedback( BP_Nouveau.messages.loading, 'loading' );
1176  
1177              this.options.threads.reset();
1178              _.extend( this.options.threads.options, _.pick( this.model.attributes, ['box', 'search_terms'] ) );
1179  
1180              this.options.threads.fetch( {
1181                  data    : _.pick( this.model.attributes, ['box', 'search_terms', 'page'] ),
1182                  success : this.threadsFiltered,
1183                  error   : this.threadsFilterError
1184              } );
1185          },
1186  
1187          threadsFiltered: function() {
1188              bp.Nouveau.Messages.removeFeedback();
1189          },
1190  
1191          threadsFilterError: function( collection, response ) {
1192              bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1193          },
1194  
1195          resetSearchTerms: function( event ) {
1196              event.preventDefault();
1197  
1198              if ( ! $( event.target ).val() ) {
1199                  $( event.target ).closest( 'form' ).submit();
1200              } else {
1201                  $( event.target ).closest( 'form' ).find( '[type=submit]' ).addClass('bp-show').removeClass('bp-hide');
1202              }
1203          },
1204  
1205          setSearchTerms: function( event ) {
1206              event.preventDefault();
1207  
1208              this.model.set( {
1209                  'search_terms': $( event.target ).find( 'input[type=search]' ).val() || '',
1210                  page: 1
1211              } );
1212          },
1213  
1214          nextPage: function( event ) {
1215              event.preventDefault();
1216  
1217              this.model.set( 'page', this.model.get( 'page' ) + 1 );
1218          },
1219  
1220          prevPage: function( event ) {
1221              event.preventDefault();
1222  
1223              this.model.set( 'page', this.model.get( 'page' ) - 1 );
1224          }
1225      } );
1226  
1227      bp.Views.userMessagesHeader = bp.Nouveau.Messages.View.extend( {
1228          tagName  : 'div',
1229          template : bp.template( 'bp-messages-single-header' ),
1230  
1231          events: {
1232              'click .actions a' : 'doAction',
1233              'click .actions button' : 'doAction'
1234          },
1235  
1236          doAction: function( event ) {
1237              var action = $( event.currentTarget ).data( 'bp-action' ), self = this, options = {},
1238                  feedback = BP_Nouveau.messages.doingAction;
1239  
1240              if ( ! action ) {
1241                  return event;
1242              }
1243  
1244              event.preventDefault();
1245  
1246              if ( ! this.model.get( 'id' ) ) {
1247                  return;
1248              }
1249  
1250              if ( 'star' === action || 'unstar' === action ) {
1251                  var opposite = {
1252                      'star'  : 'unstar',
1253                      'unstar' : 'star'
1254                  };
1255  
1256                  options.data = {
1257                      'star_nonce' : this.model.get( 'star_nonce' )
1258                  };
1259  
1260                  $( event.currentTarget ).addClass( 'bp-hide' );
1261                  $( event.currentTarget ).parent().find( '[data-bp-action="' + opposite[ action ] + '"]' ).removeClass( 'bp-hide' );
1262  
1263              }
1264  
1265              if ( ! _.isUndefined( feedback[ action ] ) ) {
1266                  bp.Nouveau.Messages.displayFeedback( feedback[ action ], 'loading' );
1267              }
1268  
1269              bp.Nouveau.Messages.threads.doAction( action, this.model.get( 'id' ), options ).done( function( response ) {
1270                  // Remove all views
1271                  if ( 'delete' === action || 'exit' === action ) {
1272                      bp.Nouveau.Messages.clearViews();
1273                  } else if ( response.messages ) {
1274                      self.model.set( _.first( response.messages ) );
1275                  }
1276  
1277                  // Remove previous feedback.
1278                  bp.Nouveau.Messages.removeFeedback();
1279  
1280                  // Display the feedback.
1281                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1282              } ).fail( function( response ) {
1283                  // Remove previous feedback.
1284                  bp.Nouveau.Messages.removeFeedback();
1285  
1286                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1287              } );
1288          }
1289      } );
1290  
1291      bp.Views.userMessagesEntry = bp.Views.userMessagesHeader.extend( {
1292          tagName  : 'li',
1293          template : bp.template( 'bp-messages-single-list' ),
1294  
1295          events: {
1296              'click [data-bp-action]' : 'doAction'
1297          },
1298  
1299          initialize: function() {
1300              this.model.on( 'change:is_starred', this.updateMessage, this );
1301          },
1302  
1303          updateMessage: function( model ) {
1304              if ( this.model.get( 'id' ) !== model.get( 'id' ) ) {
1305                  return;
1306              }
1307  
1308              this.render();
1309          }
1310      } );
1311  
1312      bp.Views.userMessages = bp.Nouveau.Messages.View.extend( {
1313          tagName  : 'div',
1314          template : bp.template( 'bp-messages-single' ),
1315  
1316          initialize: function() {
1317              // Load Messages.
1318              this.requestMessages();
1319  
1320              // Init a reply.
1321              this.reply = new bp.Models.messageThread();
1322  
1323              this.collection.on( 'add', this.addMessage, this );
1324  
1325              // Add the editor view.
1326              this.views.add( '#bp-message-content', new bp.Views.messageEditor() );
1327          },
1328  
1329          events: {
1330              'click #send_reply_button' : 'sendReply'
1331          },
1332  
1333          requestMessages: function() {
1334              var data = {};
1335  
1336              this.collection.reset();
1337  
1338              bp.Nouveau.Messages.displayFeedback( BP_Nouveau.messages.loading, 'loading' );
1339  
1340              if ( _.isUndefined( this.options.thread.attributes ) ) {
1341                  data.id = this.options.thread.id;
1342  
1343              } else {
1344                  data.id        = this.options.thread.get( 'id' );
1345                  data.js_thread = ! _.isEmpty( this.options.thread.get( 'subject' ) );
1346              }
1347  
1348              this.collection.fetch( {
1349                  data: data,
1350                  success : _.bind( this.messagesFetched, this ),
1351                  error   : this.messagesFetchError
1352              } );
1353          },
1354  
1355          messagesFetched: function( collection, response ) {
1356              if ( ! _.isUndefined( response.thread ) ) {
1357                  this.options.thread = new Backbone.Model( response.thread );
1358              }
1359  
1360              bp.Nouveau.Messages.removeFeedback();
1361  
1362              this.views.add( '#bp-message-thread-header', new bp.Views.userMessagesHeader( { model: this.options.thread } ) );
1363          },
1364  
1365          messagesFetchError: function( collection, response ) {
1366              if ( response.feedback && response.type ) {
1367                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1368              }
1369          },
1370  
1371          addMessage: function( message ) {
1372              this.views.add( '#bp-message-thread-list', new bp.Views.userMessagesEntry( { model: message } ) );
1373          },
1374  
1375          addEditor: function() {
1376              // Load the Editor
1377              this.views.add( '#bp-message-content', new bp.Views.messageEditor() );
1378          },
1379  
1380          sendReply: function( event ) {
1381              event.preventDefault();
1382  
1383              if ( true === this.reply.get( 'sending' ) ) {
1384                  return;
1385              }
1386  
1387              this.reply.set ( {
1388                  thread_id : this.options.thread.get( 'id' ),
1389                  content   : tinyMCE.activeEditor.getContent(),
1390                  sending   : true
1391              } );
1392  
1393              this.collection.sync( 'create', _.pick( this.reply.attributes, ['thread_id', 'content' ] ), {
1394                  success : _.bind( this.replySent, this ),
1395                  error   : _.bind( this.replyError, this )
1396              } );
1397          },
1398  
1399          replySent: function( response ) {
1400              var reply = this.collection.parse( response );
1401  
1402              // Reset the form.
1403              tinyMCE.activeEditor.setContent( '' );
1404              this.reply.set( 'sending', false );
1405  
1406              this.collection.add( _.first( reply ) );
1407          },
1408  
1409          replyError: function( response ) {
1410              if ( response.feedback && response.type ) {
1411                  bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
1412              }
1413          }
1414      } );
1415  
1416      bp.Nouveau.Messages.Router = Backbone.Router.extend( {
1417          routes: {
1418              'view/:id/'   : 'viewMessage',
1419              ''            : 'inboxView',
1420              '*unSupported': 'unSupported'
1421          },
1422  
1423          initialize: function() {
1424              var self = this;
1425  
1426              _.each( BP_Nouveau.messages.supportedRoutes, function( route, slug ) {
1427                  self.route( route + '/', slug + 'Route', function() {
1428                      if ( 'compose' === slug ) {
1429                          self.composeMessage();
1430                      } else if ( 'sentbox' === slug ) {
1431                          self.sentboxView();
1432                      } else if ( 'starred' === slug ) {
1433                          self.starredView();
1434                      } else if ( 'inbox' === slug ) {
1435                          self.inboxView();
1436                      }
1437                  } );
1438              } );
1439          },
1440  
1441          composeMessage: function() {
1442              bp.Nouveau.Messages.composeView();
1443          },
1444  
1445          viewMessage: function( thread_id ) {
1446              if ( ! thread_id ) {
1447                  return;
1448              }
1449  
1450              // Try to get the corresponding thread.
1451              var thread = bp.Nouveau.Messages.threads.get( thread_id );
1452  
1453              if ( undefined === thread ) {
1454                  thread    = {};
1455                  thread.id = thread_id;
1456              }
1457  
1458              bp.Nouveau.Messages.singleView( thread );
1459          },
1460  
1461          sentboxView: function() {
1462              bp.Nouveau.Messages.box = 'sentbox';
1463              bp.Nouveau.Messages.threadsView();
1464          },
1465  
1466          starredView: function() {
1467              bp.Nouveau.Messages.box = 'starred';
1468              bp.Nouveau.Messages.threadsView();
1469          },
1470  
1471          unSupported: function() {
1472              bp.Nouveau.Messages.box = 'unsupported';
1473          },
1474  
1475          inboxView: function() {
1476              bp.Nouveau.Messages.box = 'inbox';
1477              bp.Nouveau.Messages.threadsView();
1478          }
1479      } );
1480  
1481      // Launch BP Nouveau Groups.
1482      bp.Nouveau.Messages.start();
1483  
1484  } )( window.bp, jQuery );


Generated: Sat Dec 7 01:00:57 2024 Cross-referenced by PHPXref 0.7.1