run:R W Run
DIR
2026-03-11 16:18:51
R W Run
2.86 KB
2026-03-11 16:18:51
R W Run
758 By
2026-03-11 16:18:51
R W Run
6.24 KB
2026-03-11 16:18:51
R W Run
2.95 KB
2026-03-11 16:18:51
R W Run
5.66 KB
2026-03-11 16:18:51
R W Run
2.04 KB
2026-03-11 16:18:51
R W Run
11.32 KB
2026-03-11 16:18:51
R W Run
3.01 KB
2026-03-11 16:18:51
R W Run
9.54 KB
2026-03-11 16:18:51
R W Run
3.4 KB
2026-03-11 16:18:51
R W Run
2.85 KB
2026-03-11 16:18:51
R W Run
1.28 KB
2026-03-11 16:18:51
R W Run
61.15 KB
2026-03-11 16:18:51
R W Run
23.12 KB
2026-03-11 16:18:51
R W Run
3.35 KB
2026-03-11 16:18:51
R W Run
1.18 KB
2026-03-11 16:18:51
R W Run
1.98 KB
2026-03-11 16:18:51
R W Run
288.41 KB
2026-03-11 16:18:51
R W Run
109.69 KB
2026-03-11 16:18:51
R W Run
111.46 KB
2026-03-11 16:18:51
R W Run
47.14 KB
2026-03-11 16:18:51
R W Run
70.05 KB
2026-03-11 16:18:51
R W Run
27.41 KB
2026-03-11 16:18:51
R W Run
27.02 KB
2026-03-11 16:18:51
R W Run
8.65 KB
2026-03-11 16:18:51
R W Run
37.12 KB
2026-03-11 16:18:51
R W Run
15.13 KB
2026-03-11 16:18:51
R W Run
41.61 KB
2026-03-11 16:18:51
R W Run
13.14 KB
2026-03-11 16:18:51
R W Run
44 KB
2026-03-11 16:18:51
R W Run
12.78 KB
2026-03-11 16:18:51
R W Run
7.67 KB
2026-03-11 16:18:51
R W Run
5.41 KB
2026-03-11 16:18:51
R W Run
3.65 KB
2026-03-11 16:18:51
R W Run
39.98 KB
2026-03-11 16:18:51
R W Run
15.15 KB
2026-03-11 16:18:51
R W Run
20.17 KB
2026-03-11 16:18:51
R W Run
9.41 KB
2026-03-11 16:18:51
R W Run
7.61 KB
2026-03-11 16:18:51
R W Run
2.93 KB
2026-03-11 16:18:51
R W Run
23.09 KB
2026-03-11 16:18:51
R W Run
890 By
2026-03-11 16:18:51
R W Run
423 By
2026-03-11 16:18:51
R W Run
3.89 KB
2026-03-11 16:18:51
R W Run
1.7 KB
2026-03-11 16:18:51
R W Run
1.27 KB
2026-03-11 16:18:51
R W Run
611 By
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
1.13 KB
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
2.38 KB
2026-03-11 16:18:51
R W Run
61.15 KB
2026-03-11 16:18:51
R W Run
30.06 KB
2026-03-11 16:18:51
R W Run
4.14 KB
2026-03-11 16:18:51
R W Run
1.1 KB
2026-03-11 16:18:51
R W Run
1.31 KB
2026-03-11 16:18:51
R W Run
847 By
2026-03-11 16:18:51
R W Run
6.92 KB
2026-03-11 16:18:51
R W Run
2.35 KB
2026-03-11 16:18:51
R W Run
38.68 KB
2026-03-11 16:18:51
R W Run
18.4 KB
2026-03-11 16:18:51
R W Run
18.49 KB
2026-03-11 16:18:51
R W Run
6.6 KB
2026-03-11 16:18:51
R W Run
10.67 KB
2026-03-11 16:18:51
R W Run
5.03 KB
2026-03-11 16:18:51
R W Run
33.92 KB
2026-03-11 16:18:51
R W Run
17.97 KB
2026-03-11 16:18:51
R W Run
876 By
2026-03-11 16:18:51
R W Run
620 By
2026-03-11 16:18:51
R W Run
13.15 KB
2026-03-11 16:18:51
R W Run
6.13 KB
2026-03-11 16:18:51
R W Run
6.1 KB
2026-03-11 16:18:51
R W Run
2.2 KB
2026-03-11 16:18:51
R W Run
3.2 KB
2026-03-11 16:18:51
R W Run
1.53 KB
2026-03-11 16:18:51
R W Run
10.88 KB
2026-03-11 16:18:51
R W Run
3 KB
2026-03-11 16:18:51
R W Run
5.64 KB
2026-03-11 16:18:51
R W Run
2.22 KB
2026-03-11 16:18:51
R W Run
5.96 KB
2026-03-11 16:18:51
R W Run
2.41 KB
2026-03-11 16:18:51
R W Run
24.77 KB
2026-03-11 16:18:51
R W Run
11.43 KB
2026-03-11 16:18:51
R W Run
54.94 KB
2026-03-11 16:18:51
R W Run
26.51 KB
2026-03-11 16:18:51
R W Run
109.37 KB
2026-03-11 16:18:51
R W Run
47.31 KB
2026-03-11 16:18:51
R W Run
17.91 KB
2026-03-11 16:18:51
R W Run
7.81 KB
2026-03-11 16:18:51
R W Run
2.25 KB
2026-03-11 16:18:51
R W Run
676 By
2026-03-11 16:18:51
R W Run
22.56 KB
2026-03-11 16:18:51
R W Run
12.31 KB
2026-03-11 16:18:51
R W Run
7.52 KB
2026-03-11 16:18:51
R W Run
1.49 KB
2026-03-11 16:18:51
R W Run
740 By
2026-03-11 16:18:51
R W Run
458 By
2026-03-11 16:18:51
R W Run
error_log
📄edit-comments.js
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 adminCommentsSettings, thousandsSeparator, list_args, QTags, ajaxurl, wpAjax */
10/* global commentReply, theExtraList, theList, setCommentsList */
11
12(function($) {
13var getCount, updateCount, updateCountText, updatePending, updateApproved,
14 updateHtmlTitle, updateDashboardText, updateInModerationText, adminTitle = document.title,
15 isDashboard = $('#dashboard_right_now').length,
16 titleDiv, titleRegEx,
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 */
29 getCount = function(el) {
30 var n = parseInt( el.html().replace(/[^0-9]+/g, ''), 10 );
31 if ( isNaN(n) ) {
32 return 0;
33 }
34 return n;
35 };
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 */
48 updateCount = function(el, n) {
49 var n1 = '';
50 if ( isNaN(n) ) {
51 return;
52 }
53 n = n < 1 ? '0' : n.toString();
54 if ( n.length > 3 ) {
55 while ( n.length > 3 ) {
56 n1 = thousandsSeparator + n.substr(n.length - 3) + n1;
57 n = n.substr(0, n.length - 3);
58 }
59 n = n + n1;
60 }
61 el.html(n);
62 };
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 */
75 updateApproved = function( diff, commentPostId ) {
76 var postSelector = '.post-com-count-' + commentPostId,
77 noClass = 'comment-count-no-comments',
78 approvedClass = 'comment-count-approved',
79 approved,
80 noComments;
81
82 updateCountText( 'span.approved-count', diff );
83
84 if ( ! commentPostId ) {
85 return;
86 }
87
88 // Cache selectors to not get duplicates.
89 approved = $( 'span.' + approvedClass, postSelector );
90 noComments = $( 'span.' + noClass, postSelector );
91
92 approved.each(function() {
93 var a = $(this), n = getCount(a) + diff;
94 if ( n < 1 )
95 n = 0;
96
97 if ( 0 === n ) {
98 a.removeClass( approvedClass ).addClass( noClass );
99 } else {
100 a.addClass( approvedClass ).removeClass( noClass );
101 }
102 updateCount( a, n );
103 });
104
105 noComments.each(function() {
106 var a = $(this);
107 if ( diff > 0 ) {
108 a.removeClass( noClass ).addClass( approvedClass );
109 } else {
110 a.addClass( noClass ).removeClass( approvedClass );
111 }
112 updateCount( a, diff );
113 });
114 };
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 */
128 updateCountText = function( selector, diff ) {
129 $( selector ).each(function() {
130 var a = $(this), n = getCount(a) + diff;
131 if ( n < 1 ) {
132 n = 0;
133 }
134 updateCount( a, n );
135 });
136 };
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 */
149 updateDashboardText = function( response ) {
150 if ( ! isDashboard || ! response || ! response.i18n_comments_text ) {
151 return;
152 }
153
154 $( '.comment-count a', '#dashboard_right_now' ).text( response.i18n_comments_text );
155 };
156
157 /**
158 * Updates the "comments in moderation" text across the UI.
159 *
160 * @since 5.2.0
161 *
162 * @param {Object} response Ajax response from the server that includes a
163 * translated "comments in moderation" message.
164 *
165 * @return {void}
166 */
167 updateInModerationText = function( response ) {
168 if ( ! response || ! response.i18n_moderation_text ) {
169 return;
170 }
171
172 // Update the "comment in moderation" text across the UI.
173 $( '.comments-in-moderation-text' ).text( response.i18n_moderation_text );
174 // Hide the "comment in moderation" text in the Dashboard "At a Glance" widget.
175 if ( isDashboard && response.in_moderation ) {
176 $( '.comment-mod-count', '#dashboard_right_now' )
177 [ response.in_moderation > 0 ? 'removeClass' : 'addClass' ]( 'hidden' );
178 }
179 };
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 */
192 updateHtmlTitle = function( diff ) {
193 var newTitle, regExMatch, titleCount, commentFrag;
194
195 /* translators: %s: Comments count. */
196 titleRegEx = titleRegEx || new RegExp( __( 'Comments (%s)' ).replace( '%s', '\\([0-9' + thousandsSeparator + ']+\\)' ) + '?' );
197 // Count funcs operate on a $'d element.
198 titleDiv = titleDiv || $( '<div />' );
199 newTitle = adminTitle;
200
201 commentFrag = titleRegEx.exec( document.title );
202 if ( commentFrag ) {
203 commentFrag = commentFrag[0];
204 titleDiv.html( commentFrag );
205 titleCount = getCount( titleDiv ) + diff;
206 } else {
207 titleDiv.html( 0 );
208 titleCount = diff;
209 }
210
211 if ( titleCount >= 1 ) {
212 updateCount( titleDiv, titleCount );
213 regExMatch = titleRegEx.exec( document.title );
214 if ( regExMatch ) {
215 /* translators: %s: Comments count. */
216 newTitle = document.title.replace( regExMatch[0], __( 'Comments (%s)' ).replace( '%s', titleDiv.text() ) + ' ' );
217 }
218 } else {
219 regExMatch = titleRegEx.exec( newTitle );
220 if ( regExMatch ) {
221 newTitle = newTitle.replace( regExMatch[0], __( 'Comments' ) );
222 }
223 }
224 document.title = newTitle;
225 };
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 */
238 updatePending = function( diff, commentPostId ) {
239 var postSelector = '.post-com-count-' + commentPostId,
240 noClass = 'comment-count-no-pending',
241 noParentClass = 'post-com-count-no-pending',
242 pendingClass = 'comment-count-pending',
243 pending,
244 noPending;
245
246 if ( ! isDashboard ) {
247 updateHtmlTitle( diff );
248 }
249
250 $( 'span.pending-count' ).each(function() {
251 var a = $(this), n = getCount(a) + diff;
252 if ( n < 1 )
253 n = 0;
254 a.closest('.awaiting-mod')[ 0 === n ? 'addClass' : 'removeClass' ]('count-0');
255 updateCount( a, n );
256 });
257
258 if ( ! commentPostId ) {
259 return;
260 }
261
262 // Cache selectors to not get dupes.
263 pending = $( 'span.' + pendingClass, postSelector );
264 noPending = $( 'span.' + noClass, postSelector );
265
266 pending.each(function() {
267 var a = $(this), n = getCount(a) + diff;
268 if ( n < 1 )
269 n = 0;
270
271 if ( 0 === n ) {
272 a.parent().addClass( noParentClass );
273 a.removeClass( pendingClass ).addClass( noClass );
274 } else {
275 a.parent().removeClass( noParentClass );
276 a.addClass( pendingClass ).removeClass( noClass );
277 }
278 updateCount( a, n );
279 });
280
281 noPending.each(function() {
282 var a = $(this);
283 if ( diff > 0 ) {
284 a.parent().removeClass( noParentClass );
285 a.removeClass( noClass ).addClass( pendingClass );
286 } else {
287 a.parent().addClass( noParentClass );
288 a.addClass( noClass ).removeClass( pendingClass );
289 }
290 updateCount( a, diff );
291 });
292 };
293
294/**
295 * Initializes the comments list.
296 *
297 * @since 4.4.0
298 *
299 * @global
300 *
301 * @return {void}
302 */
303window.setCommentsList = function() {
304 var totalInput, perPageInput, pageInput, dimAfter, delBefore, updateTotalCount, delAfter, refillTheExtraList, diff,
305 lastConfidentTime = 0;
306
307 totalInput = $('input[name="_total"]', '#comments-form');
308 perPageInput = $('input[name="_per_page"]', '#comments-form');
309 pageInput = $('input[name="_page"]', '#comments-form');
310
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 */
331 updateTotalCount = function( total, time, setConfidentTime ) {
332 if ( time < lastConfidentTime )
333 return;
334
335 if ( setConfidentTime )
336 lastConfidentTime = time;
337
338 totalInput.val( total.toString() );
339 };
340
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 */
352 dimAfter = function( r, settings ) {
353 var editRow, replyID, replyButton, response,
354 c = $( '#' + settings.element );
355
356 if ( true !== settings.parsed ) {
357 response = settings.parsed.responses[0];
358 }
359
360 editRow = $('#replyrow');
361 replyID = $('#comment_ID', editRow).val();
362 replyButton = $('#replybtn', editRow);
363
364 if ( c.is('.unapproved') ) {
365 if ( settings.data.id == replyID )
366 replyButton.text( __( 'Approve and Reply' ) );
367
368 c.find( '.row-actions span.view' ).addClass( 'hidden' ).end()
369 .find( 'div.comment_status' ).html( '0' );
370
371 } else {
372 if ( settings.data.id == replyID )
373 replyButton.text( __( 'Reply' ) );
374
375 c.find( '.row-actions span.view' ).removeClass( 'hidden' ).end()
376 .find( 'div.comment_status' ).html( '1' );
377 }
378
379 diff = $('#' + settings.element).is('.' + settings.dimClass) ? 1 : -1;
380 if ( response ) {
381 updateDashboardText( response.supplemental );
382 updateInModerationText( response.supplemental );
383 updatePending( diff, response.supplemental.postId );
384 updateApproved( -1 * diff, response.supplemental.postId );
385 } else {
386 updatePending( diff );
387 updateApproved( -1 * diff );
388 }
389 };
390
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 */
404 delBefore = function( settings, list ) {
405 var note, id, el, n, h, a, author,
406 action = false,
407 wpListsData = $( settings.target ).attr( 'data-wp-lists' );
408
409 settings.data._total = totalInput.val() || 0;
410 settings.data._per_page = perPageInput.val() || 0;
411 settings.data._page = pageInput.val() || 0;
412 settings.data._url = document.location.href;
413 settings.data.comment_status = $('input[name="comment_status"]', '#comments-form').val();
414
415 if ( wpListsData.indexOf(':trash=1') != -1 )
416 action = 'trash';
417 else if ( wpListsData.indexOf(':spam=1') != -1 )
418 action = 'spam';
419
420 if ( action ) {
421 id = wpListsData.replace(/.*?comment-([0-9]+).*/, '$1');
422 el = $('#comment-' + id);
423 note = $('#' + action + '-undo-holder').html();
424
425 el.find('.check-column :checkbox').prop('checked', false); // Uncheck the row so as not to be affected by Bulk Edits.
426
427 if ( el.siblings('#replyrow').length && commentReply.cid == id )
428 commentReply.close();
429
430 if ( el.is('tr') ) {
431 n = el.children(':visible').length;
432 author = $('.author strong', el).text();
433 h = $('<tr id="undo-' + id + '" class="undo un' + action + '" style="display:none;"><td colspan="' + n + '">' + note + '</td></tr>');
434 } else {
435 author = $('.comment-author', el).text();
436 h = $('<div id="undo-' + id + '" style="display:none;" class="undo un' + action + '">' + note + '</div>');
437 }
438
439 el.before(h);
440
441 $('strong', '#undo-' + id).text(author);
442 a = $('.undo a', '#undo-' + id);
443 a.attr('href', 'comment.php?action=un' + action + 'comment&c=' + id + '&_wpnonce=' + settings.data._ajax_nonce);
444 a.attr('data-wp-lists', 'delete:the-comment-list:comment-' + id + '::un' + action + '=1');
445 a.attr('class', 'vim-z vim-destructive aria-button-if-js');
446 $('.avatar', el).first().clone().prependTo('#undo-' + id + ' .' + action + '-undo-inside');
447
448 a.on( 'click', function( e ){
449 e.preventDefault();
450 e.stopPropagation(); // Ticket #35904.
451 list.wpList.del(this);
452 $('#undo-' + id).css( {backgroundColor:'#ceb'} ).fadeOut(350, function(){
453 $(this).remove();
454 $('#comment-' + id).css('backgroundColor', '').fadeIn(300, function(){ $(this).show(); });
455 });
456 });
457 }
458
459 return settings;
460 };
461
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 */
477 delAfter = function( r, settings ) {
478 var total_items_i18n, total, animated, animatedCallback,
479 response = true === settings.parsed ? {} : settings.parsed.responses[0],
480 commentStatus = true === settings.parsed ? '' : response.supplemental.status,
481 commentPostId = true === settings.parsed ? '' : response.supplemental.postId,
482 newTotal = true === settings.parsed ? '' : response.supplemental,
483
484 targetParent = $( settings.target ).parent(),
485 commentRow = $('#' + settings.element),
486
487 spamDiff, trashDiff, pendingDiff, approvedDiff,
488
489 /*
490 * As `wpList` toggles only the `unapproved` class, the approved comment
491 * rows can have both the `approved` and `unapproved` classes.
492 */
493 approved = commentRow.hasClass( 'approved' ) && ! commentRow.hasClass( 'unapproved' ),
494 unapproved = commentRow.hasClass( 'unapproved' ),
495 spammed = commentRow.hasClass( 'spam' ),
496 trashed = commentRow.hasClass( 'trash' ),
497 undoing = false; // Ticket #35904.
498
499 updateDashboardText( newTotal );
500 updateInModerationText( newTotal );
501
502 /*
503 * The order of these checks is important.
504 * .unspam can also have .approve or .unapprove.
505 * .untrash can also have .approve or .unapprove.
506 */
507
508 if ( targetParent.is( 'span.undo' ) ) {
509 // The comment was spammed.
510 if ( targetParent.hasClass( 'unspam' ) ) {
511 spamDiff = -1;
512
513 if ( 'trash' === commentStatus ) {
514 trashDiff = 1;
515 } else if ( '1' === commentStatus ) {
516 approvedDiff = 1;
517 } else if ( '0' === commentStatus ) {
518 pendingDiff = 1;
519 }
520
521 // The comment was trashed.
522 } else if ( targetParent.hasClass( 'untrash' ) ) {
523 trashDiff = -1;
524
525 if ( 'spam' === commentStatus ) {
526 spamDiff = 1;
527 } else if ( '1' === commentStatus ) {
528 approvedDiff = 1;
529 } else if ( '0' === commentStatus ) {
530 pendingDiff = 1;
531 }
532 }
533
534 undoing = true;
535
536 // User clicked "Spam".
537 } else if ( targetParent.is( 'span.spam' ) ) {
538 // The comment is currently approved.
539 if ( approved ) {
540 approvedDiff = -1;
541 // The comment is currently pending.
542 } else if ( unapproved ) {
543 pendingDiff = -1;
544 // The comment was in the Trash.
545 } else if ( trashed ) {
546 trashDiff = -1;
547 }
548 // You can't spam an item on the Spam screen.
549 spamDiff = 1;
550
551 // User clicked "Unspam".
552 } else if ( targetParent.is( 'span.unspam' ) ) {
553 if ( approved ) {
554 pendingDiff = 1;
555 } else if ( unapproved ) {
556 approvedDiff = 1;
557 } else if ( trashed ) {
558 // The comment was previously approved.
559 if ( targetParent.hasClass( 'approve' ) ) {
560 approvedDiff = 1;
561 // The comment was previously pending.
562 } else if ( targetParent.hasClass( 'unapprove' ) ) {
563 pendingDiff = 1;
564 }
565 } else if ( spammed ) {
566 if ( targetParent.hasClass( 'approve' ) ) {
567 approvedDiff = 1;
568
569 } else if ( targetParent.hasClass( 'unapprove' ) ) {
570 pendingDiff = 1;
571 }
572 }
573 // You can unspam an item on the Spam screen.
574 spamDiff = -1;
575
576 // User clicked "Trash".
577 } else if ( targetParent.is( 'span.trash' ) ) {
578 if ( approved ) {
579 approvedDiff = -1;
580 } else if ( unapproved ) {
581 pendingDiff = -1;
582 // The comment was in the spam queue.
583 } else if ( spammed ) {
584 spamDiff = -1;
585 }
586 // You can't trash an item on the Trash screen.
587 trashDiff = 1;
588
589 // User clicked "Restore".
590 } else if ( targetParent.is( 'span.untrash' ) ) {
591 if ( approved ) {
592 pendingDiff = 1;
593 } else if ( unapproved ) {
594 approvedDiff = 1;
595 } else if ( trashed ) {
596 if ( targetParent.hasClass( 'approve' ) ) {
597 approvedDiff = 1;
598 } else if ( targetParent.hasClass( 'unapprove' ) ) {
599 pendingDiff = 1;
600 }
601 }
602 // You can't go from Trash to Spam.
603 // You can untrash on the Trash screen.
604 trashDiff = -1;
605
606 // User clicked "Approve".
607 } else if ( targetParent.is( 'span.approve:not(.unspam):not(.untrash)' ) ) {
608 approvedDiff = 1;
609 pendingDiff = -1;
610
611 // User clicked "Unapprove".
612 } else if ( targetParent.is( 'span.unapprove:not(.unspam):not(.untrash)' ) ) {
613 approvedDiff = -1;
614 pendingDiff = 1;
615
616 // User clicked "Delete Permanently".
617 } else if ( targetParent.is( 'span.delete' ) ) {
618 if ( spammed ) {
619 spamDiff = -1;
620 } else if ( trashed ) {
621 trashDiff = -1;
622 }
623 }
624
625 if ( pendingDiff ) {
626 updatePending( pendingDiff, commentPostId );
627 updateCountText( 'span.all-count', pendingDiff );
628 }
629
630 if ( approvedDiff ) {
631 updateApproved( approvedDiff, commentPostId );
632 updateCountText( 'span.all-count', approvedDiff );
633 }
634
635 if ( spamDiff ) {
636 updateCountText( 'span.spam-count', spamDiff );
637 }
638
639 if ( trashDiff ) {
640 updateCountText( 'span.trash-count', trashDiff );
641 }
642
643 if (
644 ( ( 'trash' === settings.data.comment_status ) && !getCount( $( 'span.trash-count' ) ) ) ||
645 ( ( 'spam' === settings.data.comment_status ) && !getCount( $( 'span.spam-count' ) ) )
646 ) {
647 $( '#delete_all' ).hide();
648 }
649
650 if ( ! isDashboard ) {
651 total = totalInput.val() ? parseInt( totalInput.val(), 10 ) : 0;
652 if ( $(settings.target).parent().is('span.undo') )
653 total++;
654 else
655 total--;
656
657 if ( total < 0 )
658 total = 0;
659
660 if ( 'object' === typeof r ) {
661 if ( response.supplemental.total_items_i18n && lastConfidentTime < response.supplemental.time ) {
662 total_items_i18n = response.supplemental.total_items_i18n || '';
663 if ( total_items_i18n ) {
664 $('.displaying-num').text( total_items_i18n.replace( '&nbsp;', String.fromCharCode( 160 ) ) );
665 $('.total-pages').text( response.supplemental.total_pages_i18n.replace( '&nbsp;', String.fromCharCode( 160 ) ) );
666 $('.tablenav-pages').find('.next-page, .last-page').toggleClass('disabled', response.supplemental.total_pages == $('.current-page').val());
667 }
668 updateTotalCount( total, response.supplemental.time, true );
669 } else if ( response.supplemental.time ) {
670 updateTotalCount( total, response.supplemental.time, false );
671 }
672 } else {
673 updateTotalCount( total, r, false );
674 }
675 }
676
677 if ( ! theExtraList || theExtraList.length === 0 || theExtraList.children().length === 0 || undoing ) {
678 return;
679 }
680
681 theList.get(0).wpList.add( theExtraList.children( ':eq(0):not(.no-items)' ).remove().clone() );
682
683 refillTheExtraList();
684
685 animated = $( ':animated', '#the-comment-list' );
686 animatedCallback = function() {
687 if ( ! $( '#the-comment-list tr:visible' ).length ) {
688 theList.get(0).wpList.add( theExtraList.find( '.no-items' ).clone() );
689 }
690 };
691
692 if ( animated.length ) {
693 animated.promise().done( animatedCallback );
694 } else {
695 animatedCallback();
696 }
697 };
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 */
709 refillTheExtraList = function(ev) {
710 var args = $.query.get(), total_pages = $('.total-pages').text(), per_page = $('input[name="_per_page"]', '#comments-form').val();
711
712 if (! args.paged)
713 args.paged = 1;
714
715 if (args.paged > total_pages) {
716 return;
717 }
718
719 if (ev) {
720 theExtraList.empty();
721 args.number = Math.min(8, per_page); // See WP_Comments_List_Table::prepare_items() in class-wp-comments-list-table.php.
722 } else {
723 args.number = 1;
724 args.offset = Math.min(8, per_page) - 1; // Fetch only the next item on the extra list.
725 }
726
727 args.no_placeholder = true;
728
729 args.paged ++;
730
731 // $.query.get() needs some correction to be sent into an Ajax request.
732 if ( true === args.comment_type )
733 args.comment_type = '';
734
735 args = $.extend(args, {
736 'action': 'fetch-list',
737 'list_args': list_args,
738 '_ajax_fetch_list_nonce': $('#_ajax_fetch_list_nonce').val()
739 });
740
741 $.ajax({
742 url: ajaxurl,
743 global: false,
744 dataType: 'json',
745 data: args,
746 success: function(response) {
747 theExtraList.get(0).wpList.add( response.rows );
748 }
749 });
750 };
751
752 /**
753 * Globally available jQuery object referring to the extra comments list.
754 *
755 * @global
756 */
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 */
764 window.theList = $('#the-comment-list').wpList( { alt: '', delBefore: delBefore, dimAfter: dimAfter, delAfter: delAfter, addColor: 'none' } )
765 .on('wpListDelEnd', function(e, s){
766 var wpListsData = $(s.target).attr('data-wp-lists'), id = s.element.replace(/[^0-9]+/g, '');
767
768 if ( wpListsData.indexOf(':trash=1') != -1 || wpListsData.indexOf(':spam=1') != -1 )
769 $('#undo-' + id).fadeIn(300, function(){ $(this).show(); });
770 });
771};
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 */
781window.commentReply = {
782 cid : '',
783 act : '',
784 originalContent : '',
785
786 /**
787 * Initializes the comment reply functionality.
788 *
789 * @since 2.7.0
790 *
791 * @memberof commentReply
792 */
793 init : function() {
794 var row = $('#replyrow');
795
796 $( '.cancel', row ).on( 'click', function() { return commentReply.revert(); } );
797 $( '.save', row ).on( 'click', function() { return commentReply.send(); } );
798 $( 'input#author-name, input#author-email, input#author-url', row ).on( 'keypress', function( e ) {
799 if ( e.which == 13 ) {
800 commentReply.send();
801 e.preventDefault();
802 return false;
803 }
804 });
805
806 // Add events.
807 $('#the-comment-list .column-comment > p').on( 'dblclick', function(){
808 commentReply.toggle($(this).parent());
809 });
810
811 $('#doaction, #post-query-submit').on( 'click', function(){
812 if ( $('#the-comment-list #replyrow').length > 0 )
813 commentReply.close();
814 });
815
816 this.comments_listing = $('#comments-form > input[name="comment_status"]').val() || '';
817 },
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 */
832 addEvents : function(r) {
833 r.each(function() {
834 $(this).find('.column-comment > p').on( 'dblclick', function(){
835 commentReply.toggle($(this).parent());
836 });
837 });
838 },
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 */
851 toggle : function(el) {
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.' ) ) ) ) {
853 $( el ).find( 'button.vim-q' ).trigger( 'click' );
854 }
855 },
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 */
866 revert : function() {
867
868 if ( $('#the-comment-list #replyrow').length < 1 )
869 return false;
870
871 $('#replyrow').fadeOut('fast', function(){
872 commentReply.close();
873 });
874 },
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 */
885 close : function() {
886 var commentRow = $(),
887 replyRow = $( '#replyrow' );
888
889 // Return if the replyrow is not showing.
890 if ( replyRow.parent().is( '#com-reply' ) ) {
891 return;
892 }
893
894 if ( this.cid ) {
895 commentRow = $( '#comment-' + this.cid );
896 }
897
898 /*
899 * When closing the Quick Edit form, show the comment row and move focus
900 * back to the Quick Edit button.
901 */
902 if ( 'edit-comment' === this.act ) {
903 commentRow.fadeIn( 300, function() {
904 commentRow
905 .show()
906 .find( '.vim-q' )
907 .attr( 'aria-expanded', 'false' )
908 .trigger( 'focus' );
909 } ).css( 'backgroundColor', '' );
910 }
911
912 // When closing the Reply form, move focus back to the Reply button.
913 if ( 'replyto-comment' === this.act ) {
914 commentRow.find( '.vim-r' )
915 .attr( 'aria-expanded', 'false' )
916 .trigger( 'focus' );
917 }
918
919 // Reset the Quicktags buttons.
920 if ( typeof QTags != 'undefined' )
921 QTags.closeAllTags('replycontent');
922
923 $('#add-new-comment').css('display', '');
924
925 replyRow.hide();
926 $( '#com-reply' ).append( replyRow );
927 $('#replycontent').css('height', '').val('');
928 $('#edithead input').val('');
929 $( '.notice-error', replyRow )
930 .addClass( 'hidden' )
931 .find( '.error' ).empty();
932 $( '.spinner', replyRow ).removeClass( 'is-active' );
933
934 this.cid = '';
935 this.originalContent = '';
936 },
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 */
951 open : function(comment_id, post_id, action) {
952 var editRow, rowData, act, replyButton, editHeight,
953 t = this,
954 c = $('#comment-' + comment_id),
955 h = c.height(),
956 colspanVal = 0;
957
958 if ( ! this.discardCommentChanges() ) {
959 return false;
960 }
961
962 t.close();
963 t.cid = comment_id;
964
965 editRow = $('#replyrow');
966 rowData = $('#inline-'+comment_id);
967 action = action || 'replyto';
968 act = 'edit' == action ? 'edit' : 'replyto';
969 act = t.act = act + '-comment';
970 t.originalContent = $('textarea.comment', rowData).val();
971 colspanVal = $( '> th:visible, > td:visible', c ).length;
972
973 // Make sure it's actually a table and there's a `colspan` value to apply.
974 if ( editRow.hasClass( 'inline-edit-row' ) && 0 !== colspanVal ) {
975 $( 'td', editRow ).attr( 'colspan', colspanVal );
976 }
977
978 $('#action', editRow).val(act);
979 $('#comment_post_ID', editRow).val(post_id);
980 $('#comment_ID', editRow).val(comment_id);
981
982 if ( action == 'edit' ) {
983 $( '#author-name', editRow ).val( $( 'div.author', rowData ).text() );
984 $('#author-email', editRow).val( $('div.author-email', rowData).text() );
985 $('#author-url', editRow).val( $('div.author-url', rowData).text() );
986 $('#status', editRow).val( $('div.comment_status', rowData).text() );
987 $('#replycontent', editRow).val( $('textarea.comment', rowData).val() );
988 $( '#edithead, #editlegend, #savebtn', editRow ).show();
989 $('#replyhead, #replybtn, #addhead, #addbtn', editRow).hide();
990
991 if ( h > 120 ) {
992 // Limit the maximum height when editing very long comments to make it more manageable.
993 // The textarea is resizable in most browsers, so the user can adjust it if needed.
994 editHeight = h > 500 ? 500 : h;
995 $('#replycontent', editRow).css('height', editHeight + 'px');
996 }
997
998 c.after( editRow ).fadeOut('fast', function(){
999 $('#replyrow').fadeIn(300, function(){ $(this).show(); });
1000 });
1001 } else if ( action == 'add' ) {
1002 $('#addhead, #addbtn', editRow).show();
1003 $( '#replyhead, #replybtn, #edithead, #editlegend, #savebtn', editRow ) .hide();
1004 $('#the-comment-list').prepend(editRow);
1005 $('#replyrow').fadeIn(300);
1006 } else {
1007 replyButton = $('#replybtn', editRow);
1008 $( '#edithead, #editlegend, #savebtn, #addhead, #addbtn', editRow ).hide();
1009 $('#replyhead, #replybtn', editRow).show();
1010 c.after(editRow);
1011
1012 if ( c.hasClass('unapproved') ) {
1013 replyButton.text( __( 'Approve and Reply' ) );
1014 } else {
1015 replyButton.text( __( 'Reply' ) );
1016 }
1017
1018 $('#replyrow').fadeIn(300, function(){ $(this).show(); });
1019 }
1020
1021 setTimeout(function() {
1022 var rtop, rbottom, scrollTop, vp, scrollBottom,
1023 isComposing = false,
1024 isContextMenuOpen = false;
1025
1026 rtop = $('#replyrow').offset().top;
1027 rbottom = rtop + $('#replyrow').height();
1028 scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1029 vp = document.documentElement.clientHeight || window.innerHeight || 0;
1030 scrollBottom = scrollTop + vp;
1031
1032 if ( scrollBottom - 20 < rbottom )
1033 window.scroll(0, rbottom - vp + 35);
1034 else if ( rtop - 20 < scrollTop )
1035 window.scroll(0, rtop - 35);
1036
1037 $( '#replycontent' )
1038 .trigger( 'focus' )
1039 .on( 'contextmenu keydown', function ( e ) {
1040 // Check if the context menu is open and set state.
1041 if ( e.type === 'contextmenu' ) {
1042 isContextMenuOpen = true;
1043 }
1044
1045 // Update the context menu state if the Escape key is pressed.
1046 if ( e.type === 'keydown' && e.which === 27 && isContextMenuOpen ) {
1047 isContextMenuOpen = false;
1048 }
1049 } )
1050 .on( 'keyup', function( e ) {
1051 // Close on Escape unless Input Method Editors (IMEs) are in use or the context menu is open.
1052 if ( e.which === 27 && ! isComposing && ! isContextMenuOpen ) {
1053 commentReply.revert();
1054 }
1055 } )
1056 .on( 'compositionstart', function() {
1057 isComposing = true;
1058 } );
1059 }, 600);
1060
1061 return false;
1062 },
1063
1064 /**
1065 * Submits the comment quick edit or reply form.
1066 *
1067 * @since 2.7.0
1068 *
1069 * @memberof commentReply
1070 *
1071 * @return {void}
1072 */
1073 send : function() {
1074 var post = {},
1075 $errorNotice = $( '#replysubmit .error-notice' );
1076
1077 $errorNotice.addClass( 'hidden' );
1078 $( '#replysubmit .spinner' ).addClass( 'is-active' );
1079
1080 $('#replyrow input').not(':button').each(function() {
1081 var t = $(this);
1082 post[ t.attr('name') ] = t.val();
1083 });
1084
1085 post.content = $('#replycontent').val();
1086 post.id = post.comment_post_ID;
1087 post.comments_listing = this.comments_listing;
1088 post.p = $('[name="p"]').val();
1089
1090 if ( $('#comment-' + $('#comment_ID').val()).hasClass('unapproved') )
1091 post.approve_parent = 1;
1092
1093 $.ajax({
1094 type : 'POST',
1095 url : ajaxurl,
1096 data : post,
1097 success : function(x) { commentReply.show(x); },
1098 error : function(r) { commentReply.error(r); }
1099 });
1100 },
1101
1102 /**
1103 * Shows the new or updated comment or reply.
1104 *
1105 * This function needs to be passed the ajax result as received from the server.
1106 * It will handle the response and show the comment that has just been saved to
1107 * the server.
1108 *
1109 * @since 2.7.0
1110 *
1111 * @memberof commentReply
1112 *
1113 * @param {Object} xml Ajax response object.
1114 *
1115 * @return {void}
1116 */
1117 show : function(xml) {
1118 var t = this, r, c, id, bg, pid;
1119
1120 if ( typeof(xml) == 'string' ) {
1121 t.error({'responseText': xml});
1122 return false;
1123 }
1124
1125 r = wpAjax.parseAjaxResponse(xml);
1126 if ( r.errors ) {
1127 t.error({'responseText': wpAjax.broken});
1128 return false;
1129 }
1130
1131 t.revert();
1132
1133 r = r.responses[0];
1134 id = '#comment-' + r.id;
1135
1136 if ( 'edit-comment' == t.act )
1137 $(id).remove();
1138
1139 if ( r.supplemental.parent_approved ) {
1140 pid = $('#comment-' + r.supplemental.parent_approved);
1141 updatePending( -1, r.supplemental.parent_post_id );
1142
1143 if ( this.comments_listing == 'moderated' ) {
1144 pid.animate( { 'backgroundColor':'#CCEEBB' }, 400, function(){
1145 pid.fadeOut();
1146 });
1147 return;
1148 }
1149 }
1150
1151 if ( r.supplemental.i18n_comments_text ) {
1152 updateDashboardText( r.supplemental );
1153 updateInModerationText( r.supplemental );
1154 updateApproved( 1, r.supplemental.parent_post_id );
1155 updateCountText( 'span.all-count', 1 );
1156 }
1157
1158 r.data = r.data || '';
1159 c = r.data.toString().trim(); // Trim leading whitespaces.
1160 $(c).hide();
1161 $('#replyrow').after(c);
1162
1163 id = $(id);
1164 t.addEvents(id);
1165 bg = id.hasClass('unapproved') ? '#FFFFE0' : id.closest('.widefat, .postbox').css('backgroundColor');
1166
1167 id.animate( { 'backgroundColor':'#CCEEBB' }, 300 )
1168 .animate( { 'backgroundColor': bg }, 300, function() {
1169 if ( pid && pid.length ) {
1170 pid.animate( { 'backgroundColor':'#CCEEBB' }, 300 )
1171 .animate( { 'backgroundColor': bg }, 300 )
1172 .removeClass('unapproved').addClass('approved')
1173 .find('div.comment_status').html('1');
1174 }
1175 });
1176
1177 },
1178
1179 /**
1180 * Shows an error for the failed comment update or reply.
1181 *
1182 * @since 2.7.0
1183 *
1184 * @memberof commentReply
1185 *
1186 * @param {string} r The Ajax response.
1187 *
1188 * @return {void}
1189 */
1190 error : function(r) {
1191 var er = r.statusText,
1192 $errorNotice = $( '#replysubmit .notice-error' ),
1193 $error = $errorNotice.find( '.error' );
1194
1195 $( '#replysubmit .spinner' ).removeClass( 'is-active' );
1196
1197 if ( r.responseText )
1198 er = r.responseText.replace( /<.[^<>]*?>/g, '' );
1199
1200 if ( er ) {
1201 $errorNotice.removeClass( 'hidden' );
1202 $error.html( er );
1203 wp.a11y.speak( er );
1204 }
1205 },
1206
1207 /**
1208 * Opens the add comments form in the comments metabox on the post edit page.
1209 *
1210 * @since 3.4.0
1211 *
1212 * @memberof commentReply
1213 *
1214 * @param {number} post_id The post ID.
1215 *
1216 * @return {void}
1217 */
1218 addcomment: function(post_id) {
1219 var t = this;
1220
1221 $('#add-new-comment').fadeOut(200, function(){
1222 t.open(0, post_id, 'add');
1223 $('table.comments-box').css('display', '');
1224 $('#no-comments').remove();
1225 });
1226 },
1227
1228 /**
1229 * Alert the user if they have unsaved changes on a comment that will be lost if
1230 * they proceed with the intended action.
1231 *
1232 * @since 4.6.0
1233 *
1234 * @memberof commentReply
1235 *
1236 * @return {boolean} Whether it is safe the continue with the intended action.
1237 */
1238 discardCommentChanges: function() {
1239 var editRow = $( '#replyrow' );
1240
1241 if ( '' === $( '#replycontent', editRow ).val() || this.originalContent === $( '#replycontent', editRow ).val() ) {
1242 return true;
1243 }
1244
1245 return window.confirm( __( 'Are you sure you want to do this?\nThe comment changes you made will be lost.' ) );
1246 }
1247};
1248
1249$( function(){
1250 var make_hotkeys_redirect, edit_comment, toggle_all, make_bulk;
1251
1252 setCommentsList();
1253 commentReply.init();
1254
1255 $(document).on( 'click', 'span.delete a.delete', function( e ) {
1256 e.preventDefault();
1257 });
1258
1259 if ( typeof $.table_hotkeys != 'undefined' ) {
1260 /**
1261 * Creates a function that navigates to a previous or next page.
1262 *
1263 * @since 2.7.0
1264 * @access private
1265 *
1266 * @param {string} which What page to navigate to: either next or prev.
1267 *
1268 * @return {Function} The function that executes the navigation.
1269 */
1270 make_hotkeys_redirect = function(which) {
1271 return function() {
1272 var first_last, l;
1273
1274 first_last = 'next' == which? 'first' : 'last';
1275 l = $('.tablenav-pages .'+which+'-page:not(.disabled)');
1276 if (l.length)
1277 window.location = l[0].href.replace(/\&hotkeys_highlight_(first|last)=1/g, '')+'&hotkeys_highlight_'+first_last+'=1';
1278 };
1279 };
1280
1281 /**
1282 * Navigates to the edit page for the selected comment.
1283 *
1284 * @since 2.7.0
1285 * @access private
1286 *
1287 * @param {Object} event The event that triggered this action.
1288 * @param {Object} current_row A jQuery object of the selected row.
1289 *
1290 * @return {void}
1291 */
1292 edit_comment = function(event, current_row) {
1293 window.location = $('span.edit a', current_row).attr('href');
1294 };
1295
1296 /**
1297 * Toggles all comments on the screen, for bulk actions.
1298 *
1299 * @since 2.7.0
1300 * @access private
1301 *
1302 * @return {void}
1303 */
1304 toggle_all = function() {
1305 $('#cb-select-all-1').data( 'wp-toggle', 1 ).trigger( 'click' ).removeData( 'wp-toggle' );
1306 };
1307
1308 /**
1309 * Creates a bulk action function that is executed on all selected comments.
1310 *
1311 * @since 2.7.0
1312 * @access private
1313 *
1314 * @param {string} value The name of the action to execute.
1315 *
1316 * @return {Function} The function that executes the bulk action.
1317 */
1318 make_bulk = function(value) {
1319 return function() {
1320 var scope = $('select[name="action"]');
1321 $('option[value="' + value + '"]', scope).prop('selected', true);
1322 $('#doaction').trigger( 'click' );
1323 };
1324 };
1325
1326 $.table_hotkeys(
1327 $('table.widefat'),
1328 [
1329 'a', 'u', 's', 'd', 'r', 'q', 'z',
1330 ['e', edit_comment],
1331 ['shift+x', toggle_all],
1332 ['shift+a', make_bulk('approve')],
1333 ['shift+s', make_bulk('spam')],
1334 ['shift+d', make_bulk('delete')],
1335 ['shift+t', make_bulk('trash')],
1336 ['shift+z', make_bulk('untrash')],
1337 ['shift+u', make_bulk('unapprove')]
1338 ],
1339 {
1340 highlight_first: adminCommentsSettings.hotkeys_highlight_first,
1341 highlight_last: adminCommentsSettings.hotkeys_highlight_last,
1342 prev_page_link_cb: make_hotkeys_redirect('prev'),
1343 next_page_link_cb: make_hotkeys_redirect('next'),
1344 hotkeys_opts: {
1345 disableInInput: true,
1346 type: 'keypress',
1347 noDisable: '.check-column input[type="checkbox"]'
1348 },
1349 cycle_expr: '#the-comment-list tr',
1350 start_row_index: 0
1351 }
1352 );
1353 }
1354
1355 // Quick Edit and Reply have an inline comment editor.
1356 $( '#the-comment-list' ).on( 'click', '.comment-inline', function() {
1357 var $el = $( this ),
1358 action = 'replyto';
1359
1360 if ( 'undefined' !== typeof $el.data( 'action' ) ) {
1361 action = $el.data( 'action' );
1362 }
1363
1364 $( this ).attr( 'aria-expanded', 'true' );
1365 commentReply.open( $el.data( 'commentId' ), $el.data( 'postId' ), action );
1366 } );
1367});
1368
1369})(jQuery);
1370
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1