[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

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          // the order of these checks is important
 500          // .unspam can also have .approve or .unapprove
 501          // .untrash can also have .approve or .unapprove
 502  
 503          if ( targetParent.is( 'span.undo' ) ) {
 504              // the comment was spammed
 505              if ( targetParent.hasClass( 'unspam' ) ) {
 506                  spamDiff = -1;
 507  
 508                  if ( 'trash' === commentStatus ) {
 509                      trashDiff = 1;
 510                  } else if ( '1' === commentStatus ) {
 511                      approvedDiff = 1;
 512                  } else if ( '0' === commentStatus ) {
 513                      pendingDiff = 1;
 514                  }
 515  
 516              // the comment was trashed
 517              } else if ( targetParent.hasClass( 'untrash' ) ) {
 518                  trashDiff = -1;
 519  
 520                  if ( 'spam' === commentStatus ) {
 521                      spamDiff = 1;
 522                  } else if ( '1' === commentStatus ) {
 523                      approvedDiff = 1;
 524                  } else if ( '0' === commentStatus ) {
 525                      pendingDiff = 1;
 526                  }
 527              }
 528  
 529              undoing = true;
 530  
 531          // user clicked "Spam"
 532          } else if ( targetParent.is( 'span.spam' ) ) {
 533              // the comment is currently approved
 534              if ( approved ) {
 535                  approvedDiff = -1;
 536              // the comment is currently pending
 537              } else if ( unapproved ) {
 538                  pendingDiff = -1;
 539              // the comment was in the trash
 540              } else if ( trashed ) {
 541                  trashDiff = -1;
 542              }
 543              // you can't spam an item on the spam screen
 544              spamDiff = 1;
 545  
 546          // user clicked "Unspam"
 547          } else if ( targetParent.is( 'span.unspam' ) ) {
 548              if ( approved ) {
 549                  pendingDiff = 1;
 550              } else if ( unapproved ) {
 551                  approvedDiff = 1;
 552              } else if ( trashed ) {
 553                  // the comment was previously approved
 554                  if ( targetParent.hasClass( 'approve' ) ) {
 555                      approvedDiff = 1;
 556                  // the comment was previously pending
 557                  } else if ( targetParent.hasClass( 'unapprove' ) ) {
 558                      pendingDiff = 1;
 559                  }
 560              } else if ( spammed ) {
 561                  if ( targetParent.hasClass( 'approve' ) ) {
 562                      approvedDiff = 1;
 563  
 564                  } else if ( targetParent.hasClass( 'unapprove' ) ) {
 565                      pendingDiff = 1;
 566                  }
 567              }
 568              // you can Unspam an item on the spam screen
 569              spamDiff = -1;
 570  
 571          // user clicked "Trash"
 572          } else if ( targetParent.is( 'span.trash' ) ) {
 573              if ( approved ) {
 574                  approvedDiff = -1;
 575              } else if ( unapproved ) {
 576                  pendingDiff = -1;
 577              // the comment was in the spam queue
 578              } else if ( spammed ) {
 579                  spamDiff = -1;
 580              }
 581              // you can't trash an item on the trash screen
 582              trashDiff = 1;
 583  
 584          // user clicked "Restore"
 585          } else if ( targetParent.is( 'span.untrash' ) ) {
 586              if ( approved ) {
 587                  pendingDiff = 1;
 588              } else if ( unapproved ) {
 589                  approvedDiff = 1;
 590              } else if ( trashed ) {
 591                  if ( targetParent.hasClass( 'approve' ) ) {
 592                      approvedDiff = 1;
 593                  } else if ( targetParent.hasClass( 'unapprove' ) ) {
 594                      pendingDiff = 1;
 595                  }
 596              }
 597              // you can't go from trash to spam
 598              // you can untrash on the trash screen
 599              trashDiff = -1;
 600  
 601          // User clicked "Approve"
 602          } else if ( targetParent.is( 'span.approve:not(.unspam):not(.untrash)' ) ) {
 603              approvedDiff = 1;
 604              pendingDiff = -1;
 605  
 606          // User clicked "Unapprove"
 607          } else if ( targetParent.is( 'span.unapprove:not(.unspam):not(.untrash)' ) ) {
 608              approvedDiff = -1;
 609              pendingDiff = 1;
 610  
 611          // User clicked "Delete Permanently"
 612          } else if ( targetParent.is( 'span.delete' ) ) {
 613              if ( spammed ) {
 614                  spamDiff = -1;
 615              } else if ( trashed ) {
 616                  trashDiff = -1;
 617              }
 618          }
 619  
 620          if ( pendingDiff ) {
 621              updatePending( pendingDiff, commentPostId );
 622              updateCountText( 'span.all-count', pendingDiff );
 623          }
 624  
 625          if ( approvedDiff ) {
 626              updateApproved( approvedDiff, commentPostId );
 627              updateCountText( 'span.all-count', approvedDiff );
 628          }
 629  
 630          if ( spamDiff ) {
 631              updateCountText( 'span.spam-count', spamDiff );
 632          }
 633  
 634          if ( trashDiff ) {
 635              updateCountText( 'span.trash-count', trashDiff );
 636          }
 637  
 638          if (
 639              ( ( 'trash' === settings.data.comment_status ) && !getCount( $( 'span.trash-count' ) ) ) ||
 640              ( ( 'spam' === settings.data.comment_status ) && !getCount( $( 'span.spam-count' ) ) )
 641          ) {
 642              $( '#delete_all' ).hide();
 643          }
 644  
 645          if ( ! isDashboard ) {
 646              total = totalInput.val() ? parseInt( totalInput.val(), 10 ) : 0;
 647              if ( $(settings.target).parent().is('span.undo') )
 648                  total++;
 649              else
 650                  total--;
 651  
 652              if ( total < 0 )
 653                  total = 0;
 654  
 655              if ( 'object' === typeof r ) {
 656                  if ( response.supplemental.total_items_i18n && lastConfidentTime < response.supplemental.time ) {
 657                      total_items_i18n = response.supplemental.total_items_i18n || '';
 658                      if ( total_items_i18n ) {
 659                          $('.displaying-num').text( total_items_i18n.replace( '&nbsp;', String.fromCharCode( 160 ) ) );
 660                          $('.total-pages').text( response.supplemental.total_pages_i18n.replace( '&nbsp;', String.fromCharCode( 160 ) ) );
 661                          $('.tablenav-pages').find('.next-page, .last-page').toggleClass('disabled', response.supplemental.total_pages == $('.current-page').val());
 662                      }
 663                      updateTotalCount( total, response.supplemental.time, true );
 664                  } else if ( response.supplemental.time ) {
 665                      updateTotalCount( total, response.supplemental.time, false );
 666                  }
 667              } else {
 668                  updateTotalCount( total, r, false );
 669              }
 670          }
 671  
 672          if ( ! theExtraList || theExtraList.length === 0 || theExtraList.children().length === 0 || undoing ) {
 673              return;
 674          }
 675  
 676          theList.get(0).wpList.add( theExtraList.children( ':eq(0):not(.no-items)' ).remove().clone() );
 677  
 678          refillTheExtraList();
 679  
 680          animated = $( ':animated', '#the-comment-list' );
 681          animatedCallback = function() {
 682              if ( ! $( '#the-comment-list tr:visible' ).length ) {
 683                  theList.get(0).wpList.add( theExtraList.find( '.no-items' ).clone() );
 684              }
 685          };
 686  
 687          if ( animated.length ) {
 688              animated.promise().done( animatedCallback );
 689          } else {
 690              animatedCallback();
 691          }
 692      };
 693  
 694      /**
 695       * Retrieves additional comments to populate the extra list.
 696       *
 697       * @since 3.1.0
 698       * @access private
 699       *
 700       * @param {boolean} [ev] Repopulate the extra comments list if true.
 701       *
 702       * @return {void}
 703       */
 704      refillTheExtraList = function(ev) {
 705          var args = $.query.get(), total_pages = $('.total-pages').text(), per_page = $('input[name="_per_page"]', '#comments-form').val();
 706  
 707          if (! args.paged)
 708              args.paged = 1;
 709  
 710          if (args.paged > total_pages) {
 711              return;
 712          }
 713  
 714          if (ev) {
 715              theExtraList.empty();
 716              args.number = Math.min(8, per_page); // see WP_Comments_List_Table::prepare_items() @ class-wp-comments-list-table.php
 717          } else {
 718              args.number = 1;
 719              args.offset = Math.min(8, per_page) - 1; // fetch only the next item on the extra list
 720          }
 721  
 722          args.no_placeholder = true;
 723  
 724          args.paged ++;
 725  
 726          // $.query.get() needs some correction to be sent into an ajax request
 727          if ( true === args.comment_type )
 728              args.comment_type = '';
 729  
 730          args = $.extend(args, {
 731              'action': 'fetch-list',
 732              'list_args': list_args,
 733              '_ajax_fetch_list_nonce': $('#_ajax_fetch_list_nonce').val()
 734          });
 735  
 736          $.ajax({
 737              url: ajaxurl,
 738              global: false,
 739              dataType: 'json',
 740              data: args,
 741              success: function(response) {
 742                  theExtraList.get(0).wpList.add( response.rows );
 743              }
 744          });
 745      };
 746  
 747      /**
 748       * Globally available jQuery object referring to the extra comments list.
 749       *
 750       * @global
 751       */
 752      window.theExtraList = $('#the-extra-comment-list').wpList( { alt: '', delColor: 'none', addColor: 'none' } );
 753  
 754      /**
 755       * Globally available jQuery object referring to the comments list.
 756       *
 757       * @global
 758       */
 759      window.theList = $('#the-comment-list').wpList( { alt: '', delBefore: delBefore, dimAfter: dimAfter, delAfter: delAfter, addColor: 'none' } )
 760          .bind('wpListDelEnd', function(e, s){
 761              var wpListsData = $(s.target).attr('data-wp-lists'), id = s.element.replace(/[^0-9]+/g, '');
 762  
 763              if ( wpListsData.indexOf(':trash=1') != -1 || wpListsData.indexOf(':spam=1') != -1 )
 764                  $('#undo-' + id).fadeIn(300, function(){ $(this).show(); });
 765          });
 766  };
 767  
 768  /**
 769   * Object containing functionality regarding the comment quick editor and reply
 770   * editor.
 771   *
 772   * @since 2.7.0
 773   *
 774   * @global
 775   */
 776  window.commentReply = {
 777      cid : '',
 778      act : '',
 779      originalContent : '',
 780  
 781      /**
 782       * Initializes the comment reply functionality.
 783       *
 784       * @memberof commentReply
 785       *
 786       * @since 2.7.0
 787       */
 788      init : function() {
 789          var row = $('#replyrow');
 790  
 791          $( '.cancel', row ).click( function() { return commentReply.revert(); } );
 792          $( '.save', row ).click( function() { return commentReply.send(); } );
 793          $( 'input#author-name, input#author-email, input#author-url', row ).keypress( function( e ) {
 794              if ( e.which == 13 ) {
 795                  commentReply.send();
 796                  e.preventDefault();
 797                  return false;
 798              }
 799          });
 800  
 801          // add events
 802          $('#the-comment-list .column-comment > p').dblclick(function(){
 803              commentReply.toggle($(this).parent());
 804          });
 805  
 806          $('#doaction, #doaction2, #post-query-submit').click(function(){
 807              if ( $('#the-comment-list #replyrow').length > 0 )
 808                  commentReply.close();
 809          });
 810  
 811          this.comments_listing = $('#comments-form > input[name="comment_status"]').val() || '';
 812      },
 813  
 814      /**
 815       * Adds doubleclick event handler to the given comment list row.
 816       *
 817       * The double-click event will toggle the comment edit or reply form.
 818       *
 819       * @since 2.7.0
 820       *
 821       * @memberof commentReply
 822       *
 823       * @param {Object} r The row to add double click handlers to.
 824       *
 825       * @return {void}
 826       */
 827      addEvents : function(r) {
 828          r.each(function() {
 829              $(this).find('.column-comment > p').dblclick(function(){
 830                  commentReply.toggle($(this).parent());
 831              });
 832          });
 833      },
 834  
 835      /**
 836       * Opens the quick edit for the given element.
 837       *
 838       * @since 2.7.0
 839       *
 840       * @memberof commentReply
 841       *
 842       * @param {HTMLElement} el The element you want to open the quick editor for.
 843       *
 844       * @return {void}
 845       */
 846      toggle : function(el) {
 847          if ( 'none' !== $( el ).css( 'display' ) && ( $( '#replyrow' ).parent().is('#com-reply') || window.confirm( adminCommentsL10n.warnQuickEdit ) ) ) {
 848              $( el ).find( 'button.vim-q' ).click();
 849          }
 850      },
 851  
 852      /**
 853       * Closes the comment quick edit or reply form and undoes any changes.
 854       *
 855       * @since 2.7.0
 856       *
 857       * @memberof commentReply
 858       *
 859       * @return {void}
 860       */
 861      revert : function() {
 862  
 863          if ( $('#the-comment-list #replyrow').length < 1 )
 864              return false;
 865  
 866          $('#replyrow').fadeOut('fast', function(){
 867              commentReply.close();
 868          });
 869      },
 870  
 871      /**
 872       * Closes the comment quick edit or reply form and undoes any changes.
 873       *
 874       * @since 2.7.0
 875       *
 876       * @memberof commentReply
 877       *
 878       * @return {void}
 879       */
 880      close : function() {
 881          var commentRow = $(),
 882              replyRow = $( '#replyrow' );
 883  
 884          // Return if the replyrow is not showing.
 885          if ( replyRow.parent().is( '#com-reply' ) ) {
 886              return;
 887          }
 888  
 889          if ( this.cid ) {
 890              commentRow = $( '#comment-' + this.cid );
 891          }
 892  
 893          /*
 894           * When closing the Quick Edit form, show the comment row and move focus
 895           * back to the Quick Edit button.
 896           */
 897          if ( 'edit-comment' === this.act ) {
 898              commentRow.fadeIn( 300, function() {
 899                  commentRow
 900                      .show()
 901                      .find( '.vim-q' )
 902                          .attr( 'aria-expanded', 'false' )
 903                          .focus();
 904              } ).css( 'backgroundColor', '' );
 905          }
 906  
 907          // When closing the Reply form, move focus back to the Reply button.
 908          if ( 'replyto-comment' === this.act ) {
 909              commentRow.find( '.vim-r' )
 910                  .attr( 'aria-expanded', 'false' )
 911                  .focus();
 912          }
 913  
 914          // reset the Quicktags buttons
 915           if ( typeof QTags != 'undefined' )
 916              QTags.closeAllTags('replycontent');
 917  
 918          $('#add-new-comment').css('display', '');
 919  
 920          replyRow.hide();
 921          $( '#com-reply' ).append( replyRow );
 922          $('#replycontent').css('height', '').val('');
 923          $('#edithead input').val('');
 924          $( '.notice-error', replyRow )
 925              .addClass( 'hidden' )
 926              .find( '.error' ).empty();
 927          $( '.spinner', replyRow ).removeClass( 'is-active' );
 928  
 929          this.cid = '';
 930          this.originalContent = '';
 931      },
 932  
 933      /**
 934       * Opens the comment quick edit or reply form.
 935       *
 936       * @since 2.7.0
 937       *
 938       * @memberof commentReply
 939       *
 940       * @param {number} comment_id The comment id to open an editor for.
 941       * @param {number} post_id The post id to open an editor for.
 942       * @param {string} action The action to perform. Either 'edit' or 'replyto'.
 943       *
 944       * @return {boolean} Always false.
 945       */
 946      open : function(comment_id, post_id, action) {
 947          var editRow, rowData, act, replyButton, editHeight,
 948              t = this,
 949              c = $('#comment-' + comment_id),
 950              h = c.height(),
 951              colspanVal = 0;
 952  
 953          if ( ! this.discardCommentChanges() ) {
 954              return false;
 955          }
 956  
 957          t.close();
 958          t.cid = comment_id;
 959  
 960          editRow = $('#replyrow');
 961          rowData = $('#inline-'+comment_id);
 962          action = action || 'replyto';
 963          act = 'edit' == action ? 'edit' : 'replyto';
 964          act = t.act = act + '-comment';
 965          t.originalContent = $('textarea.comment', rowData).val();
 966          colspanVal = $( '> th:visible, > td:visible', c ).length;
 967  
 968          // Make sure it's actually a table and there's a `colspan` value to apply.
 969          if ( editRow.hasClass( 'inline-edit-row' ) && 0 !== colspanVal ) {
 970              $( 'td', editRow ).attr( 'colspan', colspanVal );
 971          }
 972  
 973          $('#action', editRow).val(act);
 974          $('#comment_post_ID', editRow).val(post_id);
 975          $('#comment_ID', editRow).val(comment_id);
 976  
 977          if ( action == 'edit' ) {
 978              $( '#author-name', editRow ).val( $( 'div.author', rowData ).text() );
 979              $('#author-email', editRow).val( $('div.author-email', rowData).text() );
 980              $('#author-url', editRow).val( $('div.author-url', rowData).text() );
 981              $('#status', editRow).val( $('div.comment_status', rowData).text() );
 982              $('#replycontent', editRow).val( $('textarea.comment', rowData).val() );
 983              $( '#edithead, #editlegend, #savebtn', editRow ).show();
 984              $('#replyhead, #replybtn, #addhead, #addbtn', editRow).hide();
 985  
 986              if ( h > 120 ) {
 987                  // Limit the maximum height when editing very long comments to make it more manageable.
 988                  // The textarea is resizable in most browsers, so the user can adjust it if needed.
 989                  editHeight = h > 500 ? 500 : h;
 990                  $('#replycontent', editRow).css('height', editHeight + 'px');
 991              }
 992  
 993              c.after( editRow ).fadeOut('fast', function(){
 994                  $('#replyrow').fadeIn(300, function(){ $(this).show(); });
 995              });
 996          } else if ( action == 'add' ) {
 997              $('#addhead, #addbtn', editRow).show();
 998              $( '#replyhead, #replybtn, #edithead, #editlegend, #savebtn', editRow ) .hide();
 999              $('#the-comment-list').prepend(editRow);
1000              $('#replyrow').fadeIn(300);
1001          } else {
1002              replyButton = $('#replybtn', editRow);
1003              $( '#edithead, #editlegend, #savebtn, #addhead, #addbtn', editRow ).hide();
1004              $('#replyhead, #replybtn', editRow).show();
1005              c.after(editRow);
1006  
1007              if ( c.hasClass('unapproved') ) {
1008                  replyButton.text(adminCommentsL10n.replyApprove);
1009              } else {
1010                  replyButton.text(adminCommentsL10n.reply);
1011              }
1012  
1013              $('#replyrow').fadeIn(300, function(){ $(this).show(); });
1014          }
1015  
1016          setTimeout(function() {
1017              var rtop, rbottom, scrollTop, vp, scrollBottom;
1018  
1019              rtop = $('#replyrow').offset().top;
1020              rbottom = rtop + $('#replyrow').height();
1021              scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1022              vp = document.documentElement.clientHeight || window.innerHeight || 0;
1023              scrollBottom = scrollTop + vp;
1024  
1025              if ( scrollBottom - 20 < rbottom )
1026                  window.scroll(0, rbottom - vp + 35);
1027              else if ( rtop - 20 < scrollTop )
1028                  window.scroll(0, rtop - 35);
1029  
1030              $('#replycontent').focus().keyup(function(e){
1031                  if ( e.which == 27 )
1032                      commentReply.revert(); // close on Escape
1033              });
1034          }, 600);
1035  
1036          return false;
1037      },
1038  
1039      /**
1040       * Submits the comment quick edit or reply form.
1041       *
1042       * @since 2.7.0
1043       *
1044       * @memberof commentReply
1045       *
1046       * @return {void}
1047       */
1048      send : function() {
1049          var post = {},
1050              $errorNotice = $( '#replysubmit .error-notice' );
1051  
1052          $errorNotice.addClass( 'hidden' );
1053          $( '#replysubmit .spinner' ).addClass( 'is-active' );
1054  
1055          $('#replyrow input').not(':button').each(function() {
1056              var t = $(this);
1057              post[ t.attr('name') ] = t.val();
1058          });
1059  
1060          post.content = $('#replycontent').val();
1061          post.id = post.comment_post_ID;
1062          post.comments_listing = this.comments_listing;
1063          post.p = $('[name="p"]').val();
1064  
1065          if ( $('#comment-' + $('#comment_ID').val()).hasClass('unapproved') )
1066              post.approve_parent = 1;
1067  
1068          $.ajax({
1069              type : 'POST',
1070              url : ajaxurl,
1071              data : post,
1072              success : function(x) { commentReply.show(x); },
1073              error : function(r) { commentReply.error(r); }
1074          });
1075      },
1076  
1077      /**
1078       * Shows the new or updated comment or reply.
1079       *
1080       * This function needs to be passed the ajax result as received from the server.
1081       * It will handle the response and show the comment that has just been saved to
1082       * the server.
1083       *
1084       * @since 2.7.0
1085       *
1086       * @memberof commentReply
1087       *
1088       * @param {Object} xml Ajax response object.
1089       *
1090       * @return {void}
1091       */
1092      show : function(xml) {
1093          var t = this, r, c, id, bg, pid;
1094  
1095          if ( typeof(xml) == 'string' ) {
1096              t.error({'responseText': xml});
1097              return false;
1098          }
1099  
1100          r = wpAjax.parseAjaxResponse(xml);
1101          if ( r.errors ) {
1102              t.error({'responseText': wpAjax.broken});
1103              return false;
1104          }
1105  
1106          t.revert();
1107  
1108          r = r.responses[0];
1109          id = '#comment-' + r.id;
1110  
1111          if ( 'edit-comment' == t.act )
1112              $(id).remove();
1113  
1114          if ( r.supplemental.parent_approved ) {
1115              pid = $('#comment-' + r.supplemental.parent_approved);
1116              updatePending( -1, r.supplemental.parent_post_id );
1117  
1118              if ( this.comments_listing == 'moderated' ) {
1119                  pid.animate( { 'backgroundColor':'#CCEEBB' }, 400, function(){
1120                      pid.fadeOut();
1121                  });
1122                  return;
1123              }
1124          }
1125  
1126          if ( r.supplemental.i18n_comments_text ) {
1127              updateDashboardText( r.supplemental );
1128              updateInModerationText( r.supplemental );
1129              updateApproved( 1, r.supplemental.parent_post_id );
1130              updateCountText( 'span.all-count', 1 );
1131          }
1132  
1133          c = $.trim(r.data); // Trim leading whitespaces
1134          $(c).hide();
1135          $('#replyrow').after(c);
1136  
1137          id = $(id);
1138          t.addEvents(id);
1139          bg = id.hasClass('unapproved') ? '#FFFFE0' : id.closest('.widefat, .postbox').css('backgroundColor');
1140  
1141          id.animate( { 'backgroundColor':'#CCEEBB' }, 300 )
1142              .animate( { 'backgroundColor': bg }, 300, function() {
1143                  if ( pid && pid.length ) {
1144                      pid.animate( { 'backgroundColor':'#CCEEBB' }, 300 )
1145                          .animate( { 'backgroundColor': bg }, 300 )
1146                          .removeClass('unapproved').addClass('approved')
1147                          .find('div.comment_status').html('1');
1148                  }
1149              });
1150  
1151      },
1152  
1153      /**
1154       * Shows an error for the failed comment update or reply.
1155       *
1156       * @since 2.7.0
1157       *
1158       * @memberof commentReply
1159       *
1160       * @param {string} r The Ajax response.
1161       *
1162       * @return {void}
1163       */
1164      error : function(r) {
1165          var er = r.statusText,
1166              $errorNotice = $( '#replysubmit .notice-error' ),
1167              $error = $errorNotice.find( '.error' );
1168  
1169          $( '#replysubmit .spinner' ).removeClass( 'is-active' );
1170  
1171          if ( r.responseText )
1172              er = r.responseText.replace( /<.[^<>]*?>/g, '' );
1173  
1174          if ( er ) {
1175              $errorNotice.removeClass( 'hidden' );
1176              $error.html( er );
1177          }
1178      },
1179  
1180      /**
1181       * Opens the add comments form in the comments metabox on the post edit page.
1182       *
1183       * @since 3.4.0
1184       *
1185       * @memberof commentReply
1186       *
1187       * @param {number} post_id The post id.
1188       *
1189       * @return {void}
1190       */
1191      addcomment: function(post_id) {
1192          var t = this;
1193  
1194          $('#add-new-comment').fadeOut(200, function(){
1195              t.open(0, post_id, 'add');
1196              $('table.comments-box').css('display', '');
1197              $('#no-comments').remove();
1198          });
1199      },
1200  
1201      /**
1202       * Alert the user if they have unsaved changes on a comment that will be lost if
1203       * they proceed with the intended action.
1204       *
1205       * @since 4.6.0
1206       *
1207       * @memberof commentReply
1208       *
1209       * @return {boolean} Whether it is safe the continue with the intended action.
1210       */
1211      discardCommentChanges: function() {
1212          var editRow = $( '#replyrow' );
1213  
1214          if  ( this.originalContent === $( '#replycontent', editRow ).val() ) {
1215              return true;
1216          }
1217  
1218          return window.confirm( adminCommentsL10n.warnCommentChanges );
1219      }
1220  };
1221  
1222  $(document).ready(function(){
1223      var make_hotkeys_redirect, edit_comment, toggle_all, make_bulk;
1224  
1225      setCommentsList();
1226      commentReply.init();
1227  
1228      $(document).on( 'click', 'span.delete a.delete', function( e ) {
1229          e.preventDefault();
1230      });
1231  
1232      if ( typeof $.table_hotkeys != 'undefined' ) {
1233          /**
1234           * Creates a function that navigates to a previous or next page.
1235           *
1236           * @since 2.7.0
1237           * @access private
1238           *
1239           * @param {string} which What page to navigate to: either next or prev.
1240           *
1241           * @return {Function} The function that executes the navigation.
1242           */
1243          make_hotkeys_redirect = function(which) {
1244              return function() {
1245                  var first_last, l;
1246  
1247                  first_last = 'next' == which? 'first' : 'last';
1248                  l = $('.tablenav-pages .'+which+'-page:not(.disabled)');
1249                  if (l.length)
1250                      window.location = l[0].href.replace(/\&hotkeys_highlight_(first|last)=1/g, '')+'&hotkeys_highlight_'+first_last+'=1';
1251              };
1252          };
1253  
1254          /**
1255           * Navigates to the edit page for the selected comment.
1256           *
1257           * @since 2.7.0
1258           * @access private
1259           *
1260           * @param {Object} event       The event that triggered this action.
1261           * @param {Object} current_row A jQuery object of the selected row.
1262           *
1263           * @return {void}
1264           */
1265          edit_comment = function(event, current_row) {
1266              window.location = $('span.edit a', current_row).attr('href');
1267          };
1268  
1269          /**
1270           * Toggles all comments on the screen, for bulk actions.
1271           *
1272           * @since 2.7.0
1273           * @access private
1274           *
1275           * @return {void}
1276           */
1277          toggle_all = function() {
1278              $('#cb-select-all-1').data( 'wp-toggle', 1 ).trigger( 'click' ).removeData( 'wp-toggle' );
1279          };
1280  
1281          /**
1282           * Creates a bulk action function that is executed on all selected comments.
1283           *
1284           * @since 2.7.0
1285           * @access private
1286           *
1287           * @param {string} value The name of the action to execute.
1288           *
1289           * @return {Function} The function that executes the bulk action.
1290           */
1291          make_bulk = function(value) {
1292              return function() {
1293                  var scope = $('select[name="action"]');
1294                  $('option[value="' + value + '"]', scope).prop('selected', true);
1295                  $('#doaction').click();
1296              };
1297          };
1298  
1299          $.table_hotkeys(
1300              $('table.widefat'),
1301              [
1302                  'a', 'u', 's', 'd', 'r', 'q', 'z',
1303                  ['e', edit_comment],
1304                  ['shift+x', toggle_all],
1305                  ['shift+a', make_bulk('approve')],
1306                  ['shift+s', make_bulk('spam')],
1307                  ['shift+d', make_bulk('delete')],
1308                  ['shift+t', make_bulk('trash')],
1309                  ['shift+z', make_bulk('untrash')],
1310                  ['shift+u', make_bulk('unapprove')]
1311              ],
1312              {
1313                  highlight_first: adminCommentsL10n.hotkeys_highlight_first,
1314                  highlight_last: adminCommentsL10n.hotkeys_highlight_last,
1315                  prev_page_link_cb: make_hotkeys_redirect('prev'),
1316                  next_page_link_cb: make_hotkeys_redirect('next'),
1317                  hotkeys_opts: {
1318                      disableInInput: true,
1319                      type: 'keypress',
1320                      noDisable: '.check-column input[type="checkbox"]'
1321                  },
1322                  cycle_expr: '#the-comment-list tr',
1323                  start_row_index: 0
1324              }
1325          );
1326      }
1327  
1328      // Quick Edit and Reply have an inline comment editor.
1329      $( '#the-comment-list' ).on( 'click', '.comment-inline', function() {
1330          var $el = $( this ),
1331              action = 'replyto';
1332  
1333          if ( 'undefined' !== typeof $el.data( 'action' ) ) {
1334              action = $el.data( 'action' );
1335          }
1336  
1337          $( this ).attr( 'aria-expanded', 'true' );
1338          commentReply.open( $el.data( 'commentId' ), $el.data( 'postId' ), action );
1339      } );
1340  });
1341  
1342  })(jQuery);


Generated: Fri Oct 25 08:20:01 2019 Cross-referenced by PHPXref 0.7