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