[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-admin/js/ -> post.js (source)

   1  /**
   2   * @file Contains all dynamic functionality needed on post and term pages.
   3   *
   4   * @output wp-admin/js/post.js
   5   */
   6  
   7   /* global ajaxurl, wpAjax, postboxes, pagenow, tinymce, alert, deleteUserSetting, ClipboardJS */
   8   /* global theList:true, theExtraList:true, getUserSetting, setUserSetting, commentReply, commentsBox */
   9   /* global WPSetThumbnailHTML, wptitlehint */
  10  
  11  // Backward compatibility: prevent fatal errors.
  12  window.makeSlugeditClickable = window.editPermalink = function(){};
  13  
  14  // Make sure the wp object exists.
  15  window.wp = window.wp || {};
  16  
  17  ( function( $ ) {
  18      var titleHasFocus = false,
  19          __ = wp.i18n.__;
  20  
  21      /**
  22       * Control loading of comments on the post and term edit pages.
  23       *
  24       * @type {{st: number, get: commentsBox.get, load: commentsBox.load}}
  25       *
  26       * @namespace commentsBox
  27       */
  28      window.commentsBox = {
  29          // Comment offset to use when fetching new comments.
  30          st : 0,
  31  
  32          /**
  33           * Fetch comments using Ajax and display them in the box.
  34           *
  35           * @memberof commentsBox
  36           *
  37           * @param {number} total Total number of comments for this post.
  38           * @param {number} num   Optional. Number of comments to fetch, defaults to 20.
  39           * @return {boolean} Always returns false.
  40           */
  41          get : function(total, num) {
  42              var st = this.st, data;
  43              if ( ! num )
  44                  num = 20;
  45  
  46              this.st += num;
  47              this.total = total;
  48              $( '#commentsdiv .spinner' ).addClass( 'is-active' );
  49  
  50              data = {
  51                  'action' : 'get-comments',
  52                  'mode' : 'single',
  53                  '_ajax_nonce' : $('#add_comment_nonce').val(),
  54                  'p' : $('#post_ID').val(),
  55                  'start' : st,
  56                  'number' : num
  57              };
  58  
  59              $.post(
  60                  ajaxurl,
  61                  data,
  62                  function(r) {
  63                      r = wpAjax.parseAjaxResponse(r);
  64                      $('#commentsdiv .widefat').show();
  65                      $( '#commentsdiv .spinner' ).removeClass( 'is-active' );
  66  
  67                      if ( 'object' == typeof r && r.responses[0] ) {
  68                          $('#the-comment-list').append( r.responses[0].data );
  69  
  70                          theList = theExtraList = null;
  71                          $( 'a[className*=\':\']' ).off();
  72  
  73                          // If the offset is over the total number of comments we cannot fetch any more, so hide the button.
  74                          if ( commentsBox.st > commentsBox.total )
  75                              $('#show-comments').hide();
  76                          else
  77                              $('#show-comments').show().children('a').text( __( 'Show more comments' ) );
  78  
  79                          return;
  80                      } else if ( 1 == r ) {
  81                          $('#show-comments').text( __( 'No more comments found.' ) );
  82                          return;
  83                      }
  84  
  85                      $('#the-comment-list').append('<tr><td colspan="2">'+wpAjax.broken+'</td></tr>');
  86                  }
  87              );
  88  
  89              return false;
  90          },
  91  
  92          /**
  93           * Load the next batch of comments.
  94           *
  95           * @memberof commentsBox
  96           *
  97           * @param {number} total Total number of comments to load.
  98           */
  99          load: function(total){
 100              this.st = jQuery('#the-comment-list tr.comment:visible').length;
 101              this.get(total);
 102          }
 103      };
 104  
 105      /**
 106       * Overwrite the content of the Featured Image postbox
 107       *
 108       * @param {string} html New HTML to be displayed in the content area of the postbox.
 109       *
 110       * @global
 111       */
 112      window.WPSetThumbnailHTML = function(html){
 113          $('.inside', '#postimagediv').html(html);
 114      };
 115  
 116      /**
 117       * Set the Image ID of the Featured Image
 118       *
 119       * @param {number} id The post_id of the image to use as Featured Image.
 120       *
 121       * @global
 122       */
 123      window.WPSetThumbnailID = function(id){
 124          var field = $('input[value="_thumbnail_id"]', '#list-table');
 125          if ( field.length > 0 ) {
 126              $('#meta\\[' + field.attr('id').match(/[0-9]+/) + '\\]\\[value\\]').text(id);
 127          }
 128      };
 129  
 130      /**
 131       * Remove the Featured Image
 132       *
 133       * @param {string} nonce Nonce to use in the request.
 134       *
 135       * @global
 136       */
 137      window.WPRemoveThumbnail = function(nonce){
 138          $.post(
 139              ajaxurl, {
 140                  action: 'set-post-thumbnail',
 141                  post_id: $( '#post_ID' ).val(),
 142                  thumbnail_id: -1,
 143                  _ajax_nonce: nonce,
 144                  cookie: encodeURIComponent( document.cookie )
 145              },
 146              /**
 147               * Handle server response
 148               *
 149               * @param {string} str Response, will be '0' when an error occurred otherwise contains link to add Featured Image.
 150               */
 151              function(str){
 152                  if ( str == '0' ) {
 153                      alert( __( 'Could not set that as the thumbnail image. Try a different attachment.' ) );
 154                  } else {
 155                      WPSetThumbnailHTML(str);
 156                  }
 157              }
 158          );
 159      };
 160  
 161      /**
 162       * Heartbeat locks.
 163       *
 164       * Used to lock editing of an object by only one user at a time.
 165       *
 166       * When the user does not send a heartbeat in a heartbeat-time
 167       * the user is no longer editing and another user can start editing.
 168       */
 169      $(document).on( 'heartbeat-send.refresh-lock', function( e, data ) {
 170          var lock = $('#active_post_lock').val(),
 171              post_id = $('#post_ID').val(),
 172              send = {};
 173  
 174          if ( ! post_id || ! $('#post-lock-dialog').length )
 175              return;
 176  
 177          send.post_id = post_id;
 178  
 179          if ( lock )
 180              send.lock = lock;
 181  
 182          data['wp-refresh-post-lock'] = send;
 183  
 184      }).on( 'heartbeat-tick.refresh-lock', function( e, data ) {
 185          // Post locks: update the lock string or show the dialog if somebody has taken over editing.
 186          var received, wrap, avatar;
 187  
 188          if ( data['wp-refresh-post-lock'] ) {
 189              received = data['wp-refresh-post-lock'];
 190  
 191              if ( received.lock_error ) {
 192                  // Show "editing taken over" message.
 193                  wrap = $('#post-lock-dialog');
 194  
 195                  if ( wrap.length && ! wrap.is(':visible') ) {
 196                      if ( wp.autosave ) {
 197                          // Save the latest changes and disable.
 198                          $(document).one( 'heartbeat-tick', function() {
 199                              wp.autosave.server.suspend();
 200                              wrap.removeClass('saving').addClass('saved');
 201                              $(window).off( 'beforeunload.edit-post' );
 202                          });
 203  
 204                          wrap.addClass('saving');
 205                          wp.autosave.server.triggerSave();
 206                      }
 207  
 208                      if ( received.lock_error.avatar_src ) {
 209                          avatar = $( '<img />', {
 210                              'class': 'avatar avatar-64 photo',
 211                              width: 64,
 212                              height: 64,
 213                              alt: '',
 214                              src: received.lock_error.avatar_src,
 215                              srcset: received.lock_error.avatar_src_2x ?
 216                                  received.lock_error.avatar_src_2x + ' 2x' :
 217                                  undefined
 218                          } );
 219                          wrap.find('div.post-locked-avatar').empty().append( avatar );
 220                      }
 221  
 222                      wrap.show().find('.currently-editing').text( received.lock_error.text );
 223                      wrap.find('.wp-tab-first').trigger( 'focus' );
 224                  }
 225              } else if ( received.new_lock ) {
 226                  $('#active_post_lock').val( received.new_lock );
 227              }
 228          }
 229      }).on( 'before-autosave.update-post-slug', function() {
 230          titleHasFocus = document.activeElement && document.activeElement.id === 'title';
 231      }).on( 'after-autosave.update-post-slug', function() {
 232  
 233          /*
 234           * Create slug area only if not already there
 235           * and the title field was not focused (user was not typing a title) when autosave ran.
 236           */
 237          if ( ! $('#edit-slug-box > *').length && ! titleHasFocus ) {
 238              $.post( ajaxurl, {
 239                      action: 'sample-permalink',
 240                      post_id: $('#post_ID').val(),
 241                      new_title: $('#title').val(),
 242                      samplepermalinknonce: $('#samplepermalinknonce').val()
 243                  },
 244                  function( data ) {
 245                      if ( data != '-1' ) {
 246                          $('#edit-slug-box').html(data);
 247                      }
 248                  }
 249              );
 250          }
 251      });
 252  
 253  }(jQuery));
 254  
 255  /**
 256   * Heartbeat refresh nonces.
 257   */
 258  (function($) {
 259      var check, timeout;
 260  
 261      /**
 262       * Only allow to check for nonce refresh every 30 seconds.
 263       */
 264  	function schedule() {
 265          check = false;
 266          window.clearTimeout( timeout );
 267          timeout = window.setTimeout( function(){ check = true; }, 300000 );
 268      }
 269  
 270      $( function() {
 271          schedule();
 272      }).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) {
 273          var post_id,
 274              $authCheck = $('#wp-auth-check-wrap');
 275  
 276          if ( check || ( $authCheck.length && ! $authCheck.hasClass( 'hidden' ) ) ) {
 277              if ( ( post_id = $('#post_ID').val() ) && $('#_wpnonce').val() ) {
 278                  data['wp-refresh-post-nonces'] = {
 279                      post_id: post_id
 280                  };
 281              }
 282          }
 283      }).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) {
 284          var nonces = data['wp-refresh-post-nonces'];
 285  
 286          if ( nonces ) {
 287              schedule();
 288  
 289              if ( nonces.replace ) {
 290                  $.each( nonces.replace, function( selector, value ) {
 291                      $( '#' + selector ).val( value );
 292                  });
 293              }
 294  
 295              if ( nonces.heartbeatNonce )
 296                  window.heartbeatSettings.nonce = nonces.heartbeatNonce;
 297          }
 298      });
 299  }(jQuery));
 300  
 301  /**
 302   * All post and postbox controls and functionality.
 303   */
 304  jQuery( function($) {
 305      var stamp, visibility, $submitButtons, updateVisibility, updateText,
 306          $textarea = $('#content'),
 307          $document = $(document),
 308          postId = $('#post_ID').val() || 0,
 309          $submitpost = $('#submitpost'),
 310          releaseLock = true,
 311          $postVisibilitySelect = $('#post-visibility-select'),
 312          $timestampdiv = $('#timestampdiv'),
 313          $postStatusSelect = $('#post-status-select'),
 314          isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false,
 315          copyAttachmentURLClipboard = new ClipboardJS( '.copy-attachment-url.edit-media' ),
 316          copyAttachmentURLSuccessTimeout,
 317          __ = wp.i18n.__, _x = wp.i18n._x;
 318  
 319      postboxes.add_postbox_toggles(pagenow);
 320  
 321      /*
 322       * Clear the window name. Otherwise if this is a former preview window where the user navigated to edit another post,
 323       * and the first post is still being edited, clicking Preview there will use this window to show the preview.
 324       */
 325      window.name = '';
 326  
 327      // Post locks: contain focus inside the dialog. If the dialog is shown, focus the first item.
 328      $('#post-lock-dialog .notification-dialog').on( 'keydown', function(e) {
 329          // Don't do anything when [Tab] is pressed.
 330          if ( e.which != 9 )
 331              return;
 332  
 333          var target = $(e.target);
 334  
 335          // [Shift] + [Tab] on first tab cycles back to last tab.
 336          if ( target.hasClass('wp-tab-first') && e.shiftKey ) {
 337              $(this).find('.wp-tab-last').trigger( 'focus' );
 338              e.preventDefault();
 339          // [Tab] on last tab cycles back to first tab.
 340          } else if ( target.hasClass('wp-tab-last') && ! e.shiftKey ) {
 341              $(this).find('.wp-tab-first').trigger( 'focus' );
 342              e.preventDefault();
 343          }
 344      }).filter(':visible').find('.wp-tab-first').trigger( 'focus' );
 345  
 346      // Set the heartbeat interval to 10 seconds if post lock dialogs are enabled.
 347      if ( wp.heartbeat && $('#post-lock-dialog').length ) {
 348          wp.heartbeat.interval( 10 );
 349      }
 350  
 351      // The form is being submitted by the user.
 352      $submitButtons = $submitpost.find( ':submit, a.submitdelete, #post-preview' ).on( 'click.edit-post', function( event ) {
 353          var $button = $(this);
 354  
 355          if ( $button.hasClass('disabled') ) {
 356              event.preventDefault();
 357              return;
 358          }
 359  
 360          if ( $button.hasClass('submitdelete') || $button.is( '#post-preview' ) ) {
 361              return;
 362          }
 363  
 364          // The form submission can be blocked from JS or by using HTML 5.0 validation on some fields.
 365          // Run this only on an actual 'submit'.
 366          $('form#post').off( 'submit.edit-post' ).on( 'submit.edit-post', function( event ) {
 367              if ( event.isDefaultPrevented() ) {
 368                  return;
 369              }
 370  
 371              // Stop auto save.
 372              if ( wp.autosave ) {
 373                  wp.autosave.server.suspend();
 374              }
 375  
 376              if ( typeof commentReply !== 'undefined' ) {
 377                  /*
 378                   * Warn the user they have an unsaved comment before submitting
 379                   * the post data for update.
 380                   */
 381                  if ( ! commentReply.discardCommentChanges() ) {
 382                      return false;
 383                  }
 384  
 385                  /*
 386                   * Close the comment edit/reply form if open to stop the form
 387                   * action from interfering with the post's form action.
 388                   */
 389                  commentReply.close();
 390              }
 391  
 392              releaseLock = false;
 393              $(window).off( 'beforeunload.edit-post' );
 394  
 395              $submitButtons.addClass( 'disabled' );
 396  
 397              if ( $button.attr('id') === 'publish' ) {
 398                  $submitpost.find( '#major-publishing-actions .spinner' ).addClass( 'is-active' );
 399              } else {
 400                  $submitpost.find( '#minor-publishing .spinner' ).addClass( 'is-active' );
 401              }
 402          });
 403      });
 404  
 405      // Submit the form saving a draft or an autosave, and show a preview in a new tab.
 406      $('#post-preview').on( 'click.post-preview', function( event ) {
 407          var $this = $(this),
 408              $form = $('form#post'),
 409              $previewField = $('input#wp-preview'),
 410              target = $this.attr('target') || 'wp-preview',
 411              ua = navigator.userAgent.toLowerCase();
 412  
 413          event.preventDefault();
 414  
 415          if ( $this.hasClass('disabled') ) {
 416              return;
 417          }
 418  
 419          if ( wp.autosave ) {
 420              wp.autosave.server.tempBlockSave();
 421          }
 422  
 423          $previewField.val('dopreview');
 424          $form.attr( 'target', target ).trigger( 'submit' ).attr( 'target', '' );
 425  
 426          // Workaround for WebKit bug preventing a form submitting twice to the same action.
 427          // https://bugs.webkit.org/show_bug.cgi?id=28633
 428          if ( ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1 ) {
 429              $form.attr( 'action', function( index, value ) {
 430                  return value + '?t=' + ( new Date() ).getTime();
 431              });
 432          }
 433  
 434          $previewField.val('');
 435      });
 436  
 437      // Auto save new posts after a title is typed.
 438      if ( $( '#auto_draft' ).val() ) {
 439          $( '#title' ).on( 'blur', function() {
 440              var cancel;
 441  
 442              if ( ! this.value || $('#edit-slug-box > *').length ) {
 443                  return;
 444              }
 445  
 446              // Cancel the auto save when the blur was triggered by the user submitting the form.
 447              $('form#post').one( 'submit', function() {
 448                  cancel = true;
 449              });
 450  
 451              window.setTimeout( function() {
 452                  if ( ! cancel && wp.autosave ) {
 453                      wp.autosave.server.triggerSave();
 454                  }
 455              }, 200 );
 456          });
 457      }
 458  
 459      $document.on( 'autosave-disable-buttons.edit-post', function() {
 460          $submitButtons.addClass( 'disabled' );
 461      }).on( 'autosave-enable-buttons.edit-post', function() {
 462          if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) {
 463              $submitButtons.removeClass( 'disabled' );
 464          }
 465      }).on( 'before-autosave.edit-post', function() {
 466          $( '.autosave-message' ).text( __( 'Saving Draft…' ) );
 467      }).on( 'after-autosave.edit-post', function( event, data ) {
 468          $( '.autosave-message' ).text( data.message );
 469  
 470          if ( $( document.body ).hasClass( 'post-new-php' ) ) {
 471              $( '.submitbox .submitdelete' ).show();
 472          }
 473      });
 474  
 475      /*
 476       * When the user is trying to load another page, or reloads current page
 477       * show a confirmation dialog when there are unsaved changes.
 478       */
 479      $( window ).on( 'beforeunload.edit-post', function( event ) {
 480          var editor  = window.tinymce && window.tinymce.get( 'content' );
 481          var changed = false;
 482  
 483          if ( wp.autosave ) {
 484              changed = wp.autosave.server.postChanged();
 485          } else if ( editor ) {
 486              changed = ( ! editor.isHidden() && editor.isDirty() );
 487          }
 488  
 489          if ( changed ) {
 490              event.preventDefault();
 491              // The return string is needed for browser compat.
 492              // See https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event.
 493              return __( 'The changes you made will be lost if you navigate away from this page.' );
 494          }
 495      }).on( 'pagehide.edit-post', function( event ) {
 496          if ( ! releaseLock ) {
 497              return;
 498          }
 499  
 500          /*
 501           * Unload is triggered (by hand) on removing the Thickbox iframe.
 502           * Make sure we process only the main document unload.
 503           */
 504          if ( event.target && event.target.nodeName != '#document' ) {
 505              return;
 506          }
 507  
 508          var postID = $('#post_ID').val();
 509          var postLock = $('#active_post_lock').val();
 510  
 511          if ( ! postID || ! postLock ) {
 512              return;
 513          }
 514  
 515          var data = {
 516              action: 'wp-remove-post-lock',
 517              _wpnonce: $('#_wpnonce').val(),
 518              post_ID: postID,
 519              active_post_lock: postLock
 520          };
 521  
 522          if ( window.FormData && window.navigator.sendBeacon ) {
 523              var formData = new window.FormData();
 524  
 525              $.each( data, function( key, value ) {
 526                  formData.append( key, value );
 527              });
 528  
 529              if ( window.navigator.sendBeacon( ajaxurl, formData ) ) {
 530                  return;
 531              }
 532          }
 533  
 534          // Fall back to a synchronous POST request.
 535          // See https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
 536          $.post({
 537              async: false,
 538              data: data,
 539              url: ajaxurl
 540          });
 541      });
 542  
 543      // Multiple taxonomies.
 544      if ( $('#tagsdiv-post_tag').length ) {
 545          window.tagBox && window.tagBox.init();
 546      } else {
 547          $('.meta-box-sortables').children('div.postbox').each(function(){
 548              if ( this.id.indexOf('tagsdiv-') === 0 ) {
 549                  window.tagBox && window.tagBox.init();
 550                  return false;
 551              }
 552          });
 553      }
 554  
 555      // Handle categories.
 556      $('.categorydiv').each( function(){
 557          var this_id = $(this).attr('id'), catAddBefore, catAddAfter, taxonomyParts, taxonomy, settingName;
 558  
 559          taxonomyParts = this_id.split('-');
 560          taxonomyParts.shift();
 561          taxonomy = taxonomyParts.join('-');
 562          settingName = taxonomy + '_tab';
 563  
 564          if ( taxonomy == 'category' ) {
 565              settingName = 'cats';
 566          }
 567  
 568          // @todo Move to jQuery 1.3+, support for multiple hierarchical taxonomies, see wp-lists.js.
 569          $('a', '#' + taxonomy + '-tabs').on( 'click', function( e ) {
 570              e.preventDefault();
 571              var t = $(this).attr('href');
 572              $(this).parent().addClass('tabs').siblings('li').removeClass('tabs');
 573              $('#' + taxonomy + '-tabs').siblings('.tabs-panel').hide();
 574              $(t).show();
 575              if ( '#' + taxonomy + '-all' == t ) {
 576                  deleteUserSetting( settingName );
 577              } else {
 578                  setUserSetting( settingName, 'pop' );
 579              }
 580          });
 581  
 582          if ( getUserSetting( settingName ) )
 583              $('a[href="#' + taxonomy + '-pop"]', '#' + taxonomy + '-tabs').trigger( 'click' );
 584  
 585          // Add category button controls.
 586          $('#new' + taxonomy).one( 'focus', function() {
 587              $( this ).val( '' ).removeClass( 'form-input-tip' );
 588          });
 589  
 590          // On [Enter] submit the taxonomy.
 591          $('#new' + taxonomy).on( 'keypress', function(event){
 592              if( 13 === event.keyCode ) {
 593                  event.preventDefault();
 594                  $('#' + taxonomy + '-add-submit').trigger( 'click' );
 595              }
 596          });
 597  
 598          // After submitting a new taxonomy, re-focus the input field.
 599          $('#' + taxonomy + '-add-submit').on( 'click', function() {
 600              $('#new' + taxonomy).trigger( 'focus' );
 601          });
 602  
 603          /**
 604           * Before adding a new taxonomy, disable submit button.
 605           *
 606           * @param {Object} s Taxonomy object which will be added.
 607           *
 608           * @return {Object}
 609           */
 610          catAddBefore = function( s ) {
 611              if ( !$('#new'+taxonomy).val() ) {
 612                  return false;
 613              }
 614  
 615              s.data += '&' + $( ':checked', '#'+taxonomy+'checklist' ).serialize();
 616              $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', true );
 617              return s;
 618          };
 619  
 620          /**
 621           * Re-enable submit button after a taxonomy has been added.
 622           *
 623           * Re-enable submit button.
 624           * If the taxonomy has a parent place the taxonomy underneath the parent.
 625           *
 626           * @param {Object} r Response.
 627           * @param {Object} s Taxonomy data.
 628           *
 629           * @return {void}
 630           */
 631          catAddAfter = function( r, s ) {
 632              var sup, drop = $('#new'+taxonomy+'_parent');
 633  
 634              $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', false );
 635              if ( 'undefined' != s.parsed.responses[0] && (sup = s.parsed.responses[0].supplemental.newcat_parent) ) {
 636                  drop.before(sup);
 637                  drop.remove();
 638              }
 639          };
 640  
 641          $('#' + taxonomy + 'checklist').wpList({
 642              alt: '',
 643              response: taxonomy + '-ajax-response',
 644              addBefore: catAddBefore,
 645              addAfter: catAddAfter
 646          });
 647  
 648          // Add new taxonomy button toggles input form visibility.
 649          $('#' + taxonomy + '-add-toggle').on( 'click', function( e ) {
 650              e.preventDefault();
 651              $('#' + taxonomy + '-adder').toggleClass( 'wp-hidden-children' );
 652              $('a[href="#' + taxonomy + '-all"]', '#' + taxonomy + '-tabs').trigger( 'click' );
 653              $('#new'+taxonomy).trigger( 'focus' );
 654          });
 655  
 656          // Sync checked items between "All {taxonomy}" and "Most used" lists.
 657          $('#' + taxonomy + 'checklist, #' + taxonomy + 'checklist-pop').on(
 658              'click',
 659              'li.popular-category > label input[type="checkbox"]',
 660              function() {
 661                  var t = $(this), c = t.is(':checked'), id = t.val();
 662                  if ( id && t.parents('#taxonomy-'+taxonomy).length ) {
 663                      $('input[id^="in-' + taxonomy + '-' + id + '"]').prop('checked', c);
 664                      $('input#in-popular-' + taxonomy + '-' + id).prop('checked', c);
 665                  }
 666              }
 667          );
 668  
 669      }); // End cats.
 670  
 671      // Custom Fields postbox.
 672      if ( $('#postcustom').length ) {
 673          $( '#the-list' ).wpList( {
 674              /**
 675               * Add current post_ID to request to fetch custom fields
 676               *
 677               * @ignore
 678               *
 679               * @param {Object} s Request object.
 680               *
 681               * @return {Object} Data modified with post_ID attached.
 682               */
 683              addBefore: function( s ) {
 684                  s.data += '&post_id=' + $('#post_ID').val();
 685                  return s;
 686              },
 687              /**
 688               * Show the listing of custom fields after fetching.
 689               *
 690               * @ignore
 691               */
 692              addAfter: function() {
 693                  $('table#list-table').show();
 694              }
 695          });
 696      }
 697  
 698      /*
 699       * Publish Post box (#submitdiv)
 700       */
 701      if ( $('#submitdiv').length ) {
 702          stamp = $('#timestamp').html();
 703          visibility = $('#post-visibility-display').html();
 704  
 705          /**
 706           * When the visibility of a post changes sub-options should be shown or hidden.
 707           *
 708           * @ignore
 709           *
 710           * @return {void}
 711           */
 712          updateVisibility = function() {
 713              // Show sticky for public posts.
 714              if ( $postVisibilitySelect.find('input:radio:checked').val() != 'public' ) {
 715                  $('#sticky').prop('checked', false);
 716                  $('#sticky-span').hide();
 717              } else {
 718                  $('#sticky-span').show();
 719              }
 720  
 721              // Show password input field for password protected post.
 722              if ( $postVisibilitySelect.find('input:radio:checked').val() != 'password' ) {
 723                  $('#password-span').hide();
 724              } else {
 725                  $('#password-span').show();
 726              }
 727          };
 728  
 729          /**
 730           * Make sure all labels represent the current settings.
 731           *
 732           * @ignore
 733           *
 734           * @return {boolean} False when an invalid timestamp has been selected, otherwise True.
 735           */
 736          updateText = function() {
 737  
 738              if ( ! $timestampdiv.length )
 739                  return true;
 740  
 741              var attemptedDate, originalDate, currentDate, publishOn, postStatus = $('#post_status'),
 742                  optPublish = $('option[value="publish"]', postStatus), aa = $('#aa').val(),
 743                  mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val();
 744  
 745              attemptedDate = new Date( aa, mm - 1, jj, hh, mn );
 746              originalDate = new Date(
 747                  $('#hidden_aa').val(),
 748                  $('#hidden_mm').val() -1,
 749                  $('#hidden_jj').val(),
 750                  $('#hidden_hh').val(),
 751                  $('#hidden_mn').val()
 752              );
 753              currentDate = new Date(
 754                  $('#cur_aa').val(),
 755                  $('#cur_mm').val() -1,
 756                  $('#cur_jj').val(),
 757                  $('#cur_hh').val(),
 758                  $('#cur_mn').val()
 759              );
 760  
 761              // Catch unexpected date problems.
 762              if (
 763                  attemptedDate.getFullYear() != aa ||
 764                  (1 + attemptedDate.getMonth()) != mm ||
 765                  attemptedDate.getDate() != jj ||
 766                  attemptedDate.getMinutes() != mn
 767              ) {
 768                  $timestampdiv.find('.timestamp-wrap').addClass('form-invalid');
 769                  return false;
 770              } else {
 771                  $timestampdiv.find('.timestamp-wrap').removeClass('form-invalid');
 772              }
 773  
 774              // Determine what the publish should be depending on the date and post status.
 775              if ( attemptedDate > currentDate ) {
 776                  publishOn = __( 'Schedule for:' );
 777                  $('#publish').val( _x( 'Schedule', 'post action/button label' ) );
 778              } else if ( attemptedDate <= currentDate && $('#original_post_status').val() != 'publish' ) {
 779                  publishOn = __( 'Publish on:' );
 780                  $('#publish').val( __( 'Publish' ) );
 781              } else {
 782                  publishOn = __( 'Published on:' );
 783                  $('#publish').val( __( 'Update' ) );
 784              }
 785  
 786              // If the date is the same, set it to trigger update events.
 787              if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) {
 788                  // Re-set to the current value.
 789                  $('#timestamp').html(stamp);
 790              } else {
 791                  $('#timestamp').html(
 792                      '\n' + publishOn + ' <b>' +
 793                      // translators: 1: Month, 2: Day, 3: Year, 4: Hour, 5: Minute.
 794                      __( '%1$s %2$s, %3$s at %4$s:%5$s' )
 795                          .replace( '%1$s', $( 'option[value="' + mm + '"]', '#mm' ).attr( 'data-text' ) )
 796                          .replace( '%2$s', parseInt( jj, 10 ) )
 797                          .replace( '%3$s', aa )
 798                          .replace( '%4$s', ( '00' + hh ).slice( -2 ) )
 799                          .replace( '%5$s', ( '00' + mn ).slice( -2 ) ) +
 800                          '</b> '
 801                  );
 802              }
 803  
 804              // Add "privately published" to post status when applies.
 805              if ( $postVisibilitySelect.find('input:radio:checked').val() == 'private' ) {
 806                  $('#publish').val( __( 'Update' ) );
 807                  if ( 0 === optPublish.length ) {
 808                      postStatus.append('<option value="publish">' + __( 'Privately Published' ) + '</option>');
 809                  } else {
 810                      optPublish.html( __( 'Privately Published' ) );
 811                  }
 812                  $('option[value="publish"]', postStatus).prop('selected', true);
 813                  $('#misc-publishing-actions .edit-post-status').hide();
 814              } else {
 815                  if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) {
 816                      if ( optPublish.length ) {
 817                          optPublish.remove();
 818                          postStatus.val($('#hidden_post_status').val());
 819                      }
 820                  } else {
 821                      optPublish.html( __( 'Published' ) );
 822                  }
 823                  if ( postStatus.is(':hidden') )
 824                      $('#misc-publishing-actions .edit-post-status').show();
 825              }
 826  
 827              // Update "Status:" to currently selected status.
 828              $('#post-status-display').text(
 829                  // Remove any potential tags from post status text.
 830                  wp.sanitize.stripTagsAndEncodeText( $('option:selected', postStatus).text() )
 831              );
 832  
 833              // Show or hide the "Save Draft" button.
 834              if (
 835                  $('option:selected', postStatus).val() == 'private' ||
 836                  $('option:selected', postStatus).val() == 'publish'
 837              ) {
 838                  $('#save-post').hide();
 839              } else {
 840                  $('#save-post').show();
 841                  if ( $('option:selected', postStatus).val() == 'pending' ) {
 842                      $('#save-post').show().val( __( 'Save as Pending' ) );
 843                  } else {
 844                      $('#save-post').show().val( __( 'Save Draft' ) );
 845                  }
 846              }
 847              return true;
 848          };
 849  
 850          // Show the visibility options and hide the toggle button when opened.
 851          $( '#visibility .edit-visibility').on( 'click', function( e ) {
 852              e.preventDefault();
 853              if ( $postVisibilitySelect.is(':hidden') ) {
 854                  updateVisibility();
 855                  $postVisibilitySelect.slideDown( 'fast', function() {
 856                      $postVisibilitySelect.find( 'input[type="radio"]' ).first().trigger( 'focus' );
 857                  } );
 858                  $(this).hide();
 859              }
 860          });
 861  
 862          // Cancel visibility selection area and hide it from view.
 863          $postVisibilitySelect.find('.cancel-post-visibility').on( 'click', function( event ) {
 864              $postVisibilitySelect.slideUp('fast');
 865              $('#visibility-radio-' + $('#hidden-post-visibility').val()).prop('checked', true);
 866              $('#post_password').val($('#hidden-post-password').val());
 867              $('#sticky').prop('checked', $('#hidden-post-sticky').prop('checked'));
 868              $('#post-visibility-display').html(visibility);
 869              $('#visibility .edit-visibility').show().trigger( 'focus' );
 870              updateText();
 871              event.preventDefault();
 872          });
 873  
 874          // Set the selected visibility as current.
 875          $postVisibilitySelect.find('.save-post-visibility').on( 'click', function( event ) { // Crazyhorse branch - multiple OK cancels.
 876              var visibilityLabel = '', selectedVisibility = $postVisibilitySelect.find('input:radio:checked').val();
 877  
 878              $postVisibilitySelect.slideUp('fast');
 879              $('#visibility .edit-visibility').show().trigger( 'focus' );
 880              updateText();
 881  
 882              if ( 'public' !== selectedVisibility ) {
 883                  $('#sticky').prop('checked', false);
 884              }
 885  
 886              switch ( selectedVisibility ) {
 887                  case 'public':
 888                      visibilityLabel = $( '#sticky' ).prop( 'checked' ) ? __( 'Public, Sticky' ) : __( 'Public' );
 889                      break;
 890                  case 'private':
 891                      visibilityLabel = __( 'Private' );
 892                      break;
 893                  case 'password':
 894                      visibilityLabel = __( 'Password Protected' );
 895                      break;
 896              }
 897  
 898              $('#post-visibility-display').text( visibilityLabel );
 899              event.preventDefault();
 900          });
 901  
 902          // When the selection changes, update labels.
 903          $postVisibilitySelect.find('input:radio').on( 'change', function() {
 904              updateVisibility();
 905          });
 906  
 907          // Edit publish time click.
 908          $timestampdiv.siblings('a.edit-timestamp').on( 'click', function( event ) {
 909              if ( $timestampdiv.is( ':hidden' ) ) {
 910                  $timestampdiv.slideDown( 'fast', function() {
 911                      $( 'input, select', $timestampdiv.find( '.timestamp-wrap' ) ).first().trigger( 'focus' );
 912                  } );
 913                  $(this).hide();
 914              }
 915              event.preventDefault();
 916          });
 917  
 918          // Cancel editing the publish time and hide the settings.
 919          $timestampdiv.find('.cancel-timestamp').on( 'click', function( event ) {
 920              $timestampdiv.slideUp('fast').siblings('a.edit-timestamp').show().trigger( 'focus' );
 921              $('#mm').val($('#hidden_mm').val());
 922              $('#jj').val($('#hidden_jj').val());
 923              $('#aa').val($('#hidden_aa').val());
 924              $('#hh').val($('#hidden_hh').val());
 925              $('#mn').val($('#hidden_mn').val());
 926              updateText();
 927              event.preventDefault();
 928          });
 929  
 930          // Save the changed timestamp.
 931          $timestampdiv.find('.save-timestamp').on( 'click', function( event ) { // Crazyhorse branch - multiple OK cancels.
 932              if ( updateText() ) {
 933                  $timestampdiv.slideUp('fast');
 934                  $timestampdiv.siblings('a.edit-timestamp').show().trigger( 'focus' );
 935              }
 936              event.preventDefault();
 937          });
 938  
 939          // Cancel submit when an invalid timestamp has been selected.
 940          $('#post').on( 'submit', function( event ) {
 941              if ( ! updateText() ) {
 942                  event.preventDefault();
 943                  $timestampdiv.show();
 944  
 945                  if ( wp.autosave ) {
 946                      wp.autosave.enableButtons();
 947                  }
 948  
 949                  $( '#publishing-action .spinner' ).removeClass( 'is-active' );
 950              }
 951          });
 952  
 953          // Post Status edit click.
 954          $postStatusSelect.siblings('a.edit-post-status').on( 'click', function( event ) {
 955              if ( $postStatusSelect.is( ':hidden' ) ) {
 956                  $postStatusSelect.slideDown( 'fast', function() {
 957                      $postStatusSelect.find('select').trigger( 'focus' );
 958                  } );
 959                  $(this).hide();
 960              }
 961              event.preventDefault();
 962          });
 963  
 964          // Save the Post Status changes and hide the options.
 965          $postStatusSelect.find('.save-post-status').on( 'click', function( event ) {
 966              $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' );
 967              updateText();
 968              event.preventDefault();
 969          });
 970  
 971          // Cancel Post Status editing and hide the options.
 972          $postStatusSelect.find('.cancel-post-status').on( 'click', function( event ) {
 973              $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' );
 974              $('#post_status').val( $('#hidden_post_status').val() );
 975              updateText();
 976              event.preventDefault();
 977          });
 978      }
 979  
 980      /**
 981       * Handle the editing of the post_name. Create the required HTML elements and
 982       * update the changes via Ajax.
 983       *
 984       * @global
 985       *
 986       * @return {void}
 987       */
 988  	function editPermalink() {
 989          var i, slug_value, slug_label,
 990              $el, revert_e,
 991              c = 0,
 992              real_slug = $('#post_name'),
 993              revert_slug = real_slug.val(),
 994              permalink = $( '#sample-permalink' ),
 995              permalinkOrig = permalink.html(),
 996              permalinkInner = $( '#sample-permalink a' ).html(),
 997              buttons = $('#edit-slug-buttons'),
 998              buttonsOrig = buttons.html(),
 999              full = $('#editable-post-name-full');
1000  
1001          // Deal with Twemoji in the post-name.
1002          full.find( 'img' ).replaceWith( function() { return this.alt; } );
1003          full = full.html();
1004  
1005          permalink.html( permalinkInner );
1006  
1007          // Save current content to revert to when cancelling.
1008          $el = $( '#editable-post-name' );
1009          revert_e = $el.html();
1010  
1011          buttons.html(
1012              '<button type="button" class="save button button-small">' + __( 'OK' ) + '</button> ' +
1013              '<button type="button" class="cancel button-link">' + __( 'Cancel' ) + '</button>'
1014          );
1015  
1016          // Save permalink changes.
1017          buttons.children( '.save' ).on( 'click', function() {
1018              var new_slug = $el.children( 'input' ).val();
1019  
1020              if ( new_slug == $('#editable-post-name-full').text() ) {
1021                  buttons.children('.cancel').trigger( 'click' );
1022                  return;
1023              }
1024  
1025              $.post(
1026                  ajaxurl,
1027                  {
1028                      action: 'sample-permalink',
1029                      post_id: postId,
1030                      new_slug: new_slug,
1031                      new_title: $('#title').val(),
1032                      samplepermalinknonce: $('#samplepermalinknonce').val()
1033                  },
1034                  function(data) {
1035                      var box = $('#edit-slug-box');
1036                      box.html(data);
1037                      if (box.hasClass('hidden')) {
1038                          box.fadeIn('fast', function () {
1039                              box.removeClass('hidden');
1040                          });
1041                      }
1042  
1043                      buttons.html(buttonsOrig);
1044                      permalink.html(permalinkOrig);
1045                      real_slug.val(new_slug);
1046                      $( '.edit-slug' ).trigger( 'focus' );
1047                      wp.a11y.speak( __( 'Permalink saved' ) );
1048                  }
1049              );
1050          });
1051  
1052          // Cancel editing of permalink.
1053          buttons.children( '.cancel' ).on( 'click', function() {
1054              $('#view-post-btn').show();
1055              $el.html(revert_e);
1056              buttons.html(buttonsOrig);
1057              permalink.html(permalinkOrig);
1058              real_slug.val(revert_slug);
1059              $( '.edit-slug' ).trigger( 'focus' );
1060          });
1061  
1062          // If more than 1/4th of 'full' is '%', make it empty.
1063          for ( i = 0; i < full.length; ++i ) {
1064              if ( '%' == full.charAt(i) )
1065                  c++;
1066          }
1067          slug_value = ( c > full.length / 4 ) ? '' : full;
1068          slug_label = __( 'URL Slug' );
1069  
1070          $el.html(
1071              '<label for="new-post-slug" class="screen-reader-text">' + slug_label + '</label>' +
1072              '<input type="text" id="new-post-slug" value="' + slug_value + '" autocomplete="off" spellcheck="false" />'
1073          ).children( 'input' ).on( 'keydown', function( e ) {
1074              var key = e.which;
1075              // On [Enter], just save the new slug, don't save the post.
1076              if ( 13 === key ) {
1077                  e.preventDefault();
1078                  buttons.children( '.save' ).trigger( 'click' );
1079              }
1080              // On [Esc] cancel the editing.
1081              if ( 27 === key ) {
1082                  buttons.children( '.cancel' ).trigger( 'click' );
1083              }
1084          } ).on( 'keyup', function() {
1085              real_slug.val( this.value );
1086          }).trigger( 'focus' );
1087      }
1088  
1089      $( '#titlediv' ).on( 'click', '.edit-slug', function() {
1090          editPermalink();
1091      });
1092  
1093      /**
1094       * Adds screen reader text to the title label when needed.
1095       *
1096       * Use the 'screen-reader-text' class to emulate a placeholder attribute
1097       * and hide the label when entering a value.
1098       *
1099       * @param {string} id Optional. HTML ID to add the screen reader helper text to.
1100       *
1101       * @global
1102       *
1103       * @return {void}
1104       */
1105      window.wptitlehint = function( id ) {
1106          id = id || 'title';
1107  
1108          var title = $( '#' + id ), titleprompt = $( '#' + id + '-prompt-text' );
1109  
1110          if ( '' === title.val() ) {
1111              titleprompt.removeClass( 'screen-reader-text' );
1112          }
1113  
1114          title.on( 'input', function() {
1115              if ( '' === this.value ) {
1116                  titleprompt.removeClass( 'screen-reader-text' );
1117                  return;
1118              }
1119  
1120              titleprompt.addClass( 'screen-reader-text' );
1121          } );
1122      };
1123  
1124      wptitlehint();
1125  
1126      // Resize the WYSIWYG and plain text editors.
1127      ( function() {
1128          var editor, offset, mce,
1129              $handle = $('#post-status-info'),
1130              $postdivrich = $('#postdivrich');
1131  
1132          // If there are no textareas or we are on a touch device, we can't do anything.
1133          if ( ! $textarea.length || 'ontouchstart' in window ) {
1134              // Hide the resize handle.
1135              $('#content-resize-handle').hide();
1136              return;
1137          }
1138  
1139          /**
1140           * Handle drag event.
1141           *
1142           * @param {Object} event Event containing details about the drag.
1143           */
1144  		function dragging( event ) {
1145              if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) {
1146                  return;
1147              }
1148  
1149              if ( mce ) {
1150                  editor.theme.resizeTo( null, offset + event.pageY );
1151              } else {
1152                  $textarea.height( Math.max( 50, offset + event.pageY ) );
1153              }
1154  
1155              event.preventDefault();
1156          }
1157  
1158          /**
1159           * When the dragging stopped make sure we return focus and do a confidence check on the height.
1160           */
1161  		function endDrag() {
1162              var height, toolbarHeight;
1163  
1164              if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) {
1165                  return;
1166              }
1167  
1168              if ( mce ) {
1169                  editor.focus();
1170                  toolbarHeight = parseInt( $( '#wp-content-editor-container .mce-toolbar-grp' ).height(), 10 );
1171  
1172                  if ( toolbarHeight < 10 || toolbarHeight > 200 ) {
1173                      toolbarHeight = 30;
1174                  }
1175  
1176                  height = parseInt( $('#content_ifr').css('height'), 10 ) + toolbarHeight - 28;
1177              } else {
1178                  $textarea.trigger( 'focus' );
1179                  height = parseInt( $textarea.css('height'), 10 );
1180              }
1181  
1182              $document.off( '.wp-editor-resize' );
1183  
1184              // Confidence check: normalize height to stay within acceptable ranges.
1185              if ( height && height > 50 && height < 5000 ) {
1186                  setUserSetting( 'ed_size', height );
1187              }
1188          }
1189  
1190          $handle.on( 'mousedown.wp-editor-resize', function( event ) {
1191              if ( typeof tinymce !== 'undefined' ) {
1192                  editor = tinymce.get('content');
1193              }
1194  
1195              if ( editor && ! editor.isHidden() ) {
1196                  mce = true;
1197                  offset = $('#content_ifr').height() - event.pageY;
1198              } else {
1199                  mce = false;
1200                  offset = $textarea.height() - event.pageY;
1201                  $textarea.trigger( 'blur' );
1202              }
1203  
1204              $document.on( 'mousemove.wp-editor-resize', dragging )
1205                  .on( 'mouseup.wp-editor-resize mouseleave.wp-editor-resize', endDrag );
1206  
1207              event.preventDefault();
1208          }).on( 'mouseup.wp-editor-resize', endDrag );
1209      })();
1210  
1211      // TinyMCE specific handling of Post Format changes to reflect in the editor.
1212      if ( typeof tinymce !== 'undefined' ) {
1213          // When changing post formats, change the editor body class.
1214          $( '#post-formats-select input.post-format' ).on( 'change.set-editor-class', function() {
1215              var editor, body, format = this.id;
1216  
1217              if ( format && $( this ).prop( 'checked' ) && ( editor = tinymce.get( 'content' ) ) ) {
1218                  body = editor.getBody();
1219                  body.className = body.className.replace( /\bpost-format-[^ ]+/, '' );
1220                  editor.dom.addClass( body, format == 'post-format-0' ? 'post-format-standard' : format );
1221                  $( document ).trigger( 'editor-classchange' );
1222              }
1223          });
1224  
1225          // When changing page template, change the editor body class.
1226          $( '#page_template' ).on( 'change.set-editor-class', function() {
1227              var editor, body, pageTemplate = $( this ).val() || '';
1228  
1229              pageTemplate = pageTemplate.substr( pageTemplate.lastIndexOf( '/' ) + 1, pageTemplate.length )
1230                  .replace( /\.php$/, '' )
1231                  .replace( /\./g, '-' );
1232  
1233              if ( pageTemplate && ( editor = tinymce.get( 'content' ) ) ) {
1234                  body = editor.getBody();
1235                  body.className = body.className.replace( /\bpage-template-[^ ]+/, '' );
1236                  editor.dom.addClass( body, 'page-template-' + pageTemplate );
1237                  $( document ).trigger( 'editor-classchange' );
1238              }
1239          });
1240  
1241      }
1242  
1243      // Save on pressing [Ctrl]/[Command] + [S] in the Text editor.
1244      $textarea.on( 'keydown.wp-autosave', function( event ) {
1245          // Key [S] has code 83.
1246          if ( event.which === 83 ) {
1247              if (
1248                  event.shiftKey ||
1249                  event.altKey ||
1250                  ( isMac && ( ! event.metaKey || event.ctrlKey ) ) ||
1251                  ( ! isMac && ! event.ctrlKey )
1252              ) {
1253                  return;
1254              }
1255  
1256              wp.autosave && wp.autosave.server.triggerSave();
1257              event.preventDefault();
1258          }
1259      });
1260  
1261      // If the last status was auto-draft and the save is triggered, edit the current URL.
1262      if ( $( '#original_post_status' ).val() === 'auto-draft' && window.history.replaceState ) {
1263          var location;
1264  
1265          $( '#publish' ).on( 'click', function() {
1266              location = window.location.href;
1267              location += ( location.indexOf( '?' ) !== -1 ) ? '&' : '?';
1268              location += 'wp-post-new-reload=true';
1269  
1270              window.history.replaceState( null, null, location );
1271          });
1272      }
1273  
1274      /**
1275       * Copies the attachment URL in the Edit Media page to the clipboard.
1276       *
1277       * @since 5.5.0
1278       *
1279       * @param {MouseEvent} event A click event.
1280       *
1281       * @return {void}
1282       */
1283      copyAttachmentURLClipboard.on( 'success', function( event ) {
1284          var triggerElement = $( event.trigger ),
1285              successElement = $( '.success', triggerElement.closest( '.copy-to-clipboard-container' ) );
1286  
1287          // Clear the selection and move focus back to the trigger.
1288          event.clearSelection();
1289  
1290          // Show success visual feedback.
1291          clearTimeout( copyAttachmentURLSuccessTimeout );
1292          successElement.removeClass( 'hidden' );
1293  
1294          // Hide success visual feedback after 3 seconds since last success.
1295          copyAttachmentURLSuccessTimeout = setTimeout( function() {
1296              successElement.addClass( 'hidden' );
1297          }, 3000 );
1298  
1299          // Handle success audible feedback.
1300          wp.a11y.speak( __( 'The file URL has been copied to your clipboard' ) );
1301      } );
1302  } );
1303  
1304  /**
1305   * TinyMCE word count display
1306   */
1307  ( function( $, counter ) {
1308      $( function() {
1309          var $content = $( '#content' ),
1310              $count = $( '#wp-word-count' ).find( '.word-count' ),
1311              prevCount = 0,
1312              contentEditor;
1313  
1314          /**
1315           * Get the word count from TinyMCE and display it
1316           */
1317  		function update() {
1318              var text, count;
1319  
1320              if ( ! contentEditor || contentEditor.isHidden() ) {
1321                  text = $content.val();
1322              } else {
1323                  text = contentEditor.getContent( { format: 'raw' } );
1324              }
1325  
1326              count = counter.count( text );
1327  
1328              if ( count !== prevCount ) {
1329                  $count.text( count );
1330              }
1331  
1332              prevCount = count;
1333          }
1334  
1335          /**
1336           * Bind the word count update triggers.
1337           *
1338           * When a node change in the main TinyMCE editor has been triggered.
1339           * When a key has been released in the plain text content editor.
1340           */
1341          $( document ).on( 'tinymce-editor-init', function( event, editor ) {
1342              if ( editor.id !== 'content' ) {
1343                  return;
1344              }
1345  
1346              contentEditor = editor;
1347  
1348              editor.on( 'nodechange keyup', _.debounce( update, 1000 ) );
1349          } );
1350  
1351          $content.on( 'input keyup', _.debounce( update, 1000 ) );
1352  
1353          update();
1354      } );
1355  
1356  } )( jQuery, new wp.utils.WordCounter() );


Generated : Thu Nov 21 08:20:01 2024 Cross-referenced by PHPXref