[ Index ]

PHP Cross Reference of WordPress

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


Generated: Thu Jul 9 01:00:03 2020 Cross-referenced by PHPXref 0.7.1