3 * Attaches behaviors for the Comment module's "X new comments" link.
5 * May only be loaded for authenticated users, with the History module
9 (function ($, Drupal, drupalSettings) {
11 * Render "X new comments" links wherever necessary.
13 * @type {Drupal~behavior}
15 * @prop {Drupal~behaviorAttach} attach
16 * Attaches new comment links behavior.
18 Drupal.behaviors.nodeNewCommentsLink = {
20 // Collect all "X new comments" node link placeholders (and their
21 // corresponding node IDs) newer than 30 days ago that have not already
22 // been read after their last comment timestamp.
24 const $placeholders = $(context)
25 .find('[data-history-node-last-comment-timestamp]')
28 const $placeholder = $(this);
29 const lastCommentTimestamp = parseInt($placeholder.attr('data-history-node-last-comment-timestamp'), 10);
30 const nodeID = $placeholder.closest('[data-history-node-id]').attr('data-history-node-id');
31 if (Drupal.history.needsServerCheck(nodeID, lastCommentTimestamp)) {
33 // Hide this placeholder link until it is certain we'll need it.
38 // Remove this placeholder link from the DOM because we won't need
44 if ($placeholders.length === 0) {
48 // Perform an AJAX request to retrieve node read timestamps.
49 Drupal.history.fetchTimestamps(nodeIDs, () => {
50 processNodeNewCommentLinks($placeholders);
56 * Hides a "new comment" element.
58 * @param {jQuery} $placeholder
59 * The placeholder element of the new comment link.
62 * The placeholder element passed in as a parameter.
64 function hide($placeholder) {
66 // Find the parent <li>.
67 .closest('.comment-new-comments')
68 // Find the preceding <li>, if any, and give it the 'last' class.
69 .prev().addClass('last')
70 // Go back to the parent <li> and hide it.
75 * Removes a "new comment" element.
77 * @param {jQuery} $placeholder
78 * The placeholder element of the new comment link.
80 function remove($placeholder) {
81 hide($placeholder).remove();
85 * Shows a "new comment" element.
87 * @param {jQuery} $placeholder
88 * The placeholder element of the new comment link.
91 * The placeholder element passed in as a parameter.
93 function show($placeholder) {
95 // Find the parent <li>.
96 .closest('.comment-new-comments')
97 // Find the preceding <li>, if any, and remove its 'last' class, if any.
98 .prev().removeClass('last')
99 // Go back to the parent <li> and show it.
104 * Processes new comment links and adds appropriate text in relevant cases.
106 * @param {jQuery} $placeholders
107 * The placeholder elements of the current page.
109 function processNodeNewCommentLinks($placeholders) {
110 // Figure out which placeholders need the "x new comments" links.
111 const $placeholdersToUpdate = {};
112 let fieldName = 'comment';
114 $placeholders.each((index, placeholder) => {
115 $placeholder = $(placeholder);
116 const timestamp = parseInt($placeholder.attr('data-history-node-last-comment-timestamp'), 10);
117 fieldName = $placeholder.attr('data-history-node-field-name');
118 const nodeID = $placeholder.closest('[data-history-node-id]').attr('data-history-node-id');
119 const lastViewTimestamp = Drupal.history.getLastRead(nodeID);
121 // Queue this placeholder's "X new comments" link to be downloaded from
123 if (timestamp > lastViewTimestamp) {
124 $placeholdersToUpdate[nodeID] = $placeholder;
126 // No "X new comments" link necessary; remove it from the DOM.
128 remove($placeholder);
132 // Perform an AJAX request to retrieve node view timestamps.
133 const nodeIDs = Object.keys($placeholdersToUpdate);
134 if (nodeIDs.length === 0) {
139 * Renders the "X new comments" links.
141 * Either use the data embedded in the page or perform an AJAX request to
142 * retrieve the same data.
144 * @param {object} results
145 * Data about new comment links indexed by nodeID.
147 function render(results) {
148 for (const nodeID in results) {
149 if (results.hasOwnProperty(nodeID) && $placeholdersToUpdate.hasOwnProperty(nodeID)) {
150 $placeholdersToUpdate[nodeID]
151 .attr('href', results[nodeID].first_new_comment_link)
152 .text(Drupal.formatPlural(results[nodeID].new_comment_count, '1 new comment', '@count new comments'))
153 .removeClass('hidden');
154 show($placeholdersToUpdate[nodeID]);
159 if (drupalSettings.comment && drupalSettings.comment.newCommentsLinks) {
160 render(drupalSettings.comment.newCommentsLinks.node[fieldName]);
164 url: Drupal.url('comments/render_new_comments_node_links'),
166 data: { 'node_ids[]': nodeIDs, field_name: fieldName },
172 }(jQuery, Drupal, drupalSettings));