[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-activity/js/ -> mentions.js (source)

   1  /* global bp */
   2  
   3  window.bp = window.bp || {};
   4  
   5  ( function( bp, $, undefined ) {
   6      var mentionsQueryCache = [],
   7          mentionsItem;
   8  
   9      bp.mentions       = bp.mentions || {};
  10      bp.mentions.users = window.bp.mentions.users || [];
  11  
  12      if ( typeof window.BP_Suggestions === 'object' ) {
  13          bp.mentions.users = window.BP_Suggestions.friends || bp.mentions.users;
  14      }
  15  
  16      /**
  17       * Adds BuddyPress @mentions to form inputs.
  18       *
  19       * @param {array|object} options If array, becomes the suggestions' data source. If object, passed as config to $.atwho().
  20       * @since 2.1.0
  21       */
  22      $.fn.bp_mentions = function( options ) {
  23          if ( $.isArray( options ) ) {
  24              options = { data: options };
  25          }
  26  
  27          /**
  28           * Default options for at.js; see https://github.com/ichord/At.js/.
  29           */
  30          var suggestionsDefaults = {
  31              delay:             200,
  32              hideWithoutSuffix: true,
  33              insertTpl:         '@$ID}',
  34              limit:             10,
  35              startWithSpace:    false,
  36              suffix:            '',
  37  
  38              callbacks: {
  39                  /**
  40                   * Custom filter to only match the start of spaced words.
  41                   * Based on the core/default one.
  42                   *
  43                   * @param {string} query
  44                   * @param {array} data
  45                   * @param {string} search_key
  46                   * @return {array}
  47                   * @since 2.1.0
  48                   */
  49                  filter: function( query, data, search_key ) {
  50                      var item, _i, _len, _results = [],
  51                      regxp = new RegExp( '^' + query + '| ' + query, 'ig' ); // start of string, or preceded by a space.
  52  
  53                      for ( _i = 0, _len = data.length; _i < _len; _i++ ) {
  54                          item = data[ _i ];
  55                          if ( item[ search_key ].toLowerCase().match( regxp ) ) {
  56                              _results.push( item );
  57                          }
  58                      }
  59  
  60                      return _results;
  61                  },
  62  
  63                  /**
  64                   * Removes some spaces around highlighted string and tweaks regex to allow spaces
  65                   * (to match display_name). Based on the core default.
  66                   *
  67                   * @param {unknown} li
  68                   * @param {string} query
  69                   * @return {string}
  70                   * @since 2.1.0
  71                   */
  72                  highlighter: function( li, query ) {
  73                      if ( ! query ) {
  74                          return li;
  75                      }
  76  
  77                      var regexp = new RegExp( '>(\\s*|[\\w\\s]*)(' + this.at.replace( '+', '\\+') + '?' + query.replace( '+', '\\+' ) + ')([\\w ]*)\\s*<', 'ig' );
  78                      return li.replace( regexp, function( str, $1, $2, $3 ) {
  79                          return '>' + $1 + '<strong>' + $2 + '</strong>' + $3 + '<';
  80                      });
  81                  },
  82  
  83                  /**
  84                   * Reposition the suggestion list dynamically.
  85                   *
  86                   * @param {unknown} offset
  87                   * @since 2.1.0
  88                   */
  89                  before_reposition: function( offset ) {
  90                      // get the iframe, if any, already applied with atwho
  91                      var caret,
  92                              line,
  93                              iframeOffset,
  94                              move,
  95                              $view = $( '#atwho-ground-' + this.id + ' .atwho-view' ),
  96                              $body = $( 'body' ),
  97                              atwhoDataValue = this.$inputor.data( 'atwho' );
  98  
  99                      if ( 'undefined' !== atwhoDataValue && 'undefined' !== atwhoDataValue.iframe && null !== atwhoDataValue.iframe ) {
 100                          caret = this.$inputor.caret( 'offset', { iframe: atwhoDataValue.iframe } );
 101                          // Caret.js no longer calculates iframe caret position from the window (it's now just within the iframe).
 102                          // We need to get the iframe offset from the window and merge that into our object.
 103                          iframeOffset = $( atwhoDataValue.iframe ).offset();
 104                          if ( 'undefined' !== iframeOffset ) {
 105                              caret.left += iframeOffset.left;
 106                              caret.top  += iframeOffset.top;
 107                          }
 108                      } else {
 109                          caret = this.$inputor.caret( 'offset' );
 110                      }
 111  
 112                      // If the caret is past horizontal half, then flip it, yo
 113                      if ( caret.left > ( $body.width() / 2 ) ) {
 114                          $view.addClass( 'right' );
 115                          move = caret.left - offset.left - this.view.$el.width();
 116                      } else {
 117                          $view.removeClass( 'right' );
 118                          move = caret.left - offset.left + 1;
 119                      }
 120  
 121                      // If we're on a small screen, scroll to caret
 122                      if ( $body.width() <= 400 ) {
 123                          $( document ).scrollTop( caret.top - 6 );
 124                      }
 125  
 126                      // New position is under the caret (never above) and positioned to follow
 127                      // Dynamic sizing based on the input area (remove 'px' from end)
 128                      line = parseInt( this.$inputor.css( 'line-height' ).substr( 0, this.$inputor.css( 'line-height' ).length - 2 ), 10 );
 129                      if ( !line || line < 5 ) { // sanity check, and catch no line-height
 130                          line = 19;
 131                      }
 132  
 133                      offset.top   = caret.top + line;
 134                      offset.left += move;
 135                  },
 136  
 137                  /**
 138                   * Override default behaviour which inserts junk tags in the WordPress Visual editor.
 139                   *
 140                   * @param {unknown} $inputor Element which we're inserting content into.
 141                   * @param {string) content The content that will be inserted.
 142                   * @param {string) suffix Applied to the end of the content string.
 143                   * @return {string}
 144                   * @since 2.1.0
 145                   */
 146                  inserting_wrapper: function( $inputor, content, suffix ) {
 147                      return '' + content + suffix;
 148                  }
 149              }
 150          },
 151  
 152          /**
 153           * Default options for our @mentions; see https://github.com/ichord/At.js/.
 154           */
 155          mentionsDefaults = {
 156              callbacks: {
 157                  /**
 158                   * If there are no matches for the query in this.data, then query BuddyPress.
 159                   *
 160                   * @param {string} query Partial @mention to search for.
 161                   * @param {function} render_view Render page callback function.
 162                   * @since 2.1.0
 163                   * @since 3.0.0. Renamed from "remote_filter" for at.js v1.5.4 support.
 164                   */
 165                  remoteFilter: function( query, render_view ) {
 166                      var self = $( this ),
 167                          params = {};
 168  
 169                      mentionsItem = mentionsQueryCache[ query ];
 170                      if ( typeof mentionsItem === 'object' ) {
 171                          render_view( mentionsItem );
 172                          return;
 173                      }
 174  
 175                      if ( self.xhr ) {
 176                          self.xhr.abort();
 177                      }
 178  
 179                      params = { 'action': 'bp_get_suggestions', 'term': query, 'type': 'members' };
 180  
 181                      if ( $.isNumeric( this.$inputor.data( 'suggestions-group-id' ) ) ) {
 182                          params['group-id'] = parseInt( this.$inputor.data( 'suggestions-group-id' ), 10 );
 183                      }
 184  
 185                      self.xhr = $.getJSON( ajaxurl, params )
 186                          /**
 187                           * Success callback for the @suggestions lookup.
 188                           *
 189                           * @param {object} response Details of users matching the query.
 190                           * @since 2.1.0
 191                           */
 192                          .done(function( response ) {
 193                              if ( ! response.success ) {
 194                                  return;
 195                              }
 196  
 197                              var data = $.map( response.data,
 198                                  /**
 199                                   * Create a composite index to determine ordering of results;
 200                                   * nicename matches will appear on top.
 201                                   *
 202                                   * @param {array} suggestion A suggestion's original data.
 203                                   * @return {array} A suggestion's new data.
 204                                   * @since 2.1.0
 205                                   */
 206                                  function( suggestion ) {
 207                                      suggestion.search = suggestion.search || suggestion.ID + ' ' + suggestion.name;
 208                                      return suggestion;
 209                                  }
 210                              );
 211  
 212                              mentionsQueryCache[ query ] = data;
 213                              render_view( data );
 214                          });
 215                  }
 216              },
 217  
 218              data: $.map( options.data,
 219                  /**
 220                   * Create a composite index to search against of nicename + display name.
 221                   * This will also determine ordering of results, so nicename matches will appear on top.
 222                   *
 223                   * @param {array} suggestion A suggestion's original data.
 224                   * @return {array} A suggestion's new data.
 225                   * @since 2.1.0
 226                   */
 227                  function( suggestion ) {
 228                      suggestion.search = suggestion.search || suggestion.ID + ' ' + suggestion.name;
 229                      return suggestion;
 230                  }
 231              ),
 232  
 233              at:         '@',
 234              searchKey:  'search',
 235              displayTpl: '<li data-value="@$ID}"><img src="$image}" /><span class="username">@$ID}</span><small>$name}</small></li>'
 236          },
 237  
 238          opts = $.extend( true, {}, suggestionsDefaults, mentionsDefaults, options );
 239          return $.fn.atwho.call( this, opts );
 240      };
 241  
 242      $( document ).ready(function() {
 243          // Activity/reply, post comments, dashboard post 'text' editor.
 244          $( '.bp-suggestions, #comments form textarea, .wp-editor-area' ).bp_mentions( bp.mentions.users );
 245      });
 246  
 247      bp.mentions.tinyMCEinit = function() {
 248          if ( typeof window.tinyMCE === 'undefined' || window.tinyMCE.activeEditor === null || typeof window.tinyMCE.activeEditor === 'undefined' ) {
 249              return;
 250          } else {
 251              $( window.tinyMCE.activeEditor.contentDocument.activeElement )
 252                  .atwho( 'setIframe', $( '.wp-editor-wrap iframe' )[0] )
 253                  .bp_mentions( bp.mentions.users );
 254          }
 255      };
 256  })( bp, jQuery );


Generated: Wed Jul 24 01:01:43 2019 Cross-referenced by PHPXref 0.7.1