[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-admin/js/ -> edit-comments.js (source)

   1  /**
   2   * Handles updating and editing comments.
   3   *
   4   * @file This file contains functionality for the admin comments page.
   5   * @since 2.1.0
   6   * @output wp-admin/js/edit-comments.js
   7   */
   8  
   9  /* global adminCommentsL10n, thousandsSeparator, list_args, QTags, ajaxurl, wpAjax */
  10  /* global commentReply, theExtraList, theList, setCommentsList */
  11  
  12  (function($) {
  13  var getCount, updateCount, updateCountText, updatePending, updateApproved,
  14      updateHtmlTitle, updateDashboardText, updateInModerationText, adminTitle = document.title,
  15      isDashboard = $('#dashboard_right_now').length,
  16      titleDiv, titleRegEx;
  17  
  18      /**
  19       * Extracts a number from the content of a jQuery element.
  20       *
  21       * @since 2.9.0
  22       * @access private
  23       *
  24       * @param {jQuery} el jQuery element.
  25       *
  26       * @return {number} The number found in the given element.
  27       */
  28      getCount = function(el) {
  29          var n = parseInt( el.html().replace(/[^0-9]+/g, ''), 10 );
  30          if ( isNaN(n) ) {
  31              return 0;
  32          }
  33          return n;
  34      };
  35  
  36      /**
  37       * Updates an html element with a localized number string.
  38       *
  39       * @since 2.9.0
  40       * @access private
  41       *
  42       * @param {jQuery} el The jQuery element to update.
  43       * @param {number} n Number to be put in the element.
  44       *
  45       * @return {void}
  46       */
  47      updateCount = function(el, n) {
  48          var n1 = '';
  49          if ( isNaN(n) ) {
  50              return;
  51          }
  52          n = n < 1 ? '0' : n.toString();
  53          if ( n.length > 3 ) {
  54              while ( n.length > 3 ) {
  55                  n1 = thousandsSeparator + n.substr(n.length - 3) + n1;
  56                  n = n.substr(0, n.length - 3);
  57              }
  58              n = n + n1;
  59          }
  60          el.html(n);
  61      };
  62  
  63      /**
  64       * Updates the number of approved comments on a specific post and the filter bar.
  65       *
  66       * @since 4.4.0
  67       * @access private
  68       *
  69       * @param {number} diff The amount to lower or raise the approved count with.
  70       * @param {number} commentPostId The ID of the post to be updated.
  71       *
  72       * @return {void}
  73       */
  74      updateApproved = function( diff, commentPostId ) {
  75          var postSelector = '.post-com-count-' + commentPostId,
  76              noClass = 'comment-count-no-comments',
  77              approvedClass = 'comment-count-approved',
  78              approved,
  79              noComments;
  80  
  81          updateCountText( 'span.approved-count', diff );
  82  
  83          if ( ! commentPostId ) {
  84              return;
  85          }
  86  
  87          // Cache selectors to not get duplicates.
  88          approved = $( 'span.' + approvedClass, postSelector );
  89          noComments = $( 'span.' + noClass, postSelector );
  90  
  91          approved.each(function() {
  92              var a = $(this), n = getCount(a) + diff;
  93              if ( n < 1 )
  94                  n = 0;
  95  
  96              if ( 0 === n ) {
  97                  a.removeClass( approvedClass ).addClass( noClass );
  98              } else {
  99                  a.addClass( approvedClass ).removeClass( noClass );
 100              }
 101              updateCount( a, n );
 102          });
 103  
 104          noComments.each(function() {
 105              var a = $(this);
 106              if ( diff > 0 ) {
 107                  a.removeClass( noClass ).addClass( approvedClass );
 108              } else {
 109                  a.addClass( noClass ).removeClass( approvedClass );
 110              }
 111              updateCount( a, diff );
 112          });
 113      };
 114  
 115      /**
 116       * Updates a number count in all matched HTML elements
 117       *
 118       * @since 4.4.0
 119       * @access private
 120       *
 121       * @param {string} selector The jQuery selector for elements to update a count
 122       *                          for.
 123       * @param {number} diff The amount to lower or raise the count with.
 124       *
 125       * @return {void}
 126       */
 127      updateCountText = function( selector, diff ) {
 128          $( selector ).each(function() {
 129              var a = $(this), n = getCount(a) + diff;
 130              if ( n < 1 ) {
 131                  n = 0;
 132              }
 133              updateCount( a, n );
 134          });
 135      };
 136  
 137      /**
 138       * Updates a text about comment count on the dashboard.
 139       *
 140       * @since 4.4.0
 141       * @access private
 142       *
 143       * @param {Object} response Ajax response from the server that includes a
 144       *                          translated "comment count" message.
 145       *
 146       * @return {void}
 147       */
 148      updateDashboardText = function( response ) {
 149          if ( ! isDashboard || ! response || ! response.i18n_comments_text ) {
 150              return;
 151          }
 152  
 153          $( '.comment-count a', '#dashboard_right_now' ).text( response.i18n_comments_text );
 154      };
 155  
 156      /**
 157       * Updates the "comments in moderation" text across the UI.
 158       *
 159       * @since 5.2.0
 160       *
 161       * @param {object} response Ajax response from the server that includes a
 162       *                          translated "comments in moderation" message.
 163       *
 164       * @return {void}
 165       */
 166      updateInModerationText = function( response ) {
 167          if ( ! response || ! response.i18n_moderation_text ) {
 168              return;
 169          }
 170  
 171          // Update the "comment in moderation" text across the UI.
 172          $( '.comments-in-moderation-text' ).text( response.i18n_moderation_text );
 173          // Hide the "comment in moderation" text in the Dashboard "At a Glance" widget.
 174          if ( isDashboard && response.in_moderation ) {
 175              $( '.comment-mod-count', '#dashboard_right_now' )
 176                  [ response.in_moderation > 0 ? 'removeClass' : 'addClass' ]( 'hidden' );
 177          }
 178      };
 179  
 180      /**
 181       * Updates the title of the document with the number comments to be approved.
 182       *
 183       * @since 4.4.0
 184       * @access private
 185       *
 186       * @param {number} diff The amount to lower or raise the number of to be
 187       *                      approved comments with.
 188       *
 189       * @return {void}
 190       */
 191      updateHtmlTitle = function( diff ) {
 192          var newTitle, regExMatch, titleCount, commentFrag;
 193  
 194          titleRegEx = titleRegEx || new RegExp( adminCommentsL10n.docTitleCommentsCount.replace( '%s', '\\([0-9' + thousandsSeparator + ']+\\)' ) + '?' );
 195          // Count funcs operate on a $'d element.
 196          titleDiv = titleDiv || $( '<div />' );
 197          newTitle = adminTitle;
 198  
 199          commentFrag = titleRegEx.exec( document.title );
 200          if ( commentFrag ) {
 201              commentFrag = commentFrag[0];
 202              titleDiv.html( commentFrag );
 203              titleCount = getCount( titleDiv ) + diff;
 204          } else {
 205              titleDiv.html( 0 );
 206              titleCount = diff;
 207          }
 208  
 209          if ( titleCount >= 1 ) {
 210              updateCount( titleDiv, titleCount );
 211              regExMatch = titleRegEx.exec( document.title );
 212              if ( regExMatch ) {
 213                  newTitle = document.title.replace( regExMatch[0], adminCommentsL10n.docTitleCommentsCount.replace( '%s', titleDiv.text() ) + ' ' );
 214              }
 215          } else {
 216              regExMatch = titleRegEx.exec( newTitle );
 217              if ( regExMatch ) {
 218                  newTitle = newTitle.replace( regExMatch[0], adminCommentsL10n.docTitleComments );
 219              }
 220          }
 221          document.title = newTitle;
 222      };
 223  
 224      /**
 225       * Updates the number of pending comments on a specific post and the filter bar.
 226       *
 227       * @since 3.2.0
 228       * @access private
 229       *
 230       * @param {number} diff The amount to lower or raise the pending count with.
 231       * @param {number} commentPostId The ID of the post to be updated.
 232       *
 233       * @return {void}
 234       */
 235      updatePending = function( diff, commentPostId ) {
 236          var postSelector = '.post-com-count-' + commentPostId,
 237              noClass = 'comment-count-no-pending',
 238              noParentClass = 'post-com-count-no-pending',
 239              pendingClass = 'comment-count-pending',
 240              pending,
 241              noPending;
 242  
 243          if ( ! isDashboard ) {
 244              updateHtmlTitle( diff );
 245          }
 246  
 247          $( 'span.pending-count' ).each(function() {
 248              var a = $(this), n = getCount(a) + diff;
 249              if ( n < 1 )
 250                  n = 0;
 251              a.closest('.awaiting-mod')[ 0 === n ? 'addClass' : 'removeClass' ]('count-0');
 252              updateCount( a, n );
 253          });
 254  
 255          if ( ! commentPostId ) {
 256              return;
 257          }
 258  
 259          // Cache selectors to not get dupes.
 260          pending = $( 'span.' + pendingClass, postSelector );
 261          noPending = $( 'span.' + noClass, postSelector );
 262  
 263          pending.each(function() {
 264              var a = $(this), n = getCount(a) + diff;
 265              if ( n < 1 )
 266                  n = 0;
 267  
 268              if ( 0 === n ) {
 269                  a.parent().addClass( noParentClass );
 270                  a.removeClass( pendingClass ).addClass( noClass );
 271              } else {
 272                  a.parent().removeClass( noParentClass );
 273                  a.addClass( pendingClass ).removeClass( noClass );
 274              }
 275              updateCount( a, n );
 276          });
 277  
 278          noPending.each(function() {
 279              var a = $(this);
 280              if ( diff > 0 ) {
 281                  a.parent().removeClass( noParentClass );
 282                  a.removeClass( noClass ).addClass( pendingClass );
 283              } else {
 284                  a.parent().addClass( noParentClass );
 285                  a.addClass( noClass ).removeClass( pendingClass );
 286              }
 287              updateCount( a, diff );
 288          });
 289      };
 290  
 291  /**
 292   * Initializes the comments list.
 293   *
 294   * @since 4.4.0
 295   *
 296   * @global
 297   *
 298   * @return {void}
 299   */
 300  window.setCommentsList = function() {
 301      var totalInput, perPageInput, pageInput, dimAfter, delBefore, updateTotalCount, delAfter, refillTheExtraList, diff,
 302          lastConfidentTime = 0;
 303  
 304      totalInput = $('input[name="_total"]', '#comments-form');
 305      perPageInput = $('input[name="_per_page"]', '#comments-form');
 306      pageInput = $('input[name="_page"]', '#comments-form');
 307  
 308      /**
 309       * Updates the total with the latest count.
 310       *
 311       * The time parameter makes sure that we only update the total if this value is
 312       * a newer value than we previously received.
 313       *
 314       * The time and setConfidentTime parameters make sure that we only update the
 315       * total when necessary. So a value that has been generated earlier will not
 316       * update the total.
 317       *
 318       * @since 2.8.0
 319       * @access private
 320       *
 321       * @param {number} total Total number of comments.
 322       * @param {number} time Unix timestamp of response.
 323        * @param {boolean} setConfidentTime Whether to update the last confident time
 324       *                                   with the given time.
 325       *
 326       * @return {void}
 327       */
 328      updateTotalCount = function( total, time, setConfidentTime ) {
 329          if ( time < lastConfidentTime )
 330              return;
 331  
 332          if ( setConfidentTime )
 333              lastConfidentTime = time;
 334  
 335          totalInput.val( total.toString() );
 336      };
 337  
 338      /**
 339       * Changes DOM that need to be changed after a list item has been dimmed.
 340       *
 341       * @since 2.5.0
 342       * @access private
 343       *
 344       * @param {Object} r Ajax response object.
 345       * @param {Object} settings Settings for the wpList object.
 346       *
 347       * @return {void}
 348       */
 349      dimAfter = function( r, settings ) {
 350          var editRow, replyID, replyButton, response,
 351              c = $( '#' + settings.element );
 352  
 353          if ( true !== settings.parsed ) {
 354              response = settings.parsed.responses[0];
 355          }
 356  
 357          editRow = $('#replyrow');
 358          replyID = $('#comment_ID', editRow).val();
 359          replyButton = $('#replybtn', editRow);
 360  
 361          if ( c.is('.unapproved') ) {
 362              if ( settings.data.id == replyID )
 363                  replyButton.text(adminCommentsL10n.replyApprove);
 364  
 365              c.find( '.row-actions span.view' ).addClass( 'hidden' ).end()
 366                  .find( 'div.comment_status' ).html( '0' );
 367  
 368          } else {
 369              if ( settings.data.id == replyID )
 370                  replyButton.text(adminCommentsL10n.reply);
 371  
 372              c.find( '.row-actions span.view' ).removeClass( 'hidden' ).end()
 373                  .find( 'div.comment_status' ).html( '1' );
 374          }
 375  
 376          diff = $('#' + settings.element).is('.' + settings.dimClass) ? 1 : -1;
 377          if ( response ) {
 378              updateDashboardText( response.supplemental );
 379              updateInModerationText( response.supplemental );
 380              updatePending( diff, response.supplemental.postId );
 381              updateApproved( -1 * diff, response.supplemental.postId );
 382          } else {
 383              updatePending( diff );
 384              updateApproved( -1 * diff  );
 385          }
 386      };
 387  
 388      /**
 389       * Handles marking a comment as spam or trashing the comment.
 390       *
 391       * Is executed in the list delBefore hook.
 392       *
 393       * @since 2.8.0
 394       * @access private
 395       *
 396       * @param {Object} settings Settings for the wpList object.
 397       * @param {HTMLElement} list Comments table element.
 398       *
 399       * @return {Object} The settings object.
 400       */
 401      delBefore = function( settings, list ) {
 402          var note, id, el, n, h, a, author,
 403              action = false,
 404              wpListsData = $( settings.target ).attr( 'data-wp-lists' );
 405  
 406          settings.data._total = totalInput.val() || 0;
 407          settings.data._per_page = perPageInput.val() || 0;
 408          settings.data._page = pageInput.val() || 0;
 409          settings.data._url = document.location.href;
 410          settings.data.comment_status = $('input[name="comment_status"]', '#comments-form').val();
 411  
 412          if ( wpListsData.indexOf(':trash=1') != -1 )
 413              action = 'trash';
 414          else if ( wpListsData.indexOf(':spam=1') != -1 )
 415              action = 'spam';
 416  
 417          if ( action ) {
 418              id = wpListsData.replace(/.*?comment-([0-9]+).*/, '$1');
 419              el = $('#comment-' + id);
 420              note = $('#' + action + '-undo-holder').html();
 421  
 422              el.find('.check-column :checkbox').prop('checked', false); // Uncheck the row so as not to be affected by Bulk Edits.
 423  
 424              if ( el.siblings('#replyrow').length && commentReply.cid == id )
 425                  commentReply.close();
 426  
 427              if ( el.is('tr') ) {
 428                  n = el.children(':visible').length;
 429                  author = $('.author strong', el).text();
 430                  h = $('<tr id="undo-' + id + '" class="undo un' + action + '" style="display:none;"><td colspan="' + n + '">' + note + '</td></tr>');
 431              } else {
 432                  author = $('.comment-author', el).text();
 433                  h = $('<div id="undo-' + id + '" style="display:none;" class="undo un' + action + '">' + note + '</div>');
 434              }
 435  
 436              el.before(h);
 437  
 438              $('strong', '#undo-' + id).text(author);
 439              a = $('.undo a', '#undo-' + id);
 440              a.attr('href', 'comment.php?action=un' + action + 'comment&c=' + id + '&_wpnonce=' + settings.data._ajax_nonce);
 441              a.attr('data-wp-lists', 'delete:the-comment-list:comment-' + id + '::un' + action + '=1');
 442              a.attr('class', 'vim-z vim-destructive aria-button-if-js');
 443              $('.avatar', el).first().clone().prependTo('#undo-' + id + ' .' + action + '-undo-inside');
 444  
 445              a.click(function( e ){
 446                  e.preventDefault();
 447                  e.stopPropagation(); // Ticket #35904.
 448                  list.wpList.del(this);
 449                  $('#undo-' + id).css( {backgroundColor:'#ceb'} ).fadeOut(350, function(){
 450                      $(this).remove();
 451                      $('#comment-' + id).css('backgroundColor', '').fadeIn(300, function(){ $(this).show(); });
 452                  });
 453              });
 454          }
 455  
 456          return settings;
 457      };
 458  
 459      /**
 460       * Handles actions that need to be done after marking as spam or thrashing a
 461       * comment.
 462       *
 463       * The ajax requests return the unix time stamp a comment was marked as spam or
 464       * trashed. We use this to have a correct total amount of comments.
 465       *
 466       * @since 2.5.0
 467       * @access private
 468       *
 469       * @param {Object} r Ajax response object.
 470       * @param {Object} settings Settings for the wpList object.
 471       *
 472       * @return {void}
 473       */
 474      delAfter = function( r, settings ) {
 475          var total_items_i18n, total, animated, animatedCallback,
 476              response = true === settings.parsed ? {} : settings.parsed.responses[0],
 477              commentStatus = true === settings.parsed ? '' : response.supplemental.status,
 478              commentPostId = true === settings.parsed ? '' : response.supplemental.postId,
 479              newTotal = true === settings.parsed ? '' : response.supplemental,
 480  
 481              targetParent = $( settings.target ).parent(),
 482              commentRow = $('#' + settings.element),
 483  
 484              spamDiff, trashDiff, pendingDiff, approvedDiff,
 485  
 486              /*
 487               * As `wpList` toggles only the `unapproved` class, the approved comment
 488               * rows can have both the `approved` and `unapproved` classes.
 489               */
 490              approved = commentRow.hasClass( 'approved' ) && ! commentRow.hasClass( 'unapproved' ),
 491              unapproved = commentRow.hasClass( 'unapproved' ),
 492              spammed = commentRow.hasClass( 'spam' ),
 493              trashed = commentRow.hasClass( 'trash' ),
 494              undoing = false; // Ticket #35904.
 495  
 496          updateDashboardText( newTotal );
 497          updateInModerationText( newTotal );
 498  
 499          /*
 500           * The order of these checks is important.
 501           * .unspam can also have .approve or .unapprove.
 502           * .untrash can also have .approve or .unapprove.
 503           */
 504  
 505          if ( targetParent.is( 'span.undo' ) ) {
 506              // The comment was spammed.
 507              if ( targetParent.hasClass( 'unspam' ) ) {
 508                  spamDiff = -1;
 509  
 510                  if ( 'trash' === commentStatus ) {
 511                      trashDiff = 1;
 512                  } else if ( '1' === commentStatus ) {
 513                      approvedDiff = 1;
 514                  } else if ( '0' === commentStatus ) {
 515                      pendingDiff = 1;
 516                  }
 517  
 518              // The comment was trashed.
 519              } else if ( targetParent.hasClass( 'untrash' ) ) {
 520                  trashDiff = -1;
 521  
 522                  if ( 'spam' === commentStatus ) {
 523                      spamDiff = 1;
 524                  } else if ( '1' === commentStatus ) {
 525                      approvedDiff = 1;
 526                  } else if ( '0' === commentStatus ) {
 527                      pendingDiff = 1;
 528                  }
 529              }
 530  
 531              undoing = true;
 532  
 533          // User clicked "Spam".
 534          } else if ( targetParent.is( 'span.spam' ) ) {
 535              // The comment is currently approved.
 536              if ( approved ) {
 537                  approvedDiff = -1;
 538              // The comment is currently pending.
 539              } else if ( unapproved ) {
 540                  pendingDiff = -1;
 541              // The comment was in the Trash.
 542              } else if ( trashed ) {
 543                  trashDiff = -1;
 544              }
 545              // You can't spam an item on the Spam screen.
 546              spamDiff = 1;
 547  
 548          // User clicked "Unspam".
 549          } else if ( targetParent.is( 'span.unspam' ) ) {
 550              if ( approved ) {
 551                  pendingDiff = 1;
 552              } else if ( unapproved ) {
 553                  approvedDiff = 1;
 554              } else if ( trashed ) {
 555                  // The comment was previously approved.
 556                  if ( targetParent.hasClass( 'approve' ) ) {
 557                      approvedDiff = 1;
 558                  // The comment was previously pending.
 559                  } else if ( targetParent.hasClass( 'unapprove' ) ) {
 560                      pendingDiff = 1;
 561                  }
 562              } else if ( spammed ) {
 563                  if ( targetParent.hasClass( 'approve' ) ) {
 564                      approvedDiff = 1;
 565  
 566                  } else if ( targetParent.hasClass( 'unapprove' ) ) {
 567                      pendingDiff = 1;
 568                  }
 569              }
 570              // You can unspam an item on the Spam screen.
 571              spamDiff = -1;
 572  
 573          // User clicked "Trash".
 574          } else if ( targetParent.is( 'span.trash' ) ) {
 575              if ( approved ) {
 576                  approvedDiff = -1;
 577              } else if ( unapproved ) {
 578                  pendingDiff = -1;
 579              // The comment was in the spam queue.
 580              } else if ( spammed ) {
 581                  spamDiff = -1;
 582              }
 583              // You can't trash an item on the Trash screen.
 584              trashDiff = 1;
 585  
 586          // User clicked "Restore".
 587          } else if ( targetParent.is( 'span.untrash' ) ) {
 588              if ( approved ) {
 589                  pendingDiff = 1;
 590              } else if ( unapproved ) {
 591                  approvedDiff = 1;
 592              } else if ( trashed ) {
 593                  if ( targetParent.hasClass( 'approve' ) ) {
 594                      approvedDiff = 1;
 595                  } else if ( targetParent.hasClass( 'unapprove' ) ) {
 596                      pendingDiff = 1;
 597                  }
 598              }
 599              // You can't go from Trash to Spam.
 600              // You can untrash on the Trash screen.
 601              trashDiff = -1;
 602  
 603          // User clicked "Approve".
 604          } else if ( targetParent.is( 'span.approve:not(.unspam):not(.untrash)' ) ) {
 605              approvedDiff = 1;
 606              pendingDiff = -1;
 607  
 608          // User clicked "Unapprove".
 609          } else if ( targetParent.is( 'span.unapprove:not(.unspam):not(.untrash)' ) ) {
 610              approvedDiff = -1;
 611              pendingDiff = 1;
 612  
 613          // User clicked "Delete Permanently".
 614          } else if ( targetParent.is( 'span.delete' ) ) {
 615              if ( spammed ) {
 616                  spamDiff = -1;
 617              } else if ( trashed ) {
 618                  trashDiff = -1;
 619              }
 620          }
 621  
 622          if ( pendingDiff ) {
 623              updatePending( pendingDiff, commentPostId );
 624              updateCountText( 'span.all-count', pendingDiff );
 625          }
 626  
 627          if ( approvedDiff ) {
 628              updateApproved( approvedDiff, commentPostId );
 629              updateCountText( 'span.all-count', approvedDiff );
 630          }
 631  
 632          if ( spamDiff ) {
 633              updateCountText( 'span.spam-count', spamDiff );
 634          }
 635  
 636          if ( trashDiff ) {
 637              updateCountText( 'span.trash-count', trashDiff );
 638          }
 639  
 640          if (
 641              ( ( 'trash' === settings.data.comment_status ) && !getCount( $( 'span.trash-count' ) ) ) ||
 642              ( ( 'spam' === settings.data.comment_status ) && !getCount( $( 'span.spam-count' ) ) )
 643          ) {
 644              $( '#delete_all' ).hide();
 645          }
 646  
 647          if ( ! isDashboard ) {
 648              total = totalInput.val() ? parseInt( totalInput.val(), 10 ) : 0;
 649              if ( $(settings.target).parent().is('span.undo') )
 650                  total++;
 651              else
 652                  total--;
 653  
 654              if ( total < 0 )
 655                  total = 0;
 656  
 657              if ( 'object' === typeof r ) {
 658                  if ( response.supplemental.total_items_i18n && lastConfidentTime < response.supplemental.time ) {
 659                      total_items_i18n = response.supplemental.total_items_i18n || '';
 660                      if ( total_items_i18n ) {
 661                          $('.displaying-num').text( total_items_i18n.replace( '&nbsp;', String.fromCharCode( 160 ) ) );
 662                          $('.total-pages').text( response.supplemental.total_pages_i18n.replace( '&nbsp;', String.fromCharCode( 160 ) ) );
 663                          $('.tablenav-pages').find('.next-page, .last-page').toggleClass('disabled', response.supplemental.total_pages == $('.current-page').val());
 664                      }
 665                      updateTotalCount( total, response.supplemental.time, true );
 666                  } else if ( response.supplemental.time ) {
 667                      updateTotalCount( total, response.supplemental.time, false );
 668                  }
 669              } else {
 670                  updateTotalCount( total, r, false );
 671              }
 672          }
 673  
 674          if ( ! theExtraList || theExtraList.length === 0 || theExtraList.children().length === 0 || undoing ) {
 675              return;
 676          }
 677  
 678          theList.get(0).wpList.add( theExtraList.children( ':eq(0):not(.no-items)' ).remove().clone() );
 679  
 680          refillTheExtraList();
 681  
 682          animated = $( ':animated', '#the-comment-list' );
 683          animatedCallback = function() {
 684              if ( ! $( '#the-comment-list tr:visible' ).length ) {
 685                  theList.get(0).wpList.add( theExtraList.find( '.no-items' ).clone() );
 686              }
 687          };
 688  
 689          if ( animated.length ) {
 690              animated.promise().done( animatedCallback );
 691          } else {
 692              animatedCallback();
 693          }
 694      };
 695  
 696      /**
 697       * Retrieves additional comments to populate the extra list.
 698       *
 699       * @since 3.1.0
 700       * @access private
 701       *
 702       * @param {boolean} [ev] Repopulate the extra comments list if true.
 703       *
 704       * @return {void}
 705       */
 706      refillTheExtraList = function(ev) {
 707          var args = $.query.get(), total_pages = $('.total-pages').text(), per_page = $('input[name="_per_page"]', '#comments-form').val();
 708  
 709          if (! args.paged)
 710              args.paged = 1;
 711  
 712          if (args.paged > total_pages) {
 713              return;
 714          }
 715  
 716          if (ev) {
 717              theExtraList.empty();
 718              args.number = Math.min(8, per_page); // See WP_Comments_List_Table::prepare_items() in class-wp-comments-list-table.php.
 719          } else {
 720              args.number = 1;
 721              args.offset = Math.min(8, per_page) - 1; // Fetch only the next item on the extra list.
 722          }
 723  
 724          args.no_placeholder = true;
 725  
 726          args.paged ++;
 727  
 728          // $.query.get() needs some correction to be sent into an Ajax request.
 729          if ( true === args.comment_type )
 730              args.comment_type = '';
 731  
 732          args = $.extend(args, {
 733              'action': 'fetch-list',
 734              'list_args': list_args,
 735              '_ajax_fetch_list_nonce': $('#_ajax_fetch_list_nonce').val()
 736          });
 737  
 738          $.ajax({
 739              url: ajaxurl,
 740              global: false,
 741              dataType: 'json',
 742              data: args,
 743              success: function(response) {
 744                  theExtraList.get(0).wpList.add( response.rows );
 745              }
 746          });
 747      };
 748  
 749      /**
 750       * Globally available jQuery object referring to the extra comments list.
 751       *
 752       * @global
 753       */
 754      window.theExtraList = $('#the-extra-comment-list').wpList( { alt: '', delColor: 'none', addColor: 'none' } );
 755  
 756      /**
 757       * Globally available jQuery object referring to the comments list.
 758       *
 759       * @global
 760       */
 761      window.theList = $('#the-comment-list').wpList( { alt: '', delBefore: delBefore, dimAfter: dimAfter, delAfter: delAfter, addColor: 'none' } )
 762          .bind('wpListDelEnd', function(e, s){
 763              var wpListsData = $(s.target).attr('data-wp-lists'), id = s.element.replace(/[^0-9]+/g, '');
 764  
 765              if ( wpListsData.indexOf(':trash=1') != -1 || wpListsData.indexOf(':spam=1') != -1 )
 766                  $('#undo-' + id).fadeIn(300, function(){ $(this).show(); });
 767          });
 768  };
 769  
 770  /**
 771   * Object containing functionality regarding the comment quick editor and reply
 772   * editor.
 773   *
 774   * @since 2.7.0
 775   *
 776   * @global
 777   */
 778  window.commentReply = {
 779      cid : '',
 780      act : '',
 781      originalContent : '',
 782  
 783      /**
 784       * Initializes the comment reply functionality.
 785       *
 786       * @since 2.7.0
 787       *
 788       * @memberof commentReply
 789       */
 790      init : function() {
 791          var row = $('#replyrow');
 792  
 793          $( '.cancel', row ).click( function() { return commentReply.revert(); } );
 794          $( '.save', row ).click( function() { return commentReply.send(); } );
 795          $( 'input#author-name, input#author-email, input#author-url', row ).keypress( function( e ) {
 796              if ( e.which == 13 ) {
 797                  commentReply.send();
 798                  e.preventDefault();
 799                  return false;
 800              }
 801          });
 802  
 803          // Add events.
 804          $('#the-comment-list .column-comment > p').dblclick(function(){
 805              commentReply.toggle($(this).parent());
 806          });
 807  
 808          $('#doaction, #doaction2, #post-query-submit').click(function(){
 809              if ( $('#the-comment-list #replyrow').length > 0 )
 810                  commentReply.close();
 811          });
 812  
 813          this.comments_listing = $('#comments-form > input[name="comment_status"]').val() || '';
 814      },
 815  
 816      /**
 817       * Adds doubleclick event handler to the given comment list row.
 818       *
 819       * The double-click event will toggle the comment edit or reply form.
 820       *
 821       * @since 2.7.0
 822       *
 823       * @memberof commentReply
 824       *
 825       * @param {Object} r The row to add double click handlers to.
 826       *
 827       * @return {void}
 828       */
 829      addEvents : function(r) {
 830          r.each(function() {
 831              $(this).find('.column-comment > p').dblclick(function(){
 832                  commentReply.toggle($(this).parent());
 833              });
 834          });
 835      },
 836  
 837      /**
 838       * Opens the quick edit for the given element.
 839       *
 840       * @since 2.7.0
 841       *
 842       * @memberof commentReply
 843       *
 844       * @param {HTMLElement} el The element you want to open the quick editor for.
 845       *
 846       * @return {void}
 847       */
 848      toggle : function(el) {
 849          if ( 'none' !== $( el ).css( 'display' ) && ( $( '#replyrow' ).parent().is('#com-reply') || window.confirm( adminCommentsL10n.warnQuickEdit ) ) ) {
 850              $( el ).find( 'button.vim-q' ).click();
 851          }
 852      },
 853  
 854      /**
 855       * Closes the comment quick edit or reply form and undoes any changes.
 856       *
 857       * @since 2.7.0
 858       *
 859       * @memberof commentReply
 860       *
 861       * @return {void}
 862       */
 863      revert : function() {
 864  
 865          if ( $('#the-comment-list #replyrow').length < 1 )
 866              return false;
 867  
 868          $('#replyrow').fadeOut('fast', function(){
 869              commentReply.close();
 870          });
 871      },
 872  
 873      /**
 874       * Closes the comment quick edit or reply form and undoes any changes.
 875       *
 876       * @since 2.7.0
 877       *
 878       * @memberof commentReply
 879       *
 880       * @return {void}
 881       */
 882      close : function() {
 883          var commentRow = $(),
 884              replyRow = $( '#replyrow' );
 885  
 886          // Return if the replyrow is not showing.
 887          if ( replyRow.parent().is( '#com-reply' ) ) {
 888              return;
 889          }
 890  
 891          if ( this.cid ) {
 892              commentRow = $( '#comment-' + this.cid );
 893          }
 894  
 895          /*
 896           * When closing the Quick Edit form, show the comment row and move focus
 897           * back to the Quick Edit button.
 898           */
 899          if ( 'edit-comment' === this.act ) {
 900              commentRow.fadeIn( 300, function() {
 901                  commentRow
 902                      .show()
 903                      .find( '.vim-q' )
 904                          .attr( 'aria-expanded', 'false' )
 905                          .focus();
 906              } ).css( 'backgroundColor', '' );
 907          }
 908  
 909          // When closing the Reply form, move focus back to the Reply button.
 910          if ( 'replyto-comment' === this.act ) {
 911              commentRow.find( '.vim-r' )
 912                  .attr( 'aria-expanded', 'false' )
 913                  .focus();
 914          }
 915  
 916          // Reset the Quicktags buttons.
 917           if ( typeof QTags != 'undefined' )
 918              QTags.closeAllTags('replycontent');
 919  
 920          $('#add-new-comment').css('display', '');
 921  
 922          replyRow.hide();
 923          $( '#com-reply' ).append( replyRow );
 924          $('#replycontent').css('height', '').val('');
 925          $('#edithead input').val('');
 926          $( '.notice-error', replyRow )
 927              .addClass( 'hidden' )
 928              .find( '.error' ).empty();
 929          $( '.spinner', replyRow ).removeClass( 'is-active' );
 930  
 931          this.cid = '';
 932          this.originalContent = '';
 933      },
 934  
 935      /**
 936       * Opens the comment quick edit or reply form.
 937       *
 938       * @since 2.7.0
 939       *
 940       * @memberof commentReply
 941       *
 942       * @param {number} comment_id The comment ID to open an editor for.
 943       * @param {number} post_id The post ID to open an editor for.
 944       * @param {string} action The action to perform. Either 'edit' or 'replyto'.
 945       *
 946       * @return {boolean} Always false.
 947       */
 948      open : function(comment_id, post_id, action) {
 949          var editRow, rowData, act, replyButton, editHeight,
 950              t = this,
 951              c = $('#comment-' + comment_id),
 952              h = c.height(),
 953              colspanVal = 0;
 954  
 955          if ( ! this.discardCommentChanges() ) {
 956              return false;
 957          }
 958  
 959          t.close();
 960          t.cid = comment_id;
 961  
 962          editRow = $('#replyrow');
 963          rowData = $('#inline-'+comment_id);
 964          action = action || 'replyto';
 965          act = 'edit' == action ? 'edit' : 'replyto';
 966          act = t.act = act + '-comment';
 967          t.originalContent = $('textarea.comment', rowData).val();
 968          colspanVal = $( '> th:visible, > td:visible', c ).length;
 969  
 970          // Make sure it's actually a table and there's a `colspan` value to apply.
 971          if ( editRow.hasClass( 'inline-edit-row' ) && 0 !== colspanVal ) {
 972              $( 'td', editRow ).attr( 'colspan', colspanVal );
 973          }
 974  
 975          $('#action', editRow).val(act);
 976          $('#comment_post_ID', editRow).val(post_id);
 977          $('#comment_ID', editRow).val(comment_id);
 978  
 979          if ( action == 'edit' ) {
 980              $( '#author-name', editRow ).val( $( 'div.author', rowData ).text() );
 981              $('#author-email', editRow).val( $('div.author-email', rowData).text() );
 982              $('#author-url', editRow).val( $('div.author-url', rowData).text() );
 983              $('#status', editRow).val( $('div.comment_status', rowData).text() );
 984              $('#replycontent', editRow).val( $('textarea.comment', rowData).val() );
 985              $( '#edithead, #editlegend, #savebtn', editRow ).show();
 986              $('#replyhead, #replybtn, #addhead, #addbtn', editRow).hide();
 987  
 988              if ( h > 120 ) {
 989                  // Limit the maximum height when editing very long comments to make it more manageable.
 990                  // The textarea is resizable in most browsers, so the user can adjust it if needed.
 991                  editHeight = h > 500 ? 500 : h;
 992                  $('#replycontent', editRow).css('height', editHeight + 'px');
 993              }
 994  
 995              c.after( editRow ).fadeOut('fast', function(){
 996                  $('#replyrow').fadeIn(300, function(){ $(this).show(); });
 997              });
 998          } else if ( action == 'add' ) {
 999              $('#addhead, #addbtn', editRow).show();
1000              $( '#replyhead, #replybtn, #edithead, #editlegend, #savebtn', editRow ) .hide();
1001              $('#the-comment-list').prepend(editRow);
1002              $('#replyrow').fadeIn(300);
1003          } else {
1004              replyButton = $('#replybtn', editRow);
1005              $( '#edithead, #editlegend, #savebtn, #addhead, #addbtn', editRow ).hide();
1006              $('#replyhead, #replybtn', editRow).show();
1007              c.after(editRow);
1008  
1009              if ( c.hasClass('unapproved') ) {
1010                  replyButton.text(adminCommentsL10n.replyApprove);
1011              } else {
1012                  replyButton.text(adminCommentsL10n.reply);
1013              }
1014  
1015              $('#replyrow').fadeIn(300, function(){ $(this).show(); });
1016          }
1017  
1018          setTimeout(function() {
1019              var rtop, rbottom, scrollTop, vp, scrollBottom;
1020  
1021              rtop = $('#replyrow').offset().top;
1022              rbottom = rtop + $('#replyrow').height();
1023              scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1024              vp = document.documentElement.clientHeight || window.innerHeight || 0;
1025              scrollBottom = scrollTop + vp;
1026  
1027              if ( scrollBottom - 20 < rbottom )
1028                  window.scroll(0, rbottom - vp + 35);
1029              else if ( rtop - 20 < scrollTop )
1030                  window.scroll(0, rtop - 35);
1031  
1032              $('#replycontent').focus().keyup(function(e){
1033                  if ( e.which == 27 )
1034                      commentReply.revert(); // Close on Escape.
1035              });
1036          }, 600);
1037  
1038          return false;
1039      },
1040  
1041      /**
1042       * Submits the comment quick edit or reply form.
1043       *
1044       * @since 2.7.0
1045       *
1046       * @memberof commentReply
1047       *
1048       * @return {void}
1049       */
1050      send : function() {
1051          var post = {},
1052              $errorNotice = $( '#replysubmit .error-notice' );
1053  
1054          $errorNotice.addClass( 'hidden' );
1055          $( '#replysubmit .spinner' ).addClass( 'is-active' );
1056  
1057          $('#replyrow input').not(':button').each(function() {
1058              var t = $(this);
1059              post[ t.attr('name') ] = t.val();
1060          });
1061  
1062          post.content = $('#replycontent').val();
1063          post.id = post.comment_post_ID;
1064          post.comments_listing = this.comments_listing;
1065          post.p = $('[name="p"]').val();
1066  
1067          if ( $('#comment-' + $('#comment_ID').val()).hasClass('unapproved') )
1068              post.approve_parent = 1;
1069  
1070          $.ajax({
1071              type : 'POST',
1072              url : ajaxurl,
1073              data : post,
1074              success : function(x) { commentReply.show(x); },
1075              error : function(r) { commentReply.error(r); }
1076          });
1077      },
1078  
1079      /**
1080       * Shows the new or updated comment or reply.
1081       *
1082       * This function needs to be passed the ajax result as received from the server.
1083       * It will handle the response and show the comment that has just been saved to
1084       * the server.
1085       *
1086       * @since 2.7.0
1087       *
1088       * @memberof commentReply
1089       *
1090       * @param {Object} xml Ajax response object.
1091       *
1092       * @return {void}
1093       */
1094      show : function(xml) {
1095          var t = this, r, c, id, bg, pid;
1096  
1097          if ( typeof(xml) == 'string' ) {
1098              t.error({'responseText': xml});
1099              return false;
1100          }
1101  
1102          r = wpAjax.parseAjaxResponse(xml);
1103          if ( r.errors ) {
1104              t.error({'responseText': wpAjax.broken});
1105              return false;
1106          }
1107  
1108          t.revert();
1109  
1110          r = r.responses[0];
1111          id = '#comment-' + r.id;
1112  
1113          if ( 'edit-comment' == t.act )
1114              $(id).remove();
1115  
1116          if ( r.supplemental.parent_approved ) {
1117              pid = $('#comment-' + r.supplemental.parent_approved);
1118              updatePending( -1, r.supplemental.parent_post_id );
1119  
1120              if ( this.comments_listing == 'moderated' ) {
1121                  pid.animate( { 'backgroundColor':'#CCEEBB' }, 400, function(){
1122                      pid.fadeOut();
1123                  });
1124                  return;
1125              }
1126          }
1127  
1128          if ( r.supplemental.i18n_comments_text ) {
1129              updateDashboardText( r.supplemental );
1130              updateInModerationText( r.supplemental );
1131              updateApproved( 1, r.supplemental.parent_post_id );
1132              updateCountText( 'span.all-count', 1 );
1133          }
1134  
1135          c = $.trim(r.data); // Trim leading whitespaces.
1136          $(c).hide();
1137          $('#replyrow').after(c);
1138  
1139          id = $(id);
1140          t.addEvents(id);
1141          bg = id.hasClass('unapproved') ? '#FFFFE0' : id.closest('.widefat, .postbox').css('backgroundColor');
1142  
1143          id.animate( { 'backgroundColor':'#CCEEBB' }, 300 )
1144              .animate( { 'backgroundColor': bg }, 300, function() {
1145                  if ( pid && pid.length ) {
1146                      pid.animate( { 'backgroundColor':'#CCEEBB' }, 300 )
1147                          .animate( { 'backgroundColor': bg }, 300 )
1148                          .removeClass('unapproved').addClass('approved')
1149                          .find('div.comment_status').html('1');
1150                  }
1151              });
1152  
1153      },
1154  
1155      /**
1156       * Shows an error for the failed comment update or reply.
1157       *
1158       * @since 2.7.0
1159       *
1160       * @memberof commentReply
1161       *
1162       * @param {string} r The Ajax response.
1163       *
1164       * @return {void}
1165       */
1166      error : function(r) {
1167          var er = r.statusText,
1168              $errorNotice = $( '#replysubmit .notice-error' ),
1169              $error = $errorNotice.find( '.error' );
1170  
1171          $( '#replysubmit .spinner' ).removeClass( 'is-active' );
1172  
1173          if ( r.responseText )
1174              er = r.responseText.replace( /<.[^<>]*?>/g, '' );
1175  
1176          if ( er ) {
1177              $errorNotice.removeClass( 'hidden' );
1178              $error.html( er );
1179          }
1180      },
1181  
1182      /**
1183       * Opens the add comments form in the comments metabox on the post edit page.
1184       *
1185       * @since 3.4.0
1186       *
1187       * @memberof commentReply
1188       *
1189       * @param {number} post_id The post ID.
1190       *
1191       * @return {void}
1192       */
1193      addcomment: function(post_id) {
1194          var t = this;
1195  
1196          $('#add-new-comment').fadeOut(200, function(){
1197              t.open(0, post_id, 'add');
1198              $('table.comments-box').css('display', '');
1199              $('#no-comments').remove();
1200          });
1201      },
1202  
1203      /**
1204       * Alert the user if they have unsaved changes on a comment that will be lost if
1205       * they proceed with the intended action.
1206       *
1207       * @since 4.6.0
1208       *
1209       * @memberof commentReply
1210       *
1211       * @return {boolean} Whether it is safe the continue with the intended action.
1212       */
1213      discardCommentChanges: function() {
1214          var editRow = $( '#replyrow' );
1215  
1216          if  ( this.originalContent === $( '#replycontent', editRow ).val() ) {
1217              return true;
1218          }
1219  
1220          return window.confirm( adminCommentsL10n.warnCommentChanges );
1221      }
1222  };
1223  
1224  $(document).ready(function(){
1225      var make_hotkeys_redirect, edit_comment, toggle_all, make_bulk;
1226  
1227      setCommentsList();
1228      commentReply.init();
1229  
1230      $(document).on( 'click', 'span.delete a.delete', function( e ) {
1231          e.preventDefault();
1232      });
1233  
1234      if ( typeof $.table_hotkeys != 'undefined' ) {
1235          /**
1236           * Creates a function that navigates to a previous or next page.
1237           *
1238           * @since 2.7.0
1239           * @access private
1240           *
1241           * @param {string} which What page to navigate to: either next or prev.
1242           *
1243           * @return {Function} The function that executes the navigation.
1244           */
1245          make_hotkeys_redirect = function(which) {
1246              return function() {
1247                  var first_last, l;
1248  
1249                  first_last = 'next' == which? 'first' : 'last';
1250                  l = $('.tablenav-pages .'+which+'-page:not(.disabled)');
1251                  if (l.length)
1252                      window.location = l[0].href.replace(/\&hotkeys_highlight_(first|last)=1/g, '')+'&hotkeys_highlight_'+first_last+'=1';
1253              };
1254          };
1255  
1256          /**
1257           * Navigates to the edit page for the selected comment.
1258           *
1259           * @since 2.7.0
1260           * @access private
1261           *
1262           * @param {Object} event       The event that triggered this action.
1263           * @param {Object} current_row A jQuery object of the selected row.
1264           *
1265           * @return {void}
1266           */
1267          edit_comment = function(event, current_row) {
1268              window.location = $('span.edit a', current_row).attr('href');
1269          };
1270  
1271          /**
1272           * Toggles all comments on the screen, for bulk actions.
1273           *
1274           * @since 2.7.0
1275           * @access private
1276           *
1277           * @return {void}
1278           */
1279          toggle_all = function() {
1280              $('#cb-select-all-1').data( 'wp-toggle', 1 ).trigger( 'click' ).removeData( 'wp-toggle' );
1281          };
1282  
1283          /**
1284           * Creates a bulk action function that is executed on all selected comments.
1285           *
1286           * @since 2.7.0
1287           * @access private
1288           *
1289           * @param {string} value The name of the action to execute.
1290           *
1291           * @return {Function} The function that executes the bulk action.
1292           */
1293          make_bulk = function(value) {
1294              return function() {
1295                  var scope = $('select[name="action"]');
1296                  $('option[value="' + value + '"]', scope).prop('selected', true);
1297                  $('#doaction').click();
1298              };
1299          };
1300  
1301          $.table_hotkeys(
1302              $('table.widefat'),
1303              [
1304                  'a', 'u', 's', 'd', 'r', 'q', 'z',
1305                  ['e', edit_comment],
1306                  ['shift+x', toggle_all],
1307                  ['shift+a', make_bulk('approve')],
1308                  ['shift+s', make_bulk('spam')],
1309                  ['shift+d', make_bulk('delete')],
1310                  ['shift+t', make_bulk('trash')],
1311                  ['shift+z', make_bulk('untrash')],
1312                  ['shift+u', make_bulk('unapprove')]
1313              ],
1314              {
1315                  highlight_first: adminCommentsL10n.hotkeys_highlight_first,
1316                  highlight_last: adminCommentsL10n.hotkeys_highlight_last,
1317                  prev_page_link_cb: make_hotkeys_redirect('prev'),
1318                  next_page_link_cb: make_hotkeys_redirect('next'),
1319                  hotkeys_opts: {
1320                      disableInInput: true,
1321                      type: 'keypress',
1322                      noDisable: '.check-column input[type="checkbox"]'
1323                  },
1324                  cycle_expr: '#the-comment-list tr',
1325                  start_row_index: 0
1326              }
1327          );
1328      }
1329  
1330      // Quick Edit and Reply have an inline comment editor.
1331      $( '#the-comment-list' ).on( 'click', '.comment-inline', function() {
1332          var $el = $( this ),
1333              action = 'replyto';
1334  
1335          if ( 'undefined' !== typeof $el.data( 'action' ) ) {
1336              action = $el.data( 'action' );
1337          }
1338  
1339          $( this ).attr( 'aria-expanded', 'true' );
1340          commentReply.open( $el.data( 'commentId' ), $el.data( 'postId' ), action );
1341      } );
1342  });
1343  
1344  })(jQuery);


Generated: Sat Jul 4 01:00:03 2020 Cross-referenced by PHPXref 0.7.1