[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

title

Body

[close]

/wp-admin/js/ -> tags-box.js (source)

   1  /**
   2   * @output wp-admin/js/tags-box.js
   3   */
   4  
   5  /* jshint curly: false, eqeqeq: false */
   6  /* global ajaxurl, tagBox, array_unique_noempty */
   7  
   8  ( function( $ ) {
   9      var tagDelimiter = ( window.tagsSuggestL10n && window.tagsSuggestL10n.tagDelimiter ) || ',';
  10  
  11      /**
  12       * Filters unique items and returns a new array.
  13       *
  14       * Filters all items from an array into a new array containing only the unique
  15       * items. This also excludes whitespace or empty values.
  16       *
  17       * @since 2.8.0
  18       *
  19       * @global
  20       *
  21       * @param {Array} array The array to filter through.
  22       *
  23       * @return {Array} A new array containing only the unique items.
  24       */
  25      window.array_unique_noempty = function( array ) {
  26          var out = [];
  27  
  28          // Trim the values and ensure they are unique.
  29          $.each( array, function( key, val ) {
  30              val = $.trim( val );
  31  
  32              if ( val && $.inArray( val, out ) === -1 ) {
  33                  out.push( val );
  34              }
  35          } );
  36  
  37          return out;
  38      };
  39  
  40      /**
  41       * The TagBox object.
  42       *
  43       * Contains functions to create and manage tags that can be associated with a
  44       * post.
  45       *
  46       * @since 2.9.0
  47       *
  48       * @global
  49       */
  50      window.tagBox = {
  51          /**
  52           * Cleans up tags by removing redundant characters.
  53           *
  54           * @since 2.9.0
  55           * @memberOf tagBox
  56           *
  57           * @param {string} tags Comma separated tags that need to be cleaned up.
  58           *
  59           * @return {string} The cleaned up tags.
  60           */
  61          clean : function( tags ) {
  62              if ( ',' !== tagDelimiter ) {
  63                  tags = tags.replace( new RegExp( tagDelimiter, 'g' ), ',' );
  64              }
  65  
  66              tags = tags.replace(/\s*,\s*/g, ',').replace(/,+/g, ',').replace(/[,\s]+$/, '').replace(/^[,\s]+/, '');
  67  
  68              if ( ',' !== tagDelimiter ) {
  69                  tags = tags.replace( /,/g, tagDelimiter );
  70              }
  71  
  72              return tags;
  73          },
  74  
  75          /**
  76           * Parses tags and makes them editable.
  77           *
  78           * @since 2.9.0
  79           * @memberOf tagBox
  80           *
  81           * @param {Object} el The tag element to retrieve the ID from.
  82           *
  83           * @return {boolean} Always returns false.
  84           */
  85          parseTags : function(el) {
  86              var id = el.id,
  87                  num = id.split('-check-num-')[1],
  88                  taxbox = $(el).closest('.tagsdiv'),
  89                  thetags = taxbox.find('.the-tags'),
  90                  current_tags = thetags.val().split( tagDelimiter ),
  91                  new_tags = [];
  92  
  93              delete current_tags[num];
  94  
  95              // Sanitize the current tags and push them as if they're new tags.
  96              $.each( current_tags, function( key, val ) {
  97                  val = $.trim( val );
  98                  if ( val ) {
  99                      new_tags.push( val );
 100                  }
 101              });
 102  
 103              thetags.val( this.clean( new_tags.join( tagDelimiter ) ) );
 104  
 105              this.quickClicks( taxbox );
 106              return false;
 107          },
 108  
 109          /**
 110           * Creates clickable links, buttons and fields for adding or editing tags.
 111           *
 112           * @since 2.9.0
 113           * @memberOf tagBox
 114           *
 115           * @param {Object} el The container HTML element.
 116           *
 117           * @return {void}
 118           */
 119          quickClicks : function( el ) {
 120              var thetags = $('.the-tags', el),
 121                  tagchecklist = $('.tagchecklist', el),
 122                  id = $(el).attr('id'),
 123                  current_tags, disabled;
 124  
 125              if ( ! thetags.length )
 126                  return;
 127  
 128              disabled = thetags.prop('disabled');
 129  
 130              current_tags = thetags.val().split( tagDelimiter );
 131              tagchecklist.empty();
 132  
 133              /**
 134               * Creates a delete button if tag editing is enabled, before adding it to the tag list.
 135               *
 136               * @since 2.5.0
 137               * @memberOf tagBox
 138               *
 139               * @param {string} key The index of the current tag.
 140               * @param {string} val The value of the current tag.
 141               *
 142               * @return {void}
 143               */
 144              $.each( current_tags, function( key, val ) {
 145                  var listItem, xbutton;
 146  
 147                  val = $.trim( val );
 148  
 149                  if ( ! val )
 150                      return;
 151  
 152                  // Create a new list item, and ensure the text is properly escaped.
 153                  listItem = $( '<li />' ).text( val );
 154  
 155                  // If tags editing isn't disabled, create the X button.
 156                  if ( ! disabled ) {
 157                      /*
 158                       * Build the X buttons, hide the X icon with aria-hidden and
 159                       * use visually hidden text for screen readers.
 160                       */
 161                      xbutton = $( '<button type="button" id="' + id + '-check-num-' + key + '" class="ntdelbutton">' +
 162                          '<span class="remove-tag-icon" aria-hidden="true"></span>' +
 163                          '<span class="screen-reader-text">' + window.tagsSuggestL10n.removeTerm + ' ' + listItem.html() + '</span>' +
 164                          '</button>' );
 165  
 166                      /**
 167                       * Handles the click and keypress event of the tag remove button.
 168                       *
 169                       * Makes sure the focus ends up in the tag input field when using
 170                       * the keyboard to delete the tag.
 171                       *
 172                       * @since 4.2.0
 173                       *
 174                       * @param {Event} e The click or keypress event to handle.
 175                       *
 176                       * @return {void}
 177                       */
 178                      xbutton.on( 'click keypress', function( e ) {
 179                          // On click or when using the Enter/Spacebar keys.
 180                          if ( 'click' === e.type || 13 === e.keyCode || 32 === e.keyCode ) {
 181                              /*
 182                               * When using the keyboard, move focus back to the
 183                               * add new tag field. Note: when releasing the pressed
 184                               * key this will fire the `keyup` event on the input.
 185                               */
 186                              if ( 13 === e.keyCode || 32 === e.keyCode ) {
 187                                   $( this ).closest( '.tagsdiv' ).find( 'input.newtag' ).focus();
 188                               }
 189  
 190                              tagBox.userAction = 'remove';
 191                              tagBox.parseTags( this );
 192                          }
 193                      });
 194  
 195                      listItem.prepend( '&nbsp;' ).prepend( xbutton );
 196                  }
 197  
 198                  // Append the list item to the tag list.
 199                  tagchecklist.append( listItem );
 200              });
 201  
 202              // The buttons list is built now, give feedback to screen reader users.
 203              tagBox.screenReadersMessage();
 204          },
 205  
 206          /**
 207           * Adds a new tag.
 208           *
 209           * Also ensures that the quick links are properly generated.
 210           *
 211           * @since 2.9.0
 212           * @memberOf tagBox
 213           *
 214           * @param {Object} el The container HTML element.
 215           * @param {Object|boolean} a When this is an HTML element the text of that
 216           *                           element will be used for the new tag.
 217           * @param {number|boolean} f If this value is not passed then the tag input
 218           *                           field is focused.
 219           *
 220           * @return {boolean} Always returns false.
 221           */
 222          flushTags : function( el, a, f ) {
 223              var tagsval, newtags, text,
 224                  tags = $( '.the-tags', el ),
 225                  newtag = $( 'input.newtag', el );
 226  
 227              a = a || false;
 228  
 229              text = a ? $(a).text() : newtag.val();
 230  
 231              /*
 232               * Return if there's no new tag or if the input field is empty.
 233               * Note: when using the keyboard to add tags, focus is moved back to
 234               * the input field and the `keyup` event attached on this field will
 235               * fire when releasing the pressed key. Checking also for the field
 236               * emptiness avoids to set the tags and call quickClicks() again.
 237               */
 238              if ( 'undefined' == typeof( text ) || '' === text ) {
 239                  return false;
 240              }
 241  
 242              tagsval = tags.val();
 243              newtags = tagsval ? tagsval + tagDelimiter + text : text;
 244  
 245              newtags = this.clean( newtags );
 246              newtags = array_unique_noempty( newtags.split( tagDelimiter ) ).join( tagDelimiter );
 247              tags.val( newtags );
 248              this.quickClicks( el );
 249  
 250              if ( ! a )
 251                  newtag.val('');
 252              if ( 'undefined' == typeof( f ) )
 253                  newtag.focus();
 254  
 255              return false;
 256          },
 257  
 258          /**
 259           * Retrieves the available tags and creates a tagcloud.
 260           *
 261           * Retrieves the available tags from the database and creates an interactive
 262           * tagcloud. Clicking a tag will add it.
 263           *
 264           * @since 2.9.0
 265           * @memberOf tagBox
 266           *
 267           * @param {string} id The ID to extract the taxonomy from.
 268           *
 269           * @return {void}
 270           */
 271          get : function( id ) {
 272              var tax = id.substr( id.indexOf('-') + 1 );
 273  
 274              /**
 275               * Puts a received tag cloud into a DOM element.
 276               *
 277               * The tag cloud HTML is generated on the server.
 278               *
 279               * @since 2.9.0
 280               *
 281               * @param {number|string} r The response message from the AJAX call.
 282               * @param {string} stat The status of the AJAX request.
 283               *
 284               * @return {void}
 285               */
 286              $.post( ajaxurl, { 'action': 'get-tagcloud', 'tax': tax }, function( r, stat ) {
 287                  if ( 0 === r || 'success' != stat ) {
 288                      return;
 289                  }
 290  
 291                  r = $( '<div id="tagcloud-' + tax + '" class="the-tagcloud">' + r + '</div>' );
 292  
 293                  /**
 294                   * Adds a new tag when a tag in the tagcloud is clicked.
 295                   *
 296                   * @since 2.9.0
 297                   *
 298                   * @return {boolean} Returns false to prevent the default action.
 299                   */
 300                  $( 'a', r ).click( function() {
 301                      tagBox.userAction = 'add';
 302                      tagBox.flushTags( $( '#' + tax ), this );
 303                      return false;
 304                  });
 305  
 306                  $( '#' + id ).after( r );
 307              });
 308          },
 309  
 310          /**
 311           * Track the user's last action.
 312           *
 313           * @since 4.7.0
 314           */
 315          userAction: '',
 316  
 317          /**
 318           * Dispatches an audible message to screen readers.
 319           *
 320           * This will inform the user when a tag has been added or removed.
 321           *
 322           * @since 4.7.0
 323           *
 324           * @return {void}
 325           */
 326          screenReadersMessage: function() {
 327              var message;
 328  
 329              switch ( this.userAction ) {
 330                  case 'remove':
 331                      message = window.tagsSuggestL10n.termRemoved;
 332                      break;
 333  
 334                  case 'add':
 335                      message = window.tagsSuggestL10n.termAdded;
 336                      break;
 337  
 338                  default:
 339                      return;
 340              }
 341  
 342              window.wp.a11y.speak( message, 'assertive' );
 343          },
 344  
 345          /**
 346           * Initializes the tags box by setting up the links, buttons. Sets up event
 347           * handling.
 348           *
 349           * This includes handling of pressing the enter key in the input field and the
 350           * retrieval of tag suggestions.
 351           *
 352           * @since 2.9.0
 353           * @memberOf tagBox
 354           *
 355           * @return {void}
 356           */
 357          init : function() {
 358              var ajaxtag = $('div.ajaxtag');
 359  
 360              $('.tagsdiv').each( function() {
 361                  tagBox.quickClicks( this );
 362              });
 363  
 364              $( '.tagadd', ajaxtag ).click( function() {
 365                  tagBox.userAction = 'add';
 366                  tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
 367              });
 368  
 369              /**
 370               * Handles pressing enter on the new tag input field.
 371               *
 372               * Prevents submitting the post edit form. Uses `keypress` to take
 373               * into account Input Method Editor (IME) converters.
 374               *
 375               * @since 2.9.0
 376               *
 377               * @param {Event} event The keypress event that occurred.
 378               *
 379               * @return {void}
 380               */
 381              $( 'input.newtag', ajaxtag ).keypress( function( event ) {
 382                  if ( 13 == event.which ) {
 383                      tagBox.userAction = 'add';
 384                      tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
 385                      event.preventDefault();
 386                      event.stopPropagation();
 387                  }
 388              }).each( function( i, element ) {
 389                  $( element ).wpTagsSuggest();
 390              });
 391  
 392              /**
 393               * Before a post is saved the value currently in the new tag input field will be
 394               * added as a tag.
 395               *
 396               * @since 2.9.0
 397               *
 398               * @return {void}
 399               */
 400              $('#post').submit(function(){
 401                  $('div.tagsdiv').each( function() {
 402                      tagBox.flushTags(this, false, 1);
 403                  });
 404              });
 405  
 406              /**
 407               * Handles clicking on the tag cloud link.
 408               *
 409               * Makes sure the ARIA attributes are set correctly.
 410               *
 411               * @since 2.9.0
 412               *
 413               * @return {void}
 414               */
 415              $('.tagcloud-link').click(function(){
 416                  // On the first click, fetch the tag cloud and insert it in the DOM.
 417                  tagBox.get( $( this ).attr( 'id' ) );
 418                  // Update button state, remove previous click event and attach a new one to toggle the cloud.
 419                  $( this )
 420                      .attr( 'aria-expanded', 'true' )
 421                      .unbind()
 422                      .click( function() {
 423                          $( this )
 424                              .attr( 'aria-expanded', 'false' === $( this ).attr( 'aria-expanded' ) ? 'true' : 'false' )
 425                              .siblings( '.the-tagcloud' ).toggle();
 426                      });
 427              });
 428          }
 429      };
 430  }( jQuery ));


Generated: Sat Nov 23 20:47:33 2019 Cross-referenced by PHPXref 0.7